|
MythTV
0.26-pre
|
00001 /* 00002 MP3 encoding support using liblame for MythMusic 00003 00004 (c) 2003 Stefan Frank 00005 00006 Please send an e-mail to sfr@gmx.net if you have 00007 questions or comments. 00008 00009 Project Website: out http://www.mythtv.org/ 00010 00011 This program is free software; you can redistribute it and/or modify 00012 it under the terms of the GNU General Public License as published by 00013 the Free Software Foundation; either version 2 of the License, or 00014 (at your option) any later version. 00015 00016 This program is distributed in the hope that it will be useful, 00017 but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 GNU General Public License for more details. 00020 00021 You should have received a copy of the GNU General Public License 00022 along with this program; if not, write to the Free Software 00023 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00024 */ 00025 00026 #include <QApplication> 00027 #include <QString> 00028 00029 #include "metadata.h" 00030 #include "lameencoder.h" 00031 #include "metaioid3.h" 00032 00033 #include <iostream> 00034 00035 #include <mythcontext.h> 00036 #include <mythlogging.h> 00037 00038 using namespace std; 00039 00040 static int write_buffer(char *buf, int bufsize, FILE *fp) 00041 { 00042 return fwrite(buf, 1, bufsize, fp); 00043 } 00044 00045 void LameEncoder::init_id3tags(lame_global_flags *gf) 00046 { 00047 // Very basic ID3v2 Header. Rewritten later, but libid3tag. 00048 id3tag_init(gf); 00049 00050 // Dummy tag. It'll get overwritten later by the more flexible 00051 // libid3 (MAD). Unf. it wont write the id3 tag to the file if 00052 // none exists, hense this dummy entry. 00053 id3tag_set_title(gf, "Title"); 00054 00055 // write v2 tags. 00056 id3tag_v2_only(gf); 00057 } 00058 00059 int LameEncoder::init_encoder(lame_global_flags *gf, int quality, bool vbr) 00060 { 00061 int lameret = 0; 00062 int meanbitrate = 128; 00063 int preset = STANDARD; 00064 00065 switch (quality) 00066 { 00067 case 0: // low, always use CBR 00068 meanbitrate = 128; 00069 vbr = false; 00070 break; 00071 case 1: // medium 00072 meanbitrate = 192; 00073 break; 00074 case 2: // high 00075 meanbitrate = 256; 00076 preset = EXTREME; 00077 break; 00078 } 00079 00080 if (vbr) 00081 lame_set_preset(gf, preset); 00082 else 00083 { 00084 lame_set_preset(gf, meanbitrate); 00085 lame_set_VBR(gf, vbr_off); 00086 } 00087 00088 if (channels == 1) 00089 { 00090 lame_set_mode(gf, MONO); 00091 } 00092 00093 lameret = lame_init_params(gf); 00094 00095 return lameret; 00096 } 00097 00098 LameEncoder::LameEncoder(const QString &outfile, int qualitylevel, 00099 Metadata *metadata, bool vbr) : 00100 Encoder(outfile, qualitylevel, metadata), 00101 bits(16), 00102 channels(2), 00103 samplerate(44100), 00104 bytes_per_sample(channels * bits / 8), 00105 samples_per_channel(0), 00106 mp3buf_size((int)(1.25 * 16384 + 7200)), // worst-case estimate 00107 mp3buf(new char[mp3buf_size]), 00108 mp3bytes(0), 00109 gf(lame_init()) 00110 { 00111 init_id3tags(gf); 00112 00113 int lameret = init_encoder(gf, qualitylevel, vbr); 00114 if (lameret < 0) 00115 { 00116 LOG(VB_GENERAL, LOG_ERR, 00117 QString("Error initializing LAME encoder. Got return code: %1") 00118 .arg(lameret)); 00119 return; 00120 } 00121 } 00122 00123 LameEncoder::~LameEncoder() 00124 { 00125 addSamples(0, 0); //flush 00126 00127 if (gf && m_out) 00128 lame_mp3_tags_fid (gf, m_out); 00129 if (gf) 00130 lame_close(gf); 00131 if (mp3buf) 00132 delete[] mp3buf; 00133 00134 // Need to close the file here. 00135 if (m_out) 00136 { 00137 fclose(m_out); 00138 00139 // Make sure the base class doesn't do a double clear. 00140 m_out = NULL; 00141 } 00142 00143 // Now write the Metadata 00144 if (m_metadata) 00145 { 00146 QString filename = m_metadata->Filename(); 00147 m_metadata->setFilename(m_outfile); 00148 MetaIOID3().write(m_metadata); 00149 m_metadata->setFilename(filename); 00150 } 00151 } 00152 00153 int LameEncoder::addSamples(int16_t * bytes, unsigned int length) 00154 { 00155 int lameret = 0; 00156 00157 samples_per_channel = length / bytes_per_sample; 00158 00159 if (length > 0) 00160 { 00161 lameret = lame_encode_buffer_interleaved(gf, (short int *)bytes, 00162 samples_per_channel, 00163 (unsigned char *)mp3buf, 00164 mp3buf_size); 00165 } 00166 else 00167 { 00168 lameret = lame_encode_flush(gf, (unsigned char *)mp3buf, 00169 mp3buf_size); 00170 } 00171 00172 if (lameret < 0) 00173 { 00174 LOG(VB_GENERAL, LOG_ERR, QString("LAME encoder error.")); 00175 } 00176 else if (lameret > 0 && m_out) 00177 { 00178 if (write_buffer(mp3buf, lameret, m_out) != lameret) 00179 { 00180 LOG(VB_GENERAL, LOG_ERR, "Failed to write mp3 data. Aborting."); 00181 return EENCODEERROR; 00182 } 00183 } 00184 00185 return 0; 00186 } 00187
1.7.6.1