1159b3361Sopenharmony_ci/* 2159b3361Sopenharmony_ci * LAME MP3 encoder for DirectShow 3159b3361Sopenharmony_ci * LAME encoder wrapper 4159b3361Sopenharmony_ci * 5159b3361Sopenharmony_ci * Copyright (c) 2000-2005 Marie Orlova, Peter Gubanov, Vitaly Ivanov, Elecard Ltd. 6159b3361Sopenharmony_ci * 7159b3361Sopenharmony_ci * This library is free software; you can redistribute it and/or 8159b3361Sopenharmony_ci * modify it under the terms of the GNU Library General Public 9159b3361Sopenharmony_ci * License as published by the Free Software Foundation; either 10159b3361Sopenharmony_ci * version 2 of the License, or (at your option) any later version. 11159b3361Sopenharmony_ci * 12159b3361Sopenharmony_ci * This library is distributed in the hope that it will be useful, 13159b3361Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14159b3361Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15159b3361Sopenharmony_ci * Library General Public License for more details. 16159b3361Sopenharmony_ci * 17159b3361Sopenharmony_ci * You should have received a copy of the GNU Library General Public 18159b3361Sopenharmony_ci * License along with this library; if not, write to the 19159b3361Sopenharmony_ci * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 20159b3361Sopenharmony_ci * Boston, MA 02111-1307, USA. 21159b3361Sopenharmony_ci */ 22159b3361Sopenharmony_ci 23159b3361Sopenharmony_ci#include <streams.h> 24159b3361Sopenharmony_ci#include "Encoder.h" 25159b3361Sopenharmony_ci 26159b3361Sopenharmony_ci 27159b3361Sopenharmony_ci////////////////////////////////////////////////////////////////////// 28159b3361Sopenharmony_ci// Construction/Destruction 29159b3361Sopenharmony_ci////////////////////////////////////////////////////////////////////// 30159b3361Sopenharmony_ciCEncoder::CEncoder() : 31159b3361Sopenharmony_ci pgf(NULL), 32159b3361Sopenharmony_ci m_bInpuTypeSet(FALSE), 33159b3361Sopenharmony_ci m_bOutpuTypeSet(FALSE), 34159b3361Sopenharmony_ci m_bFinished(FALSE), 35159b3361Sopenharmony_ci m_frameCount(0), 36159b3361Sopenharmony_ci m_outOffset(0), 37159b3361Sopenharmony_ci m_outReadOffset(0) 38159b3361Sopenharmony_ci{ 39159b3361Sopenharmony_ci m_outFrameBuf = new unsigned char[OUT_BUFFER_SIZE]; 40159b3361Sopenharmony_ci} 41159b3361Sopenharmony_ci 42159b3361Sopenharmony_ciCEncoder::~CEncoder() 43159b3361Sopenharmony_ci{ 44159b3361Sopenharmony_ci Close(NULL); 45159b3361Sopenharmony_ci 46159b3361Sopenharmony_ci if (m_outFrameBuf) 47159b3361Sopenharmony_ci delete [] m_outFrameBuf; 48159b3361Sopenharmony_ci} 49159b3361Sopenharmony_ci 50159b3361Sopenharmony_ci////////////////////////////////////////////////////////////////////// 51159b3361Sopenharmony_ci// SetInputType - check if given input type is supported 52159b3361Sopenharmony_ci////////////////////////////////////////////////////////////////////// 53159b3361Sopenharmony_ciHRESULT CEncoder::SetInputType(LPWAVEFORMATEX lpwfex, bool bJustCheck) 54159b3361Sopenharmony_ci{ 55159b3361Sopenharmony_ci CAutoLock l(&m_lock); 56159b3361Sopenharmony_ci 57159b3361Sopenharmony_ci if (lpwfex->wFormatTag == WAVE_FORMAT_PCM) 58159b3361Sopenharmony_ci { 59159b3361Sopenharmony_ci if (lpwfex->nChannels == 1 || lpwfex->nChannels == 2) 60159b3361Sopenharmony_ci { 61159b3361Sopenharmony_ci if (lpwfex->nSamplesPerSec == 48000 || 62159b3361Sopenharmony_ci lpwfex->nSamplesPerSec == 44100 || 63159b3361Sopenharmony_ci lpwfex->nSamplesPerSec == 32000 || 64159b3361Sopenharmony_ci lpwfex->nSamplesPerSec == 24000 || 65159b3361Sopenharmony_ci lpwfex->nSamplesPerSec == 22050 || 66159b3361Sopenharmony_ci lpwfex->nSamplesPerSec == 16000 || 67159b3361Sopenharmony_ci lpwfex->nSamplesPerSec == 12000 || 68159b3361Sopenharmony_ci lpwfex->nSamplesPerSec == 11025 || 69159b3361Sopenharmony_ci lpwfex->nSamplesPerSec == 8000) 70159b3361Sopenharmony_ci { 71159b3361Sopenharmony_ci if (lpwfex->wBitsPerSample == 16) 72159b3361Sopenharmony_ci { 73159b3361Sopenharmony_ci if (!bJustCheck) 74159b3361Sopenharmony_ci { 75159b3361Sopenharmony_ci memcpy(&m_wfex, lpwfex, sizeof(WAVEFORMATEX)); 76159b3361Sopenharmony_ci m_bInpuTypeSet = true; 77159b3361Sopenharmony_ci } 78159b3361Sopenharmony_ci 79159b3361Sopenharmony_ci return S_OK; 80159b3361Sopenharmony_ci } 81159b3361Sopenharmony_ci } 82159b3361Sopenharmony_ci } 83159b3361Sopenharmony_ci } 84159b3361Sopenharmony_ci 85159b3361Sopenharmony_ci if (!bJustCheck) 86159b3361Sopenharmony_ci m_bInpuTypeSet = false; 87159b3361Sopenharmony_ci 88159b3361Sopenharmony_ci return E_INVALIDARG; 89159b3361Sopenharmony_ci} 90159b3361Sopenharmony_ci 91159b3361Sopenharmony_ci////////////////////////////////////////////////////////////////////// 92159b3361Sopenharmony_ci// SetOutputType - try to initialize encoder with given output type 93159b3361Sopenharmony_ci////////////////////////////////////////////////////////////////////// 94159b3361Sopenharmony_ciHRESULT CEncoder::SetOutputType(MPEG_ENCODER_CONFIG &mabsi) 95159b3361Sopenharmony_ci{ 96159b3361Sopenharmony_ci CAutoLock l(&m_lock); 97159b3361Sopenharmony_ci 98159b3361Sopenharmony_ci m_mabsi = mabsi; 99159b3361Sopenharmony_ci m_bOutpuTypeSet = true; 100159b3361Sopenharmony_ci 101159b3361Sopenharmony_ci return S_OK; 102159b3361Sopenharmony_ci} 103159b3361Sopenharmony_ci 104159b3361Sopenharmony_ci////////////////////////////////////////////////////////////////////// 105159b3361Sopenharmony_ci// SetDefaultOutputType - sets default MPEG audio properties according 106159b3361Sopenharmony_ci// to input type 107159b3361Sopenharmony_ci////////////////////////////////////////////////////////////////////// 108159b3361Sopenharmony_ciHRESULT CEncoder::SetDefaultOutputType(LPWAVEFORMATEX lpwfex) 109159b3361Sopenharmony_ci{ 110159b3361Sopenharmony_ci CAutoLock l(&m_lock); 111159b3361Sopenharmony_ci 112159b3361Sopenharmony_ci if(lpwfex->nChannels == 1 || m_mabsi.bForceMono) 113159b3361Sopenharmony_ci m_mabsi.ChMode = MONO; 114159b3361Sopenharmony_ci 115159b3361Sopenharmony_ci if((lpwfex->nSamplesPerSec < m_mabsi.dwSampleRate) || (lpwfex->nSamplesPerSec % m_mabsi.dwSampleRate != 0)) 116159b3361Sopenharmony_ci m_mabsi.dwSampleRate = lpwfex->nSamplesPerSec; 117159b3361Sopenharmony_ci 118159b3361Sopenharmony_ci return S_OK; 119159b3361Sopenharmony_ci} 120159b3361Sopenharmony_ci 121159b3361Sopenharmony_ci////////////////////////////////////////////////////////////////////// 122159b3361Sopenharmony_ci// Init - initialized or reiniyialized encoder SDK with given input 123159b3361Sopenharmony_ci// and output settings 124159b3361Sopenharmony_ci////////////////////////////////////////////////////////////////////// 125159b3361Sopenharmony_ciHRESULT CEncoder::Init() 126159b3361Sopenharmony_ci{ 127159b3361Sopenharmony_ci CAutoLock l(&m_lock); 128159b3361Sopenharmony_ci 129159b3361Sopenharmony_ci m_outOffset = 0; 130159b3361Sopenharmony_ci m_outReadOffset = 0; 131159b3361Sopenharmony_ci 132159b3361Sopenharmony_ci m_bFinished = FALSE; 133159b3361Sopenharmony_ci 134159b3361Sopenharmony_ci m_frameCount = 0; 135159b3361Sopenharmony_ci 136159b3361Sopenharmony_ci if (!pgf) 137159b3361Sopenharmony_ci { 138159b3361Sopenharmony_ci if (!m_bInpuTypeSet || !m_bOutpuTypeSet) 139159b3361Sopenharmony_ci return E_UNEXPECTED; 140159b3361Sopenharmony_ci 141159b3361Sopenharmony_ci // Init Lame library 142159b3361Sopenharmony_ci // note: newer, safer interface which doesn't 143159b3361Sopenharmony_ci // allow or require direct access to 'gf' struct is being written 144159b3361Sopenharmony_ci // see the file 'API' included with LAME. 145159b3361Sopenharmony_ci if (pgf = lame_init()) 146159b3361Sopenharmony_ci { 147159b3361Sopenharmony_ci lame_set_num_channels(pgf, m_wfex.nChannels); 148159b3361Sopenharmony_ci lame_set_in_samplerate(pgf, m_wfex.nSamplesPerSec); 149159b3361Sopenharmony_ci lame_set_out_samplerate(pgf, m_mabsi.dwSampleRate); 150159b3361Sopenharmony_ci if ((lame_get_out_samplerate(pgf) >= 32000) && (m_mabsi.dwBitrate < 32)) 151159b3361Sopenharmony_ci lame_set_brate(pgf, 32); 152159b3361Sopenharmony_ci else 153159b3361Sopenharmony_ci lame_set_brate(pgf, m_mabsi.dwBitrate); 154159b3361Sopenharmony_ci lame_set_VBR(pgf, m_mabsi.vmVariable); 155159b3361Sopenharmony_ci lame_set_VBR_min_bitrate_kbps(pgf, m_mabsi.dwVariableMin); 156159b3361Sopenharmony_ci lame_set_VBR_max_bitrate_kbps(pgf, m_mabsi.dwVariableMax); 157159b3361Sopenharmony_ci 158159b3361Sopenharmony_ci lame_set_copyright(pgf, m_mabsi.bCopyright); 159159b3361Sopenharmony_ci lame_set_original(pgf, m_mabsi.bOriginal); 160159b3361Sopenharmony_ci lame_set_error_protection(pgf, m_mabsi.bCRCProtect); 161159b3361Sopenharmony_ci 162159b3361Sopenharmony_ci lame_set_bWriteVbrTag(pgf, m_mabsi.dwXingTag); 163159b3361Sopenharmony_ci lame_set_strict_ISO(pgf, m_mabsi.dwStrictISO); 164159b3361Sopenharmony_ci lame_set_VBR_hard_min(pgf, m_mabsi.dwEnforceVBRmin); 165159b3361Sopenharmony_ci 166159b3361Sopenharmony_ci if (lame_get_num_channels(pgf) == 2 && !m_mabsi.bForceMono) 167159b3361Sopenharmony_ci { 168159b3361Sopenharmony_ci //int act_br = pgf->VBR ? pgf->VBR_min_bitrate_kbps + pgf->VBR_max_bitrate_kbps / 2 : pgf->brate; 169159b3361Sopenharmony_ci 170159b3361Sopenharmony_ci // Disabled. It's for user's consideration now 171159b3361Sopenharmony_ci //int rel = pgf->out_samplerate / (act_br + 1); 172159b3361Sopenharmony_ci //pgf->mode = rel < 200 ? m_mabsi.ChMode : JOINT_STEREO; 173159b3361Sopenharmony_ci 174159b3361Sopenharmony_ci lame_set_mode(pgf, m_mabsi.ChMode); 175159b3361Sopenharmony_ci } 176159b3361Sopenharmony_ci else 177159b3361Sopenharmony_ci lame_set_mode(pgf, MONO); 178159b3361Sopenharmony_ci 179159b3361Sopenharmony_ci if (lame_get_mode(pgf) == JOINT_STEREO) 180159b3361Sopenharmony_ci lame_set_force_ms(pgf, m_mabsi.dwForceMS); 181159b3361Sopenharmony_ci else 182159b3361Sopenharmony_ci lame_set_force_ms(pgf, 0); 183159b3361Sopenharmony_ci 184159b3361Sopenharmony_ci// pgf->mode_fixed = m_mabsi.dwModeFixed; 185159b3361Sopenharmony_ci 186159b3361Sopenharmony_ci if (m_mabsi.dwVoiceMode != 0) 187159b3361Sopenharmony_ci { 188159b3361Sopenharmony_ci lame_set_lowpassfreq(pgf,12000); 189159b3361Sopenharmony_ci ///pgf->VBR_max_bitrate_kbps = 160; 190159b3361Sopenharmony_ci } 191159b3361Sopenharmony_ci 192159b3361Sopenharmony_ci if (m_mabsi.dwKeepAllFreq != 0) 193159b3361Sopenharmony_ci { 194159b3361Sopenharmony_ci ///pgf->lowpassfreq = -1; 195159b3361Sopenharmony_ci ///pgf->highpassfreq = -1; 196159b3361Sopenharmony_ci /// not available anymore 197159b3361Sopenharmony_ci } 198159b3361Sopenharmony_ci 199159b3361Sopenharmony_ci lame_set_quality(pgf, m_mabsi.dwQuality); 200159b3361Sopenharmony_ci lame_set_VBR_q(pgf, m_mabsi.dwVBRq); 201159b3361Sopenharmony_ci 202159b3361Sopenharmony_ci lame_init_params(pgf); 203159b3361Sopenharmony_ci 204159b3361Sopenharmony_ci // encoder delay compensation 205159b3361Sopenharmony_ci { 206159b3361Sopenharmony_ci int const nch = lame_get_num_channels(pgf); 207159b3361Sopenharmony_ci short * start_padd = (short *)calloc(48, nch * sizeof(short)); 208159b3361Sopenharmony_ci 209159b3361Sopenharmony_ci int out_bytes = 0; 210159b3361Sopenharmony_ci 211159b3361Sopenharmony_ci if (nch == 2) 212159b3361Sopenharmony_ci out_bytes = lame_encode_buffer_interleaved(pgf, start_padd, 48, m_outFrameBuf, OUT_BUFFER_SIZE); 213159b3361Sopenharmony_ci else 214159b3361Sopenharmony_ci out_bytes = lame_encode_buffer(pgf, start_padd, start_padd, 48, m_outFrameBuf, OUT_BUFFER_SIZE); 215159b3361Sopenharmony_ci 216159b3361Sopenharmony_ci if (out_bytes > 0) 217159b3361Sopenharmony_ci m_outOffset += out_bytes; 218159b3361Sopenharmony_ci 219159b3361Sopenharmony_ci free(start_padd); 220159b3361Sopenharmony_ci } 221159b3361Sopenharmony_ci 222159b3361Sopenharmony_ci return S_OK; 223159b3361Sopenharmony_ci } 224159b3361Sopenharmony_ci 225159b3361Sopenharmony_ci return E_FAIL; 226159b3361Sopenharmony_ci } 227159b3361Sopenharmony_ci 228159b3361Sopenharmony_ci return S_OK; 229159b3361Sopenharmony_ci} 230159b3361Sopenharmony_ci 231159b3361Sopenharmony_ci////////////////////////////////////////////////////////////////////// 232159b3361Sopenharmony_ci// Close - closes encoder 233159b3361Sopenharmony_ci////////////////////////////////////////////////////////////////////// 234159b3361Sopenharmony_ciHRESULT CEncoder::Close(IStream* pStream) 235159b3361Sopenharmony_ci{ 236159b3361Sopenharmony_ci CAutoLock l(&m_lock); 237159b3361Sopenharmony_ci if (pgf) 238159b3361Sopenharmony_ci { 239159b3361Sopenharmony_ci if(lame_get_bWriteVbrTag(pgf) && pStream) 240159b3361Sopenharmony_ci { 241159b3361Sopenharmony_ci updateLameTagFrame(pStream); 242159b3361Sopenharmony_ci } 243159b3361Sopenharmony_ci 244159b3361Sopenharmony_ci lame_close(pgf); 245159b3361Sopenharmony_ci pgf = NULL; 246159b3361Sopenharmony_ci } 247159b3361Sopenharmony_ci 248159b3361Sopenharmony_ci return S_OK; 249159b3361Sopenharmony_ci} 250159b3361Sopenharmony_ci 251159b3361Sopenharmony_ci////////////////////////////////////////////////////////////////////// 252159b3361Sopenharmony_ci// Encode - encodes data placed on pdata and returns 253159b3361Sopenharmony_ci// the number of processed bytes 254159b3361Sopenharmony_ci////////////////////////////////////////////////////////////////////// 255159b3361Sopenharmony_ciint CEncoder::Encode(const short * pdata, int data_size) 256159b3361Sopenharmony_ci{ 257159b3361Sopenharmony_ci CAutoLock l(&m_lock); 258159b3361Sopenharmony_ci 259159b3361Sopenharmony_ci if (!pgf || !m_outFrameBuf || !pdata || data_size < 0 || (data_size & (sizeof(short) - 1))) 260159b3361Sopenharmony_ci return -1; 261159b3361Sopenharmony_ci 262159b3361Sopenharmony_ci // some data left in the buffer, shift to start 263159b3361Sopenharmony_ci if (m_outReadOffset > 0) 264159b3361Sopenharmony_ci { 265159b3361Sopenharmony_ci if (m_outOffset > m_outReadOffset) 266159b3361Sopenharmony_ci memmove(m_outFrameBuf, m_outFrameBuf + m_outReadOffset, m_outOffset - m_outReadOffset); 267159b3361Sopenharmony_ci 268159b3361Sopenharmony_ci m_outOffset -= m_outReadOffset; 269159b3361Sopenharmony_ci } 270159b3361Sopenharmony_ci 271159b3361Sopenharmony_ci m_outReadOffset = 0; 272159b3361Sopenharmony_ci 273159b3361Sopenharmony_ci 274159b3361Sopenharmony_ci 275159b3361Sopenharmony_ci m_bFinished = FALSE; 276159b3361Sopenharmony_ci 277159b3361Sopenharmony_ci int bytes_processed = 0; 278159b3361Sopenharmony_ci int const nch = lame_get_num_channels(pgf); 279159b3361Sopenharmony_ci 280159b3361Sopenharmony_ci while (1) 281159b3361Sopenharmony_ci { 282159b3361Sopenharmony_ci int nsamples = (data_size - bytes_processed) / (sizeof(short) * nch); 283159b3361Sopenharmony_ci 284159b3361Sopenharmony_ci if (nsamples <= 0) 285159b3361Sopenharmony_ci break; 286159b3361Sopenharmony_ci 287159b3361Sopenharmony_ci if (nsamples > 1152) 288159b3361Sopenharmony_ci nsamples = 1152; 289159b3361Sopenharmony_ci 290159b3361Sopenharmony_ci if (m_outOffset >= OUT_BUFFER_MAX) 291159b3361Sopenharmony_ci break; 292159b3361Sopenharmony_ci 293159b3361Sopenharmony_ci int out_bytes = 0; 294159b3361Sopenharmony_ci 295159b3361Sopenharmony_ci if (nch == 2) 296159b3361Sopenharmony_ci out_bytes = lame_encode_buffer_interleaved( 297159b3361Sopenharmony_ci pgf, 298159b3361Sopenharmony_ci (short *)(pdata + (bytes_processed / sizeof(short))), 299159b3361Sopenharmony_ci nsamples, 300159b3361Sopenharmony_ci m_outFrameBuf + m_outOffset, 301159b3361Sopenharmony_ci OUT_BUFFER_SIZE - m_outOffset); 302159b3361Sopenharmony_ci else 303159b3361Sopenharmony_ci out_bytes = lame_encode_buffer( 304159b3361Sopenharmony_ci pgf, 305159b3361Sopenharmony_ci pdata + (bytes_processed / sizeof(short)), 306159b3361Sopenharmony_ci pdata + (bytes_processed / sizeof(short)), 307159b3361Sopenharmony_ci nsamples, 308159b3361Sopenharmony_ci m_outFrameBuf + m_outOffset, 309159b3361Sopenharmony_ci OUT_BUFFER_SIZE - m_outOffset); 310159b3361Sopenharmony_ci 311159b3361Sopenharmony_ci if (out_bytes < 0) 312159b3361Sopenharmony_ci return -1; 313159b3361Sopenharmony_ci 314159b3361Sopenharmony_ci m_outOffset += out_bytes; 315159b3361Sopenharmony_ci bytes_processed += nsamples * nch * sizeof(short); 316159b3361Sopenharmony_ci } 317159b3361Sopenharmony_ci 318159b3361Sopenharmony_ci return bytes_processed; 319159b3361Sopenharmony_ci} 320159b3361Sopenharmony_ci 321159b3361Sopenharmony_ci// 322159b3361Sopenharmony_ci// Finsh - flush the buffered samples 323159b3361Sopenharmony_ci// 324159b3361Sopenharmony_ciHRESULT CEncoder::Finish() 325159b3361Sopenharmony_ci{ 326159b3361Sopenharmony_ci CAutoLock l(&m_lock); 327159b3361Sopenharmony_ci 328159b3361Sopenharmony_ci if (!pgf || !m_outFrameBuf || (m_outOffset >= OUT_BUFFER_MAX)) 329159b3361Sopenharmony_ci return E_FAIL; 330159b3361Sopenharmony_ci 331159b3361Sopenharmony_ci m_outOffset += lame_encode_flush(pgf, m_outFrameBuf + m_outOffset, OUT_BUFFER_SIZE - m_outOffset); 332159b3361Sopenharmony_ci 333159b3361Sopenharmony_ci m_bFinished = TRUE; 334159b3361Sopenharmony_ci 335159b3361Sopenharmony_ci return S_OK; 336159b3361Sopenharmony_ci} 337159b3361Sopenharmony_ci 338159b3361Sopenharmony_ci 339159b3361Sopenharmony_ciint getFrameLength(const unsigned char * pdata) 340159b3361Sopenharmony_ci{ 341159b3361Sopenharmony_ci if (!pdata || pdata[0] != 0xff || (pdata[1] & 0xe0) != 0xe0) 342159b3361Sopenharmony_ci return -1; 343159b3361Sopenharmony_ci 344159b3361Sopenharmony_ci const int sample_rate_tab[4][4] = 345159b3361Sopenharmony_ci { 346159b3361Sopenharmony_ci {11025,12000,8000,1}, 347159b3361Sopenharmony_ci {1,1,1,1}, 348159b3361Sopenharmony_ci {22050,24000,16000,1}, 349159b3361Sopenharmony_ci {44100,48000,32000,1} 350159b3361Sopenharmony_ci }; 351159b3361Sopenharmony_ci 352159b3361Sopenharmony_ci#define MPEG_VERSION_RESERVED 1 353159b3361Sopenharmony_ci#define MPEG_VERSION_1 3 354159b3361Sopenharmony_ci 355159b3361Sopenharmony_ci#define LAYER_III 1 356159b3361Sopenharmony_ci 357159b3361Sopenharmony_ci#define BITRATE_FREE 0 358159b3361Sopenharmony_ci#define BITRATE_RESERVED 15 359159b3361Sopenharmony_ci 360159b3361Sopenharmony_ci#define SRATE_RESERVED 3 361159b3361Sopenharmony_ci 362159b3361Sopenharmony_ci#define EMPHASIS_RESERVED 2 363159b3361Sopenharmony_ci 364159b3361Sopenharmony_ci int version_id = (pdata[1] & 0x18) >> 3; 365159b3361Sopenharmony_ci int layer = (pdata[1] & 0x06) >> 1; 366159b3361Sopenharmony_ci int bitrate_id = (pdata[2] & 0xF0) >> 4; 367159b3361Sopenharmony_ci int sample_rate_id = (pdata[2] & 0x0C) >> 2; 368159b3361Sopenharmony_ci int padding = (pdata[2] & 0x02) >> 1; 369159b3361Sopenharmony_ci int emphasis = pdata[3] & 0x03; 370159b3361Sopenharmony_ci 371159b3361Sopenharmony_ci if (version_id != MPEG_VERSION_RESERVED && 372159b3361Sopenharmony_ci layer == LAYER_III && 373159b3361Sopenharmony_ci bitrate_id != BITRATE_FREE && 374159b3361Sopenharmony_ci bitrate_id != BITRATE_RESERVED && 375159b3361Sopenharmony_ci sample_rate_id != SRATE_RESERVED && 376159b3361Sopenharmony_ci emphasis != EMPHASIS_RESERVED) 377159b3361Sopenharmony_ci { 378159b3361Sopenharmony_ci int spf = (version_id == MPEG_VERSION_1) ? 1152 : 576; 379159b3361Sopenharmony_ci int sample_rate = sample_rate_tab[version_id][sample_rate_id]; 380159b3361Sopenharmony_ci int bitrate = dwBitRateValue[version_id != MPEG_VERSION_1][bitrate_id - 1] * 1000; 381159b3361Sopenharmony_ci 382159b3361Sopenharmony_ci return (bitrate * spf) / (8 * sample_rate) + padding; 383159b3361Sopenharmony_ci } 384159b3361Sopenharmony_ci 385159b3361Sopenharmony_ci return -1; 386159b3361Sopenharmony_ci} 387159b3361Sopenharmony_ci 388159b3361Sopenharmony_ci 389159b3361Sopenharmony_ciint CEncoder::GetFrame(const unsigned char ** pframe) 390159b3361Sopenharmony_ci{ 391159b3361Sopenharmony_ci if (!pgf || !m_outFrameBuf || !pframe) 392159b3361Sopenharmony_ci return -1; 393159b3361Sopenharmony_ci 394159b3361Sopenharmony_ci while ((m_outOffset - m_outReadOffset) > 4) 395159b3361Sopenharmony_ci { 396159b3361Sopenharmony_ci int frame_length = getFrameLength(m_outFrameBuf + m_outReadOffset); 397159b3361Sopenharmony_ci 398159b3361Sopenharmony_ci if (frame_length < 0) 399159b3361Sopenharmony_ci { 400159b3361Sopenharmony_ci m_outReadOffset++; 401159b3361Sopenharmony_ci } 402159b3361Sopenharmony_ci else if (frame_length <= (m_outOffset - m_outReadOffset)) 403159b3361Sopenharmony_ci { 404159b3361Sopenharmony_ci *pframe = m_outFrameBuf + m_outReadOffset; 405159b3361Sopenharmony_ci m_outReadOffset += frame_length; 406159b3361Sopenharmony_ci 407159b3361Sopenharmony_ci m_frameCount++; 408159b3361Sopenharmony_ci 409159b3361Sopenharmony_ci // don't deliver the first and the last frames 410159b3361Sopenharmony_ci if (m_frameCount != 1 && !(m_bFinished && (m_outOffset - m_outReadOffset) < 5)) 411159b3361Sopenharmony_ci return frame_length; 412159b3361Sopenharmony_ci } 413159b3361Sopenharmony_ci else 414159b3361Sopenharmony_ci break; 415159b3361Sopenharmony_ci } 416159b3361Sopenharmony_ci 417159b3361Sopenharmony_ci return 0; 418159b3361Sopenharmony_ci} 419159b3361Sopenharmony_ci 420159b3361Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 421159b3361Sopenharmony_ci// Returns block of a mp3 file, witch size integer multiples of cbAlign 422159b3361Sopenharmony_ci// or not aligned if finished 423159b3361Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 424159b3361Sopenharmony_ciint CEncoder::GetBlockAligned(const unsigned char ** pblock, int* piBufferSize, const long& cbAlign) 425159b3361Sopenharmony_ci{ 426159b3361Sopenharmony_ci ASSERT(piBufferSize); 427159b3361Sopenharmony_ci if (!pgf || !m_outFrameBuf || !pblock) 428159b3361Sopenharmony_ci return -1; 429159b3361Sopenharmony_ci 430159b3361Sopenharmony_ci int iBlockLen = m_outOffset - m_outReadOffset; 431159b3361Sopenharmony_ci ASSERT(iBlockLen >= 0); 432159b3361Sopenharmony_ci 433159b3361Sopenharmony_ci if(!m_bFinished) 434159b3361Sopenharmony_ci { 435159b3361Sopenharmony_ci if(cbAlign > 0) 436159b3361Sopenharmony_ci iBlockLen-=iBlockLen%cbAlign; 437159b3361Sopenharmony_ci *piBufferSize = iBlockLen; 438159b3361Sopenharmony_ci } 439159b3361Sopenharmony_ci else 440159b3361Sopenharmony_ci { 441159b3361Sopenharmony_ci if(cbAlign && iBlockLen%cbAlign) 442159b3361Sopenharmony_ci { 443159b3361Sopenharmony_ci *piBufferSize = iBlockLen + cbAlign - iBlockLen%cbAlign; 444159b3361Sopenharmony_ci } 445159b3361Sopenharmony_ci else 446159b3361Sopenharmony_ci { 447159b3361Sopenharmony_ci *piBufferSize = iBlockLen; 448159b3361Sopenharmony_ci } 449159b3361Sopenharmony_ci } 450159b3361Sopenharmony_ci 451159b3361Sopenharmony_ci if(iBlockLen) { 452159b3361Sopenharmony_ci *pblock = m_outFrameBuf + m_outReadOffset; 453159b3361Sopenharmony_ci m_outReadOffset+=iBlockLen; 454159b3361Sopenharmony_ci } 455159b3361Sopenharmony_ci 456159b3361Sopenharmony_ci return iBlockLen; 457159b3361Sopenharmony_ci} 458159b3361Sopenharmony_ci 459159b3361Sopenharmony_ciHRESULT CEncoder::maybeSyncWord(IStream *pStream) 460159b3361Sopenharmony_ci{ 461159b3361Sopenharmony_ci HRESULT hr = S_OK; 462159b3361Sopenharmony_ci unsigned char mp3_frame_header[4]; 463159b3361Sopenharmony_ci ULONG nbytes; 464159b3361Sopenharmony_ci if(FAILED(hr = pStream->Read(mp3_frame_header, sizeof(mp3_frame_header), &nbytes))) 465159b3361Sopenharmony_ci return hr; 466159b3361Sopenharmony_ci 467159b3361Sopenharmony_ci if ( nbytes != sizeof(mp3_frame_header) ) { 468159b3361Sopenharmony_ci return E_FAIL; 469159b3361Sopenharmony_ci } 470159b3361Sopenharmony_ci if ( mp3_frame_header[0] != 0xffu ) { 471159b3361Sopenharmony_ci return S_FALSE; /* doesn't look like a sync word */ 472159b3361Sopenharmony_ci } 473159b3361Sopenharmony_ci if ( (mp3_frame_header[1] & 0xE0u) != 0xE0u ) { 474159b3361Sopenharmony_ci return S_FALSE; /* doesn't look like a sync word */ 475159b3361Sopenharmony_ci } 476159b3361Sopenharmony_ci return S_OK; 477159b3361Sopenharmony_ci} 478159b3361Sopenharmony_ci 479159b3361Sopenharmony_ciHRESULT CEncoder::skipId3v2(IStream *pStream, size_t lametag_frame_size) 480159b3361Sopenharmony_ci{ 481159b3361Sopenharmony_ci HRESULT hr = S_OK; 482159b3361Sopenharmony_ci ULONG nbytes; 483159b3361Sopenharmony_ci size_t id3v2TagSize = 0; 484159b3361Sopenharmony_ci unsigned char id3v2Header[10]; 485159b3361Sopenharmony_ci LARGE_INTEGER seekTo; 486159b3361Sopenharmony_ci 487159b3361Sopenharmony_ci /* seek to the beginning of the stream */ 488159b3361Sopenharmony_ci seekTo.QuadPart = 0; 489159b3361Sopenharmony_ci if (FAILED(hr = pStream->Seek(seekTo, STREAM_SEEK_SET, NULL))) { 490159b3361Sopenharmony_ci return hr; /* not seekable, abort */ 491159b3361Sopenharmony_ci } 492159b3361Sopenharmony_ci /* read 10 bytes in case there's an ID3 version 2 header here */ 493159b3361Sopenharmony_ci hr = pStream->Read(id3v2Header, sizeof(id3v2Header), &nbytes); 494159b3361Sopenharmony_ci if (FAILED(hr)) 495159b3361Sopenharmony_ci return hr; 496159b3361Sopenharmony_ci if(nbytes != sizeof(id3v2Header)) { 497159b3361Sopenharmony_ci return E_FAIL; /* not readable, maybe opened Write-Only */ 498159b3361Sopenharmony_ci } 499159b3361Sopenharmony_ci /* does the stream begin with the ID3 version 2 file identifier? */ 500159b3361Sopenharmony_ci if (!strncmp((char *) id3v2Header, "ID3", 3)) { 501159b3361Sopenharmony_ci /* the tag size (minus the 10-byte header) is encoded into four 502159b3361Sopenharmony_ci * bytes where the most significant bit is clear in each byte 503159b3361Sopenharmony_ci */ 504159b3361Sopenharmony_ci id3v2TagSize = (((id3v2Header[6] & 0x7f) << 21) 505159b3361Sopenharmony_ci | ((id3v2Header[7] & 0x7f) << 14) 506159b3361Sopenharmony_ci | ((id3v2Header[8] & 0x7f) << 7) 507159b3361Sopenharmony_ci | (id3v2Header[9] & 0x7f)) 508159b3361Sopenharmony_ci + sizeof id3v2Header; 509159b3361Sopenharmony_ci } 510159b3361Sopenharmony_ci /* Seek to the beginning of the audio stream */ 511159b3361Sopenharmony_ci seekTo.QuadPart = id3v2TagSize; 512159b3361Sopenharmony_ci if (FAILED(hr = pStream->Seek(seekTo, STREAM_SEEK_SET, NULL))) { 513159b3361Sopenharmony_ci return hr; 514159b3361Sopenharmony_ci } 515159b3361Sopenharmony_ci if (S_OK != (hr = maybeSyncWord(pStream))) { 516159b3361Sopenharmony_ci return SUCCEEDED(hr)?E_FAIL:hr; 517159b3361Sopenharmony_ci } 518159b3361Sopenharmony_ci seekTo.QuadPart = id3v2TagSize+lametag_frame_size; 519159b3361Sopenharmony_ci if (FAILED(hr = pStream->Seek(seekTo, STREAM_SEEK_SET, NULL))) { 520159b3361Sopenharmony_ci return hr; 521159b3361Sopenharmony_ci } 522159b3361Sopenharmony_ci if (S_OK != (hr = maybeSyncWord(pStream))) { 523159b3361Sopenharmony_ci return SUCCEEDED(hr)?E_FAIL:hr; 524159b3361Sopenharmony_ci } 525159b3361Sopenharmony_ci /* OK, it seems we found our LAME-Tag/Xing frame again */ 526159b3361Sopenharmony_ci /* Seek to the beginning of the audio stream */ 527159b3361Sopenharmony_ci seekTo.QuadPart = id3v2TagSize; 528159b3361Sopenharmony_ci if (FAILED(hr = pStream->Seek(seekTo, STREAM_SEEK_SET, NULL))) { 529159b3361Sopenharmony_ci return hr; 530159b3361Sopenharmony_ci } 531159b3361Sopenharmony_ci return S_OK; 532159b3361Sopenharmony_ci} 533159b3361Sopenharmony_ci 534159b3361Sopenharmony_ci// Updates VBR tag 535159b3361Sopenharmony_ciHRESULT CEncoder::updateLameTagFrame(IStream* pStream) 536159b3361Sopenharmony_ci{ 537159b3361Sopenharmony_ci HRESULT hr = S_OK; 538159b3361Sopenharmony_ci size_t n = lame_get_lametag_frame( pgf, 0, 0 ); /* ask for bufer size */ 539159b3361Sopenharmony_ci 540159b3361Sopenharmony_ci if ( n > 0 ) 541159b3361Sopenharmony_ci { 542159b3361Sopenharmony_ci unsigned char* buffer = 0; 543159b3361Sopenharmony_ci ULONG m = n; 544159b3361Sopenharmony_ci 545159b3361Sopenharmony_ci if ( FAILED(hr = skipId3v2(pStream, n) )) 546159b3361Sopenharmony_ci { 547159b3361Sopenharmony_ci /*DispErr( "Error updating LAME-tag frame:\n\n" 548159b3361Sopenharmony_ci "can't locate old frame\n" );*/ 549159b3361Sopenharmony_ci return hr; 550159b3361Sopenharmony_ci } 551159b3361Sopenharmony_ci 552159b3361Sopenharmony_ci buffer = (unsigned char*)malloc( n ); 553159b3361Sopenharmony_ci 554159b3361Sopenharmony_ci if ( buffer == 0 ) 555159b3361Sopenharmony_ci { 556159b3361Sopenharmony_ci /*DispErr( "Error updating LAME-tag frame:\n\n" 557159b3361Sopenharmony_ci "can't allocate frame buffer\n" );*/ 558159b3361Sopenharmony_ci return E_OUTOFMEMORY; 559159b3361Sopenharmony_ci } 560159b3361Sopenharmony_ci 561159b3361Sopenharmony_ci /* Put it all to disk again */ 562159b3361Sopenharmony_ci n = lame_get_lametag_frame( pgf, buffer, n ); 563159b3361Sopenharmony_ci if ( n > 0 ) 564159b3361Sopenharmony_ci { 565159b3361Sopenharmony_ci hr = pStream->Write(buffer, n, &m); 566159b3361Sopenharmony_ci } 567159b3361Sopenharmony_ci free( buffer ); 568159b3361Sopenharmony_ci 569159b3361Sopenharmony_ci if ( m != n ) 570159b3361Sopenharmony_ci { 571159b3361Sopenharmony_ci /*DispErr( "Error updating LAME-tag frame:\n\n" 572159b3361Sopenharmony_ci "couldn't write frame into file\n" );*/ 573159b3361Sopenharmony_ci return E_FAIL; 574159b3361Sopenharmony_ci } 575159b3361Sopenharmony_ci } 576159b3361Sopenharmony_ci return hr; 577159b3361Sopenharmony_ci} 578