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