00001 #include <qstring.h>
00002 #include <qcstring.h>
00003 #include <qapplication.h>
00004 #include <qprogressbar.h>
00005
00006 #include "metadata.h"
00007 #include "encoder.h"
00008 #include "vorbisencoder.h"
00009 #include "metaiooggvorbiscomment.h"
00010
00011 #include <vorbis/vorbisfile.h>
00012
00013 #include <iostream>
00014
00015 #include <mythtv/mythcontext.h>
00016
00017 using namespace std;
00018
00019 int write_page(ogg_page *page, FILE *fp)
00020 {
00021 int written = fwrite(page->header, 1, page->header_len, fp);
00022 written += fwrite(page->body, 1, page->body_len, fp);
00023
00024 return written;
00025 }
00026
00027 VorbisEncoder::VorbisEncoder(const QString &outfile, int qualitylevel,
00028 Metadata *metadata)
00029 : Encoder(outfile, qualitylevel, metadata)
00030 {
00031 int result;
00032
00033 vorbis_comment_init(&vc);
00034 MetaIOOggVorbisComment::getRawVorbisComment(metadata, &vc);
00035
00036 packetsdone = 0;
00037 bytes_written = 0;
00038
00039 vorbis_info_init(&vi);
00040
00041 float quality = 1.0;
00042 if (qualitylevel == 0)
00043 quality = 0.4;
00044 if (qualitylevel == 1)
00045 quality = 0.7;
00046
00047 int ret = vorbis_encode_setup_vbr(&vi, 2, 44100, quality);
00048 if (ret)
00049 {
00050 VERBOSE(VB_GENERAL, QString("Error initializing VORBIS encoder."
00051 " Got return code: %1").arg(ret));
00052 vorbis_info_clear(&vi);
00053 return;
00054 }
00055
00056 vorbis_encode_ctl(&vi, OV_ECTL_RATEMANAGE_SET, NULL);
00057 vorbis_encode_setup_init(&vi);
00058 vorbis_analysis_init(&vd, &vi);
00059 vorbis_block_init(&vd, &vb);
00060
00061 ogg_stream_init(&os, 0);
00062
00063 ogg_packet header_main;
00064 ogg_packet header_comments;
00065 ogg_packet header_codebooks;
00066
00067 vorbis_analysis_headerout(&vd, &vc, &header_main, &header_comments,
00068 &header_codebooks);
00069
00070 ogg_stream_packetin(&os, &header_main);
00071 ogg_stream_packetin(&os, &header_comments);
00072 ogg_stream_packetin(&os, &header_codebooks);
00073
00074 while ((result = ogg_stream_flush(&os, &og)))
00075 {
00076 if (!result || !m_out)
00077 break;
00078 int ret = write_page(&og, m_out);
00079 if (ret != og.header_len + og.body_len)
00080 {
00081 VERBOSE(VB_IMPORTANT, QString("Failed to write header"
00082 " to output stream."));
00083 }
00084 }
00085 }
00086
00087 VorbisEncoder::~VorbisEncoder()
00088 {
00089 addSamples(0, 0);
00090 ogg_stream_clear(&os);
00091 vorbis_block_clear(&vb);
00092 vorbis_dsp_clear(&vd);
00093 vorbis_comment_clear(&vc);
00094 vorbis_info_clear(&vi);
00095 }
00096
00097 int VorbisEncoder::addSamples(int16_t * bytes, unsigned int length)
00098 {
00099 int i;
00100 long realsamples = 0;
00101 signed char *chars = (signed char *)bytes;
00102
00103 realsamples = length / 4;
00104
00105 if (!m_out)
00106 return 0;
00107
00108 float** buffer = vorbis_analysis_buffer(&vd, realsamples);
00109
00110 for (i = 0; i < realsamples; i++)
00111 {
00112 buffer[0][i] = ((chars[i * 4 + 1] << 8) |
00113 (chars[i * 4] & 0xff)) / 32768.0f;
00114 buffer[1][i] = ((chars[i * 4 + 3] << 8) |
00115 (chars[i * 4 + 2] & 0xff)) / 32768.0f;
00116 }
00117
00118 vorbis_analysis_wrote(&vd, realsamples);
00119
00120 while (vorbis_analysis_blockout(&vd, &vb) == 1)
00121 {
00122 vorbis_analysis(&vb, NULL);
00123 vorbis_bitrate_addblock(&vb);
00124
00125 while (vorbis_bitrate_flushpacket(&vd, &op))
00126 {
00127 ogg_stream_packetin(&os, &op);
00128 packetsdone++;
00129
00130 int eos = 0;
00131 while (!eos)
00132 {
00133 int result = ogg_stream_pageout(&os, &og);
00134 if (!result)
00135 break;
00136
00137 int ret = write_page(&og, m_out);
00138 if (ret != og.header_len + og.body_len)
00139 {
00140 VERBOSE(VB_GENERAL, QString("Failed to write ogg data."
00141 " Aborting."));
00142 return EENCODEERROR;
00143 }
00144 bytes_written += ret;
00145
00146 if (ogg_page_eos(&og))
00147 eos = 1;
00148 }
00149 }
00150 }
00151
00152 return 0;
00153 }