MythTV master
vorbisencoder.cpp
Go to the documentation of this file.
1// System
2#include <vorbis/vorbisfile.h>
3
4// C++
5#include <cstdio>
6#include <iostream>
7
8// Qt
9#include <QApplication>
10#include <QString>
11
12// MythTV
17
18// MythMusic
19#include "encoder.h"
20#include "vorbisencoder.h"
21
22
23static int write_page(ogg_page *page, FILE *fp)
24{
25 int written = fwrite(page->header, 1, page->header_len, fp);
26 written += fwrite(page->body, 1, page->body_len, fp);
27
28 return written;
29}
30
31VorbisEncoder::VorbisEncoder(const QString &outfile, int qualitylevel,
32 MusicMetadata *metadata) :
33 Encoder(outfile, qualitylevel, metadata)
34{
35 vorbis_comment_init(&m_vc);
36
37 vorbis_info_init(&m_vi);
38
39 ogg_packet_clear(&m_op);
40
41 float quality = 1.0;
42 if (qualitylevel == 0)
43 quality = 0.4;
44 if (qualitylevel == 1)
45 quality = 0.7;
46
47 int ret = vorbis_encode_setup_vbr(&m_vi, 2, 44100, quality);
48 if (ret)
49 {
50 LOG(VB_GENERAL, LOG_ERR, QString("Error initializing VORBIS encoder."
51 " Got return code: %1").arg(ret));
52 vorbis_info_clear(&m_vi);
53 return;
54 }
55
56 vorbis_encode_ctl(&m_vi, OV_ECTL_RATEMANAGE_SET, nullptr);
57 vorbis_encode_setup_init(&m_vi);
58 vorbis_analysis_init(&m_vd, &m_vi);
59 vorbis_block_init(&m_vd, &m_vb);
60
61 ogg_stream_init(&m_os, MythRandom());
62
63 ogg_packet header_main;
64 ogg_packet header_comments;
65 ogg_packet header_codebooks;
66
67 vorbis_analysis_headerout(&m_vd, &m_vc, &header_main, &header_comments,
68 &header_codebooks);
69
70 ogg_stream_packetin(&m_os, &header_main);
71 ogg_stream_packetin(&m_os, &header_comments);
72 ogg_stream_packetin(&m_os, &header_codebooks);
73
74 int result = 0;
75 while ((result = ogg_stream_flush(&m_os, &m_og)))
76 {
77 if (!result || !m_out)
78 break;
79 int ret2 = write_page(&m_og, m_out);
80 if (ret2 != m_og.header_len + m_og.body_len)
81 {
82 LOG(VB_GENERAL, LOG_ERR,
83 "Failed to write header to output stream.");
84 }
85 }
86}
87
89{
90 VorbisEncoder::addSamples(nullptr, 0); //flush
91 ogg_stream_clear(&m_os);
92 vorbis_block_clear(&m_vb);
93 vorbis_dsp_clear(&m_vd);
94 vorbis_comment_clear(&m_vc);
95 vorbis_info_clear(&m_vi);
96
97 // Now write the Metadata
98 if (m_metadata)
100}
101
102int VorbisEncoder::addSamples(int16_t * bytes, unsigned int length)
103{
104 long realsamples = 0;
105 auto *chars = (signed char *)bytes;
106
107 realsamples = length / 4;
108
109 if (!m_out)
110 return 0;
111
112 float** buffer = vorbis_analysis_buffer(&m_vd, realsamples);
113
114 for (long i = 0; i < realsamples; i++)
115 {
116 buffer[0][i] = ((chars[(i * 4) + 1] << 8) |
117 (chars[i * 4] & 0xff)) / 32768.0F;
118 buffer[1][i] = ((chars[(i * 4) + 3] << 8) |
119 (chars[(i * 4) + 2] & 0xff)) / 32768.0F;
120 }
121
122 vorbis_analysis_wrote(&m_vd, realsamples);
123
124 while (vorbis_analysis_blockout(&m_vd, &m_vb) == 1)
125 {
126 vorbis_analysis(&m_vb, nullptr);
127 vorbis_bitrate_addblock(&m_vb);
128
129 while (vorbis_bitrate_flushpacket(&m_vd, &m_op))
130 {
131 ogg_stream_packetin(&m_os, &m_op);
133
134 int eos = 0;
135 while (!eos)
136 {
137 int result = ogg_stream_pageout(&m_os, &m_og);
138 if (!result)
139 break;
140
141 int ret = write_page(&m_og, m_out);
142 if (ret != m_og.header_len + m_og.body_len)
143 {
144 LOG(VB_GENERAL, LOG_ERR,
145 QString("Failed to write ogg data. Aborting."));
146 return EENCODEERROR;
147 }
148 m_bytesWritten += ret;
149
150 if (ogg_page_eos(&m_og))
151 eos = 1;
152 }
153 }
154 }
155
156 return 0;
157}
FILE * m_out
Definition: encoder.h:24
MusicMetadata * m_metadata
Definition: encoder.h:26
const QString m_outfile
Definition: encoder.h:23
Read and write Vorbis (Xiph) tags in an Ogg container.
bool write(const QString &filename, MusicMetadata *mdata) override
Writes all metadata back to a file.
ogg_stream_state m_os
Definition: vorbisencoder.h:23
vorbis_info m_vi
Definition: vorbisencoder.h:27
vorbis_dsp_state m_vd
Definition: vorbisencoder.h:25
int addSamples(int16_t *bytes, unsigned int len) override
VorbisEncoder(const QString &outfile, int qualitylevel, MusicMetadata *metadata)
ogg_packet m_op
Definition: vorbisencoder.h:19
ogg_page m_og
Definition: vorbisencoder.h:18
vorbis_block m_vb
Definition: vorbisencoder.h:26
vorbis_comment m_vc
Definition: vorbisencoder.h:22
~VorbisEncoder() override
#define EENCODEERROR
Definition: encoder.h:7
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
Convenience inline random number generator functions.
uint32_t MythRandom()
generate 32 random bits
Definition: mythrandom.h:20
int FILE
Definition: mythburn.py:138
static int write_page(ogg_page *page, FILE *fp)