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