Mpegac.cpp 63 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025
  1. /*
  2. * LAME MP3 encoder for DirectShow
  3. * DirectShow filter implementation
  4. *
  5. * Copyright (c) 2000-2005 Marie Orlova, Peter Gubanov, Vitaly Ivanov, Elecard Ltd.
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Library General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Library General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Library General Public
  18. * License along with this library; if not, write to the
  19. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  20. * Boston, MA 02111-1307, USA.
  21. */
  22. #include <streams.h>
  23. #include <olectl.h>
  24. #include <initguid.h>
  25. //#include <olectlid.h>
  26. #include "uids.h"
  27. #include "iaudioprops.h"
  28. #include "mpegac.h"
  29. #include "resource.h"
  30. #include "PropPage.h"
  31. #include "PropPage_adv.h"
  32. #include "aboutprp.h"
  33. #include "Encoder.h"
  34. #include "Reg.h"
  35. #ifndef _INC_MMREG
  36. #include <mmreg.h>
  37. #endif
  38. // default parameters
  39. #define DEFAULT_LAYER 3
  40. #define DEFAULT_STEREO_MODE JOINT_STEREO
  41. #define DEFAULT_FORCE_MS 0
  42. #define DEFAULT_MODE_FIXED 0
  43. #define DEFAULT_ENFORCE_MIN 0
  44. #define DEFAULT_VOICE 0
  45. #define DEFAULT_KEEP_ALL_FREQ 0
  46. #define DEFAULT_STRICT_ISO 0
  47. #define DEFAULT_DISABLE_SHORT_BLOCK 0
  48. #define DEFAULT_XING_TAG 0
  49. #define DEFAULT_SAMPLE_RATE 44100
  50. #define DEFAULT_BITRATE 128
  51. #define DEFAULT_VARIABLE 0
  52. #define DEFAULT_CRC 0
  53. #define DEFAULT_FORCE_MONO 0
  54. #define DEFAULT_SET_DURATION 1
  55. #define DEFAULT_SAMPLE_OVERLAP 1
  56. #define DEFAULT_COPYRIGHT 0
  57. #define DEFAULT_ORIGINAL 0
  58. #define DEFAULT_VARIABLEMIN 80
  59. #define DEFAULT_VARIABLEMAX 160
  60. #define DEFAULT_ENCODING_QUALITY 5
  61. #define DEFAULT_VBR_QUALITY 4
  62. #define DEFAULT_PES 0
  63. #define DEFAULT_FILTER_MERIT MERIT_DO_NOT_USE // Standard compressor merit value
  64. #define GET_DATARATE(kbps) (kbps * 1000 / 8)
  65. #define GET_FRAMELENGTH(bitrate, sample_rate) ((WORD)(((sample_rate < 32000 ? 72000 : 144000) * (bitrate))/(sample_rate)))
  66. #define DECLARE_PTR(type, ptr, expr) type* ptr = (type*)(expr);
  67. // Create a list of all (or mostly all) of the encoder CBR output capabilities which
  68. // will be parsed into a list of capabilities used by the IAMStreamConfig Interface
  69. output_caps_t OutputCapabilities[] =
  70. { // {SampleRate, BitRate}
  71. { 48000, 320 },{ 48000, 256 },{ 48000, 224 },{ 48000, 192 }, // MPEG 1.0 Spec @ 48KHz
  72. { 48000, 160 },{ 48000, 128 },{ 48000, 112 },{ 48000, 96 },
  73. { 48000, 80 },{ 48000, 64 },{ 48000, 56 },{ 48000, 48 },
  74. { 48000, 40 },{ 48000, 32 },
  75. { 24000, 160 },{ 24000, 144 },{ 24000, 128 },{ 24000, 112 }, // MPEG 2.0 Spec @ 24KHz
  76. { 24000, 96 },{ 24000, 80 },{ 24000, 64 },{ 24000, 56 },
  77. { 24000, 48 },{ 24000, 40 },{ 24000, 32 },{ 24000, 24 },
  78. { 24000, 16 },{ 24000, 8 },
  79. { 12000, 64 },{ 12000, 56 },{ 12000, 48 },{ 12000, 40 }, // MPEG 2.5 Spec @ 12KHz
  80. { 12000, 32 },{ 12000, 24 },{ 12000, 16 },{ 12000, 8 },
  81. // --------------------------- --------------------------
  82. { 44100, 320 },{ 44100, 256 },{ 44100, 224 },{ 44100, 192 }, // MPEG 1.0 Spec @ 44.1KHz
  83. { 44100, 160 },{ 44100, 128 },{ 44100, 112 },{ 44100, 96 },
  84. { 44100, 80 },{ 44100, 64 },{ 44100, 56 },{ 44100, 48 },
  85. { 44100, 40 },{ 44100, 32 },
  86. { 22050, 160 },{ 22050, 144 },{ 22050, 128 },{ 22050, 112 }, // MPEG 2.0 Spec @ 22.05KHz
  87. { 22050, 96 },{ 22050, 80 },{ 22050, 64 },{ 22050, 56 },
  88. { 22050, 48 },{ 22050, 40 },{ 22050, 32 },{ 22050, 24 },
  89. { 22050, 16 },{ 22050, 8 },
  90. { 11025, 64 },{ 11025, 56 },{ 11025, 48 },{ 11025, 40 }, // MPEG 2.5 Spec @ 11.025KHz
  91. { 11025, 32 },{ 11025, 24 },{ 11025, 16 },{ 11025, 8 },
  92. // --------------------------- --------------------------
  93. { 32000, 320 },{ 32000, 256 },{ 32000, 224 },{ 32000, 192 }, // MPEG 1.0 Spec @ 32KHz
  94. { 32000, 160 },{ 32000, 128 },{ 32000, 112 },{ 32000, 96 },
  95. { 32000, 80 },{ 32000, 64 },{ 32000, 56 },{ 32000, 48 },
  96. { 32000, 40 },{ 32000, 32 },
  97. { 16000, 160 },{ 16000, 144 },{ 16000, 128 },{ 16000, 112 }, // MPEG 2.0 Spec @ 16KHz
  98. { 16000, 96 },{ 16000, 80 },{ 16000, 64 },{ 16000, 56 },
  99. { 16000, 48 },{ 16000, 40 },{ 16000, 32 },{ 16000, 24 },
  100. { 16000, 16 },{ 16000, 8 },
  101. { 8000, 64 },{ 8000, 56 },{ 8000, 48 },{ 8000, 40 }, // MPEG 2.5 Spec @ 8KHz
  102. { 8000, 32 },{ 8000, 24 },{ 8000, 16 },{ 8000, 8 }
  103. };
  104. /* Registration setup stuff */
  105. // Setup data
  106. AMOVIESETUP_MEDIATYPE sudMpgInputType[] =
  107. {
  108. { &MEDIATYPE_Audio, &MEDIASUBTYPE_PCM }
  109. };
  110. AMOVIESETUP_MEDIATYPE sudMpgOutputType[] =
  111. {
  112. { &MEDIATYPE_Audio, &MEDIASUBTYPE_MPEG1AudioPayload },
  113. { &MEDIATYPE_Audio, &MEDIASUBTYPE_MPEG2_AUDIO },
  114. { &MEDIATYPE_Audio, &MEDIASUBTYPE_MP3 },
  115. { &MEDIATYPE_Stream, &MEDIASUBTYPE_MPEG1Audio }
  116. };
  117. AMOVIESETUP_PIN sudMpgPins[] =
  118. {
  119. { L"PCM Input",
  120. FALSE, // bRendered
  121. FALSE, // bOutput
  122. FALSE, // bZero
  123. FALSE, // bMany
  124. &CLSID_NULL, // clsConnectsToFilter
  125. NULL, // ConnectsToPin
  126. NUMELMS(sudMpgInputType), // Number of media types
  127. sudMpgInputType
  128. },
  129. { L"MPEG Output",
  130. FALSE, // bRendered
  131. TRUE, // bOutput
  132. FALSE, // bZero
  133. FALSE, // bMany
  134. &CLSID_NULL, // clsConnectsToFilter
  135. NULL, // ConnectsToPin
  136. NUMELMS(sudMpgOutputType), // Number of media types
  137. sudMpgOutputType
  138. }
  139. };
  140. AMOVIESETUP_FILTER sudMpgAEnc =
  141. {
  142. &CLSID_LAMEDShowFilter,
  143. L"LAME Audio Encoder",
  144. DEFAULT_FILTER_MERIT, // Standard compressor merit value
  145. NUMELMS(sudMpgPins), // 2 pins
  146. sudMpgPins
  147. };
  148. /*****************************************************************************/
  149. // COM Global table of objects in this dll
  150. static WCHAR g_wszName[] = L"LAME Audio Encoder";
  151. CFactoryTemplate g_Templates[] =
  152. {
  153. { g_wszName, &CLSID_LAMEDShowFilter, CMpegAudEnc::CreateInstance, NULL, &sudMpgAEnc },
  154. { L"LAME Audio Encoder Property Page", &CLSID_LAMEDShow_PropertyPage, CMpegAudEncPropertyPage::CreateInstance},
  155. { L"LAME Audio Encoder Property Page", &CLSID_LAMEDShow_PropertyPageAdv, CMpegAudEncPropertyPageAdv::CreateInstance},
  156. { L"LAME Audio Encoder About", &CLSID_LAMEDShow_About, CMAEAbout::CreateInstance}
  157. };
  158. // Count of objects listed in g_cTemplates
  159. int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
  160. ////////////////////////////////////////////
  161. // Declare the DirectShow filter information.
  162. // Used by IFilterMapper2() in the call to DllRegisterServer()
  163. // to register the filter in the CLSID_AudioCompressorCategory.
  164. REGFILTER2 rf2FilterReg = {
  165. 1, // Version number.
  166. DEFAULT_FILTER_MERIT, // Merit. This should match the merit specified in the AMOVIESETUP_FILTER definition
  167. NUMELMS(sudMpgPins), // Number of pins.
  168. sudMpgPins // Pointer to pin information.
  169. };
  170. STDAPI DllRegisterServer(void)
  171. {
  172. HRESULT hr = AMovieDllRegisterServer2(TRUE);
  173. if (FAILED(hr)) {
  174. return hr;
  175. }
  176. IFilterMapper2 *pFM2 = NULL;
  177. hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, IID_IFilterMapper2, (void **)&pFM2);
  178. if (SUCCEEDED(hr)) {
  179. hr = pFM2->RegisterFilter(
  180. CLSID_LAMEDShowFilter, // Filter CLSID.
  181. g_wszName, // Filter name.
  182. NULL, // Device moniker.
  183. &CLSID_AudioCompressorCategory, // Audio compressor category.
  184. g_wszName, // Instance data.
  185. &rf2FilterReg // Filter information.
  186. );
  187. pFM2->Release();
  188. }
  189. return hr;
  190. }
  191. STDAPI DllUnregisterServer()
  192. {
  193. HRESULT hr = AMovieDllRegisterServer2(FALSE);
  194. if (FAILED(hr)) {
  195. return hr;
  196. }
  197. IFilterMapper2 *pFM2 = NULL;
  198. hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, IID_IFilterMapper2, (void **)&pFM2);
  199. if (SUCCEEDED(hr)) {
  200. hr = pFM2->UnregisterFilter(&CLSID_AudioCompressorCategory, g_wszName, CLSID_LAMEDShowFilter);
  201. pFM2->Release();
  202. }
  203. return hr;
  204. }
  205. CUnknown *CMpegAudEnc::CreateInstance(LPUNKNOWN lpunk, HRESULT *phr)
  206. {
  207. CMpegAudEnc *punk = new CMpegAudEnc(lpunk, phr);
  208. if (punk == NULL)
  209. *phr = E_OUTOFMEMORY;
  210. return punk;
  211. }
  212. CMpegAudEnc::CMpegAudEnc(LPUNKNOWN lpunk, HRESULT *phr)
  213. : CTransformFilter(NAME("LAME Audio Encoder"), lpunk, CLSID_LAMEDShowFilter),
  214. CPersistStream(lpunk, phr)
  215. {
  216. // ENCODER OUTPUT PIN
  217. // Override the output pin with our own which will implement the IAMStreamConfig Interface
  218. CTransformOutputPin *pOut = new CMpegAudEncOutPin( this, phr );
  219. if (pOut == NULL) {
  220. *phr = E_OUTOFMEMORY;
  221. return;
  222. }
  223. else if (FAILED(*phr)) { // A failed return code should delete the object
  224. delete pOut;
  225. return;
  226. }
  227. m_pOutput = pOut;
  228. // ENCODER INPUT PIN
  229. // Since we've created our own output pin we must also create
  230. // the input pin ourselves because the CTransformFilter base class
  231. // will create an extra output pin if the input pin wasn't created.
  232. CTransformInputPin *pIn = new CTransformInputPin(NAME("LameEncoderInputPin"),
  233. this, // Owner filter
  234. phr, // Result code
  235. L"Input"); // Pin name
  236. if (pIn == NULL) {
  237. *phr = E_OUTOFMEMORY;
  238. return;
  239. }
  240. else if (FAILED(*phr)) { // A failed return code should delete the object
  241. delete pIn;
  242. return;
  243. }
  244. m_pInput = pIn;
  245. MPEG_ENCODER_CONFIG mec;
  246. ReadPresetSettings(&mec);
  247. m_Encoder.SetOutputType(mec);
  248. m_CapsNum = 0;
  249. m_hasFinished = TRUE;
  250. m_bStreamOutput = FALSE;
  251. m_currentMediaTypeIndex = 0;
  252. }
  253. CMpegAudEnc::~CMpegAudEnc(void)
  254. {
  255. }
  256. LPAMOVIESETUP_FILTER CMpegAudEnc::GetSetupData()
  257. {
  258. return &sudMpgAEnc;
  259. }
  260. HRESULT CMpegAudEnc::Receive(IMediaSample * pSample)
  261. {
  262. CAutoLock lock(&m_cs);
  263. if (!pSample)
  264. return S_OK;
  265. BYTE * pSourceBuffer = NULL;
  266. if (pSample->GetPointer(&pSourceBuffer) != S_OK || !pSourceBuffer)
  267. return S_OK;
  268. long sample_size = pSample->GetActualDataLength();
  269. REFERENCE_TIME rtStart, rtStop;
  270. BOOL gotValidTime = (pSample->GetTime(&rtStart, &rtStop) != VFW_E_SAMPLE_TIME_NOT_SET);
  271. if (sample_size <= 0 || pSourceBuffer == NULL || m_hasFinished || (gotValidTime && rtStart < 0))
  272. return S_OK;
  273. if (gotValidTime)
  274. {
  275. if (m_rtStreamTime < 0)
  276. {
  277. m_rtStreamTime = rtStart;
  278. m_rtEstimated = rtStart;
  279. }
  280. else
  281. {
  282. resync_point_t * sync = m_sync + m_sync_in_idx;
  283. if (sync->applied)
  284. {
  285. REFERENCE_TIME rtGap = rtStart - m_rtEstimated;
  286. // if old sync data is applied and gap is greater than 1 ms
  287. // then make a new synchronization point
  288. if (rtGap > 10000 || (m_allowOverlap && rtGap < -10000))
  289. {
  290. sync->sample = m_samplesIn;
  291. sync->delta = rtGap;
  292. sync->applied = FALSE;
  293. m_rtEstimated += sync->delta;
  294. if (m_sync_in_idx < (RESYNC_COUNT - 1))
  295. m_sync_in_idx++;
  296. else
  297. m_sync_in_idx = 0;
  298. }
  299. }
  300. }
  301. }
  302. m_rtEstimated += (LONGLONG)(m_bytesToDuration * sample_size);
  303. m_samplesIn += sample_size / m_bytesPerSample;
  304. while (sample_size > 0)
  305. {
  306. int bytes_processed = m_Encoder.Encode((short *)pSourceBuffer, sample_size);
  307. if (bytes_processed <= 0)
  308. return S_OK;
  309. FlushEncodedSamples();
  310. sample_size -= bytes_processed;
  311. pSourceBuffer += bytes_processed;
  312. }
  313. return S_OK;
  314. }
  315. HRESULT CMpegAudEnc::FlushEncodedSamples()
  316. {
  317. IMediaSample * pOutSample = NULL;
  318. BYTE * pDst = NULL;
  319. if(m_bStreamOutput)
  320. {
  321. HRESULT hr = S_OK;
  322. const unsigned char * pblock = NULL;
  323. int iBufferSize;
  324. int iBlockLength = m_Encoder.GetBlockAligned(&pblock, &iBufferSize, m_cbStreamAlignment);
  325. if(!iBlockLength)
  326. return S_OK;
  327. hr = m_pOutput->GetDeliveryBuffer(&pOutSample, NULL, NULL, 0);
  328. if (hr == S_OK && pOutSample)
  329. {
  330. hr = pOutSample->GetPointer(&pDst);
  331. if (hr == S_OK && pDst)
  332. {
  333. CopyMemory(pDst, pblock, iBlockLength);
  334. REFERENCE_TIME rtEndPos = m_rtBytePos + iBufferSize;
  335. EXECUTE_ASSERT(S_OK == pOutSample->SetTime(&m_rtBytePos, &rtEndPos));
  336. pOutSample->SetActualDataLength(iBufferSize);
  337. m_rtBytePos += iBlockLength;
  338. m_pOutput->Deliver(pOutSample);
  339. }
  340. pOutSample->Release();
  341. }
  342. return S_OK;
  343. }
  344. if (m_rtStreamTime < 0)
  345. m_rtStreamTime = 0;
  346. while (1)
  347. {
  348. const unsigned char * pframe = NULL;
  349. int frame_size = m_Encoder.GetFrame(&pframe);
  350. if (frame_size <= 0 || !pframe)
  351. break;
  352. if (!m_sync[m_sync_out_idx].applied && m_sync[m_sync_out_idx].sample <= m_samplesOut)
  353. {
  354. m_rtStreamTime += m_sync[m_sync_out_idx].delta;
  355. m_sync[m_sync_out_idx].applied = TRUE;
  356. if (m_sync_out_idx < (RESYNC_COUNT - 1))
  357. m_sync_out_idx++;
  358. else
  359. m_sync_out_idx = 0;
  360. }
  361. REFERENCE_TIME rtStart = m_rtStreamTime;
  362. REFERENCE_TIME rtStop = rtStart + m_rtFrameTime;
  363. HRESULT hr = S_OK;
  364. hr = m_pOutput->GetDeliveryBuffer(&pOutSample, NULL, NULL, 0);
  365. if (hr == S_OK && pOutSample)
  366. {
  367. hr = pOutSample->GetPointer(&pDst);
  368. if (hr == S_OK && pDst)
  369. {
  370. CopyMemory(pDst, pframe, frame_size);
  371. pOutSample->SetActualDataLength(frame_size);
  372. pOutSample->SetSyncPoint(TRUE);
  373. pOutSample->SetTime(&rtStart, m_setDuration ? &rtStop : NULL);
  374. m_pOutput->Deliver(pOutSample);
  375. }
  376. pOutSample->Release();
  377. }
  378. m_samplesOut += m_samplesPerFrame;
  379. m_rtStreamTime = rtStop;
  380. }
  381. return S_OK;
  382. }
  383. ////////////////////////////////////////////////////////////////////////////
  384. // StartStreaming - prepare to receive new data
  385. ////////////////////////////////////////////////////////////////////////////
  386. HRESULT CMpegAudEnc::StartStreaming()
  387. {
  388. WAVEFORMATEX * pwfxIn = (WAVEFORMATEX *) m_pInput->CurrentMediaType().Format();
  389. m_bytesPerSample = pwfxIn->nChannels * sizeof(short);
  390. DWORD dwOutSampleRate;
  391. if(MEDIATYPE_Stream == m_pOutput->CurrentMediaType().majortype)
  392. {
  393. MPEG_ENCODER_CONFIG mcfg;
  394. if(FAILED(m_Encoder.GetOutputType(&mcfg)))
  395. return E_FAIL;
  396. dwOutSampleRate = mcfg.dwSampleRate;
  397. }
  398. else
  399. {
  400. dwOutSampleRate = ((WAVEFORMATEX *) m_pOutput->CurrentMediaType().Format())->nSamplesPerSec;
  401. }
  402. m_samplesPerFrame = (dwOutSampleRate >= 32000) ? 1152 : 576;
  403. m_rtFrameTime = MulDiv(10000000, m_samplesPerFrame, dwOutSampleRate);
  404. m_samplesIn = m_samplesOut = 0;
  405. m_rtStreamTime = -1;
  406. m_rtBytePos = 0;
  407. // initialize encoder
  408. m_Encoder.Init();
  409. m_hasFinished = FALSE;
  410. for (int i = 0; i < RESYNC_COUNT; i++)
  411. {
  412. m_sync[i].sample = 0;
  413. m_sync[i].delta = 0;
  414. m_sync[i].applied = TRUE;
  415. }
  416. m_sync_in_idx = 0;
  417. m_sync_out_idx = 0;
  418. get_SetDuration(&m_setDuration);
  419. get_SampleOverlap(&m_allowOverlap);
  420. return S_OK;
  421. }
  422. HRESULT CMpegAudEnc::StopStreaming()
  423. {
  424. IStream *pStream = NULL;
  425. if(m_bStreamOutput && m_pOutput->IsConnected() != FALSE)
  426. {
  427. IPin * pDwnstrmInputPin = m_pOutput->GetConnected();
  428. if(pDwnstrmInputPin && FAILED(pDwnstrmInputPin->QueryInterface(IID_IStream, (LPVOID*)(&pStream))))
  429. {
  430. pStream = NULL;
  431. }
  432. }
  433. m_Encoder.Close(pStream);
  434. if(pStream)
  435. pStream->Release();
  436. return S_OK;
  437. }
  438. ////////////////////////////////////////////////////////////////////////////
  439. // EndOfStream - stop data processing
  440. ////////////////////////////////////////////////////////////////////////////
  441. HRESULT CMpegAudEnc::EndOfStream()
  442. {
  443. CAutoLock lock(&m_cs);
  444. // Flush data
  445. m_Encoder.Finish();
  446. FlushEncodedSamples();
  447. IStream *pStream = NULL;
  448. if(m_bStreamOutput && m_pOutput->IsConnected() != FALSE)
  449. {
  450. IPin * pDwnstrmInputPin = m_pOutput->GetConnected();
  451. if(pDwnstrmInputPin)
  452. {
  453. if(FAILED(pDwnstrmInputPin->QueryInterface(IID_IStream, (LPVOID*)(&pStream))))
  454. {
  455. pStream = NULL;
  456. }
  457. }
  458. }
  459. if(pStream)
  460. {
  461. ULARGE_INTEGER size;
  462. size.QuadPart = m_rtBytePos;
  463. pStream->SetSize(size);
  464. }
  465. m_Encoder.Close(pStream);
  466. if(pStream)
  467. pStream->Release();
  468. m_hasFinished = TRUE;
  469. return CTransformFilter::EndOfStream();
  470. }
  471. ////////////////////////////////////////////////////////////////////////////
  472. // BeginFlush - stop data processing
  473. ////////////////////////////////////////////////////////////////////////////
  474. HRESULT CMpegAudEnc::BeginFlush()
  475. {
  476. HRESULT hr = CTransformFilter::BeginFlush();
  477. if (SUCCEEDED(hr))
  478. {
  479. CAutoLock lock(&m_cs);
  480. DWORD dwDstSize = 0;
  481. // Flush data
  482. m_Encoder.Finish();
  483. FlushEncodedSamples();
  484. IStream *pStream = NULL;
  485. if(m_bStreamOutput && m_pOutput->IsConnected() != FALSE)
  486. {
  487. IPin * pDwnstrmInputPin = m_pOutput->GetConnected();
  488. if(pDwnstrmInputPin && SUCCEEDED(pDwnstrmInputPin->QueryInterface(IID_IStream, (LPVOID*)(&pStream))))
  489. {
  490. ULARGE_INTEGER size;
  491. size.QuadPart = m_rtBytePos;
  492. pStream->SetSize(size);
  493. pStream->Release();
  494. }
  495. }
  496. m_rtStreamTime = -1;
  497. m_rtBytePos = 0;
  498. }
  499. return hr;
  500. }
  501. ////////////////////////////////////////////////////////////////////////////
  502. // SetMediaType - called when filters are connecting
  503. ////////////////////////////////////////////////////////////////////////////
  504. HRESULT CMpegAudEnc::SetMediaType(PIN_DIRECTION direction, const CMediaType * pmt)
  505. {
  506. HRESULT hr = S_OK;
  507. if (direction == PINDIR_INPUT)
  508. {
  509. if (*pmt->FormatType() != FORMAT_WaveFormatEx)
  510. return VFW_E_INVALIDMEDIATYPE;
  511. if (pmt->FormatLength() < sizeof(WAVEFORMATEX))
  512. return VFW_E_INVALIDMEDIATYPE;
  513. DbgLog((LOG_TRACE,1,TEXT("CMpegAudEnc::SetMediaType(), direction = PINDIR_INPUT")));
  514. // Pass input media type to encoder
  515. m_Encoder.SetInputType((LPWAVEFORMATEX)pmt->Format());
  516. WAVEFORMATEX * pwfx = (WAVEFORMATEX *)pmt->Format();
  517. if (pwfx)
  518. m_bytesToDuration = (float)1.e7 / (float)(pwfx->nChannels * sizeof(short) * pwfx->nSamplesPerSec);
  519. else
  520. m_bytesToDuration = 0.0;
  521. // Parse the encoder output capabilities into the subset of capabilities that are supported
  522. // for the current input format. This listing will be utilized by the IAMStreamConfig Interface.
  523. LoadOutputCapabilities(pwfx->nSamplesPerSec);
  524. Reconnect();
  525. }
  526. else if (direction == PINDIR_OUTPUT)
  527. {
  528. // Before we set the output type, we might need to reconnect
  529. // the input pin with a new type.
  530. if (m_pInput && m_pInput->IsConnected())
  531. {
  532. // Check if the current input type is compatible.
  533. hr = CheckTransform(&m_pInput->CurrentMediaType(), &m_pOutput->CurrentMediaType());
  534. if (FAILED(hr)) {
  535. // We need to reconnect the input pin.
  536. // Note: The CheckMediaType method has already called QueryAccept on the upstream filter.
  537. hr = m_pGraph->Reconnect(m_pInput);
  538. return hr;
  539. }
  540. }
  541. // WAVEFORMATEX wfIn;
  542. // m_Encoder.GetInputType(&wfIn);
  543. // if (wfIn.nSamplesPerSec %
  544. // ((LPWAVEFORMATEX)pmt->Format())->nSamplesPerSec != 0)
  545. // return VFW_E_TYPE_NOT_ACCEPTED;
  546. }
  547. return hr;
  548. }
  549. ////////////////////////////////////////////////////////////////////////////
  550. // CheckInputType - check if you can support mtIn
  551. ////////////////////////////////////////////////////////////////////////////
  552. HRESULT CMpegAudEnc::CheckInputType(const CMediaType* mtIn)
  553. {
  554. if (*mtIn->Type() == MEDIATYPE_Audio && *mtIn->FormatType() == FORMAT_WaveFormatEx)
  555. if (mtIn->FormatLength() >= sizeof(WAVEFORMATEX))
  556. if (mtIn->IsTemporalCompressed() == FALSE)
  557. return m_Encoder.SetInputType((LPWAVEFORMATEX)mtIn->Format(), true);
  558. return E_INVALIDARG;
  559. }
  560. ////////////////////////////////////////////////////////////////////////////
  561. // CheckTransform - checks if we can support the transform from this input to this output
  562. ////////////////////////////////////////////////////////////////////////////
  563. HRESULT CMpegAudEnc::CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut)
  564. {
  565. if(MEDIATYPE_Stream != mtOut->majortype)
  566. {
  567. if (*mtOut->FormatType() != FORMAT_WaveFormatEx)
  568. return VFW_E_INVALIDMEDIATYPE;
  569. if (mtOut->FormatLength() < sizeof(WAVEFORMATEX))
  570. return VFW_E_INVALIDMEDIATYPE;
  571. MPEG_ENCODER_CONFIG mec;
  572. if(FAILED(m_Encoder.GetOutputType(&mec)))
  573. return S_OK;
  574. if (((LPWAVEFORMATEX)mtIn->Format())->nSamplesPerSec % mec.dwSampleRate != 0)
  575. return S_OK;
  576. if (mec.dwSampleRate != ((LPWAVEFORMATEX)mtOut->Format())->nSamplesPerSec)
  577. return VFW_E_TYPE_NOT_ACCEPTED;
  578. return S_OK;
  579. }
  580. else if(mtOut->subtype == MEDIASUBTYPE_MPEG1Audio)
  581. return S_OK;
  582. return VFW_E_TYPE_NOT_ACCEPTED;
  583. }
  584. ////////////////////////////////////////////////////////////////////////////
  585. // DecideBufferSize - sets output buffers number and size
  586. ////////////////////////////////////////////////////////////////////////////
  587. HRESULT CMpegAudEnc::DecideBufferSize(
  588. IMemAllocator* pAllocator,
  589. ALLOCATOR_PROPERTIES* pProperties)
  590. {
  591. HRESULT hr = S_OK;
  592. if(m_bStreamOutput)
  593. m_cbStreamAlignment = pProperties->cbAlign;
  594. ///
  595. if (pProperties->cBuffers == 0) pProperties->cBuffers = 1; // If downstream filter didn't suggest a buffer count then default to 1
  596. pProperties->cbBuffer = OUT_BUFFER_SIZE;
  597. //
  598. ASSERT(pProperties->cbBuffer);
  599. ALLOCATOR_PROPERTIES Actual;
  600. hr = pAllocator->SetProperties(pProperties,&Actual);
  601. if(FAILED(hr))
  602. return hr;
  603. if (Actual.cbBuffer < pProperties->cbBuffer ||
  604. Actual.cBuffers < pProperties->cBuffers)
  605. {// can't use this allocator
  606. return E_INVALIDARG;
  607. }
  608. return S_OK;
  609. }
  610. ////////////////////////////////////////////////////////////////////////////
  611. // GetMediaType - overrideable for suggesting output pin media types
  612. ////////////////////////////////////////////////////////////////////////////
  613. HRESULT CMpegAudEnc::GetMediaType(int iPosition, CMediaType *pMediaType)
  614. {
  615. DbgLog((LOG_TRACE,1,TEXT("CMpegAudEnc::GetMediaType()")));
  616. return m_pOutput->GetMediaType(iPosition, pMediaType);
  617. }
  618. ////////////////////////////////////////////////////////////////////////////
  619. // Reconnect - called after a manual change has been made to the
  620. // encoder parameters to reset the filter output media type structure
  621. // to match the current encoder out MPEG audio properties
  622. ////////////////////////////////////////////////////////////////////////////
  623. HRESULT CMpegAudEnc::Reconnect()
  624. {
  625. HRESULT hr = S_FALSE;
  626. if (m_pOutput && m_pOutput->IsConnected() && m_State == State_Stopped)
  627. {
  628. MPEG_ENCODER_CONFIG mec;
  629. hr = m_Encoder.GetOutputType(&mec);
  630. if ((hr = m_Encoder.SetOutputType(mec)) == S_OK)
  631. {
  632. // Create an updated output MediaType using the current encoder settings
  633. CMediaType cmt;
  634. cmt.InitMediaType();
  635. m_pOutput->GetMediaType(m_currentMediaTypeIndex, &cmt);
  636. // If the updated MediaType matches the current output MediaType no reconnect is needed
  637. if (m_pOutput->CurrentMediaType() == cmt) return S_OK;
  638. // Attempt to reconnect the output pin using the updated MediaType
  639. if (S_OK == (hr = m_pOutput->GetConnected()->QueryAccept(&cmt))) {
  640. hr = m_pOutput->SetMediaType(&cmt);
  641. if ( FAILED(hr) ) { return(hr); }
  642. hr = m_pGraph->Reconnect(m_pOutput);
  643. }
  644. else
  645. hr = m_pOutput->SetMediaType(&cmt);
  646. }
  647. }
  648. return hr;
  649. }
  650. ////////////////////////////////////////////////////////////////////////////
  651. // LoadOutputCapabilities - create a list of the currently supported output
  652. // format capabilities which will be used by the IAMStreamConfig Interface
  653. ////////////////////////////////////////////////////////////////////////////
  654. void CMpegAudEnc::LoadOutputCapabilities(DWORD sample_rate)
  655. {
  656. m_CapsNum = 0;
  657. // Clear out any existing output capabilities
  658. ZeroMemory(OutputCaps, sizeof(OutputCaps));
  659. // Create the set of Constant Bit Rate output capabilities that are
  660. // supported for the current input pin sampling rate.
  661. for (int i = 0; i < NUMELMS(OutputCapabilities); i++) {
  662. if (0 == sample_rate % OutputCapabilities[i].nSampleRate) {
  663. // Add this output capability to the OutputCaps list
  664. OutputCaps[m_CapsNum] = OutputCapabilities[i];
  665. m_CapsNum++;
  666. // Don't overrun the hard-coded capabilities array limit
  667. if (m_CapsNum > (int)MAX_IAMSTREAMCONFIG_CAPS) break;
  668. }
  669. }
  670. }
  671. //
  672. // Read persistent configuration from Registry
  673. //
  674. void CMpegAudEnc::ReadPresetSettings(MPEG_ENCODER_CONFIG * pmec)
  675. {
  676. DbgLog((LOG_TRACE,1,TEXT("CMpegAudEnc::ReadPresetSettings()")));
  677. Lame::CRegKey rk(HKEY_CURRENT_USER, KEY_LAME_ENCODER);
  678. pmec->dwBitrate = rk.getDWORD(VALUE_BITRATE,DEFAULT_BITRATE);
  679. pmec->dwVariableMin = rk.getDWORD(VALUE_VARIABLEMIN,DEFAULT_VARIABLEMIN);
  680. pmec->dwVariableMax = rk.getDWORD(VALUE_VARIABLEMAX,DEFAULT_VARIABLEMAX);
  681. pmec->vmVariable = rk.getDWORD(VALUE_VARIABLE, DEFAULT_VARIABLE) ? vbr_rh : vbr_off;
  682. pmec->dwQuality = rk.getDWORD(VALUE_QUALITY,DEFAULT_ENCODING_QUALITY);
  683. pmec->dwVBRq = rk.getDWORD(VALUE_VBR_QUALITY,DEFAULT_VBR_QUALITY);
  684. pmec->lLayer = rk.getDWORD(VALUE_LAYER, DEFAULT_LAYER);
  685. pmec->bCRCProtect = rk.getDWORD(VALUE_CRC, DEFAULT_CRC);
  686. pmec->bForceMono = rk.getDWORD(VALUE_FORCE_MONO, DEFAULT_FORCE_MONO);
  687. pmec->bSetDuration = rk.getDWORD(VALUE_SET_DURATION, DEFAULT_SET_DURATION);
  688. pmec->bSampleOverlap = rk.getDWORD(VALUE_SAMPLE_OVERLAP, DEFAULT_SAMPLE_OVERLAP);
  689. pmec->bCopyright = rk.getDWORD(VALUE_COPYRIGHT, DEFAULT_COPYRIGHT);
  690. pmec->bOriginal = rk.getDWORD(VALUE_ORIGINAL, DEFAULT_ORIGINAL);
  691. pmec->dwSampleRate = rk.getDWORD(VALUE_SAMPLE_RATE, DEFAULT_SAMPLE_RATE);
  692. pmec->dwPES = rk.getDWORD(VALUE_PES, DEFAULT_PES);
  693. pmec->ChMode = (MPEG_mode)rk.getDWORD(VALUE_STEREO_MODE, DEFAULT_STEREO_MODE);
  694. pmec->dwForceMS = rk.getDWORD(VALUE_FORCE_MS, DEFAULT_FORCE_MS);
  695. pmec->dwEnforceVBRmin = rk.getDWORD(VALUE_ENFORCE_MIN, DEFAULT_ENFORCE_MIN);
  696. pmec->dwVoiceMode = rk.getDWORD(VALUE_VOICE, DEFAULT_VOICE);
  697. pmec->dwKeepAllFreq = rk.getDWORD(VALUE_KEEP_ALL_FREQ, DEFAULT_KEEP_ALL_FREQ);
  698. pmec->dwStrictISO = rk.getDWORD(VALUE_STRICT_ISO, DEFAULT_STRICT_ISO);
  699. pmec->dwNoShortBlock = rk.getDWORD(VALUE_DISABLE_SHORT_BLOCK, DEFAULT_DISABLE_SHORT_BLOCK);
  700. pmec->dwXingTag = rk.getDWORD(VALUE_XING_TAG, DEFAULT_XING_TAG);
  701. pmec->dwModeFixed = rk.getDWORD(VALUE_MODE_FIXED, DEFAULT_MODE_FIXED);
  702. rk.Close();
  703. }
  704. ////////////////////////////////////////////////////////////////
  705. // Property page handling
  706. ////////////////////////////////////////////////////////////////
  707. HRESULT CMpegAudEnc::GetPages(CAUUID *pcauuid)
  708. {
  709. GUID *pguid;
  710. pcauuid->cElems = 3;
  711. pcauuid->pElems = pguid = (GUID *) CoTaskMemAlloc(sizeof(GUID) * pcauuid->cElems);
  712. if (pcauuid->pElems == NULL)
  713. return E_OUTOFMEMORY;
  714. pguid[0] = CLSID_LAMEDShow_PropertyPage;
  715. pguid[1] = CLSID_LAMEDShow_PropertyPageAdv;
  716. pguid[2] = CLSID_LAMEDShow_About;
  717. return S_OK;
  718. }
  719. STDMETHODIMP CMpegAudEnc::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
  720. {
  721. if (riid == IID_ISpecifyPropertyPages)
  722. return GetInterface((ISpecifyPropertyPages *) this, ppv);
  723. else if(riid == IID_IPersistStream)
  724. return GetInterface((IPersistStream *)this, ppv);
  725. // else if (riid == IID_IVAudioEncSettings)
  726. // return GetInterface((IVAudioEncSettings*) this, ppv);
  727. else if (riid == IID_IAudioEncoderProperties)
  728. return GetInterface((IAudioEncoderProperties*) this, ppv);
  729. return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
  730. }
  731. ////////////////////////////////////////////////////////////////
  732. //IVAudioEncSettings interface methods
  733. ////////////////////////////////////////////////////////////////
  734. //
  735. // IAudioEncoderProperties
  736. //
  737. STDMETHODIMP CMpegAudEnc::get_PESOutputEnabled(DWORD *dwEnabled)
  738. {
  739. *dwEnabled = (DWORD)m_Encoder.IsPES();
  740. DbgLog((LOG_TRACE, 1, TEXT("get_PESOutputEnabled -> %d"), *dwEnabled));
  741. return S_OK;
  742. }
  743. STDMETHODIMP CMpegAudEnc::set_PESOutputEnabled(DWORD dwEnabled)
  744. {
  745. m_Encoder.SetPES((BOOL)!!dwEnabled);
  746. DbgLog((LOG_TRACE, 1, TEXT("set_PESOutputEnabled(%d)"), !!dwEnabled));
  747. return S_OK;
  748. }
  749. STDMETHODIMP CMpegAudEnc::get_MPEGLayer(DWORD *dwLayer)
  750. {
  751. MPEG_ENCODER_CONFIG mec;
  752. m_Encoder.GetOutputType(&mec);
  753. *dwLayer = (DWORD)mec.lLayer;
  754. DbgLog((LOG_TRACE, 1, TEXT("get_MPEGLayer -> %d"), *dwLayer));
  755. return S_OK;
  756. }
  757. STDMETHODIMP CMpegAudEnc::set_MPEGLayer(DWORD dwLayer)
  758. {
  759. MPEG_ENCODER_CONFIG mec;
  760. m_Encoder.GetOutputType(&mec);
  761. if (dwLayer == 2)
  762. mec.lLayer = 2;
  763. else if (dwLayer == 1)
  764. mec.lLayer = 1;
  765. m_Encoder.SetOutputType(mec);
  766. DbgLog((LOG_TRACE, 1, TEXT("set_MPEGLayer(%d)"), dwLayer));
  767. return S_OK;
  768. }
  769. STDMETHODIMP CMpegAudEnc::get_Bitrate(DWORD *dwBitrate)
  770. {
  771. MPEG_ENCODER_CONFIG mec;
  772. m_Encoder.GetOutputType(&mec);
  773. *dwBitrate = (DWORD)mec.dwBitrate;
  774. DbgLog((LOG_TRACE, 1, TEXT("get_Bitrate -> %d"), *dwBitrate));
  775. return S_OK;
  776. }
  777. STDMETHODIMP CMpegAudEnc::set_Bitrate(DWORD dwBitrate)
  778. {
  779. MPEG_ENCODER_CONFIG mec;
  780. m_Encoder.GetOutputType(&mec);
  781. mec.dwBitrate = dwBitrate;
  782. m_Encoder.SetOutputType(mec);
  783. DbgLog((LOG_TRACE, 1, TEXT("set_Bitrate(%d)"), dwBitrate));
  784. return S_OK;
  785. }
  786. STDMETHODIMP CMpegAudEnc::get_Variable(DWORD *dwVariable)
  787. {
  788. MPEG_ENCODER_CONFIG mec;
  789. m_Encoder.GetOutputType(&mec);
  790. *dwVariable = (DWORD)(mec.vmVariable == vbr_off ? 0 : 1);
  791. DbgLog((LOG_TRACE, 1, TEXT("get_Variable -> %d"), *dwVariable));
  792. return S_OK;
  793. }
  794. STDMETHODIMP CMpegAudEnc::set_Variable(DWORD dwVariable)
  795. {
  796. MPEG_ENCODER_CONFIG mec;
  797. m_Encoder.GetOutputType(&mec);
  798. mec.vmVariable = dwVariable ? vbr_rh : vbr_off;
  799. m_Encoder.SetOutputType(mec);
  800. DbgLog((LOG_TRACE, 1, TEXT("set_Variable(%d)"), dwVariable));
  801. return S_OK;
  802. }
  803. STDMETHODIMP CMpegAudEnc::get_VariableMin(DWORD *dwMin)
  804. {
  805. MPEG_ENCODER_CONFIG mec;
  806. m_Encoder.GetOutputType(&mec);
  807. *dwMin = (DWORD)mec.dwVariableMin;
  808. DbgLog((LOG_TRACE, 1, TEXT("get_Variablemin -> %d"), *dwMin));
  809. return S_OK;
  810. }
  811. STDMETHODIMP CMpegAudEnc::set_VariableMin(DWORD dwMin)
  812. {
  813. MPEG_ENCODER_CONFIG mec;
  814. m_Encoder.GetOutputType(&mec);
  815. mec.dwVariableMin = dwMin;
  816. m_Encoder.SetOutputType(mec);
  817. DbgLog((LOG_TRACE, 1, TEXT("set_Variablemin(%d)"), dwMin));
  818. return S_OK;
  819. }
  820. STDMETHODIMP CMpegAudEnc::get_VariableMax(DWORD *dwMax)
  821. {
  822. MPEG_ENCODER_CONFIG mec;
  823. m_Encoder.GetOutputType(&mec);
  824. *dwMax = (DWORD)mec.dwVariableMax;
  825. DbgLog((LOG_TRACE, 1, TEXT("get_Variablemax -> %d"), *dwMax));
  826. return S_OK;
  827. }
  828. STDMETHODIMP CMpegAudEnc::set_VariableMax(DWORD dwMax)
  829. {
  830. MPEG_ENCODER_CONFIG mec;
  831. m_Encoder.GetOutputType(&mec);
  832. mec.dwVariableMax = dwMax;
  833. m_Encoder.SetOutputType(mec);
  834. DbgLog((LOG_TRACE, 1, TEXT("set_Variablemax(%d)"), dwMax));
  835. return S_OK;
  836. }
  837. STDMETHODIMP CMpegAudEnc::get_Quality(DWORD *dwQuality)
  838. {
  839. MPEG_ENCODER_CONFIG mec;
  840. m_Encoder.GetOutputType(&mec);
  841. *dwQuality=(DWORD)mec.dwQuality;
  842. DbgLog((LOG_TRACE, 1, TEXT("get_Quality -> %d"), *dwQuality));
  843. return S_OK;
  844. }
  845. STDMETHODIMP CMpegAudEnc::set_Quality(DWORD dwQuality)
  846. {
  847. MPEG_ENCODER_CONFIG mec;
  848. m_Encoder.GetOutputType(&mec);
  849. mec.dwQuality = dwQuality;
  850. m_Encoder.SetOutputType(mec);
  851. DbgLog((LOG_TRACE, 1, TEXT("set_Quality(%d)"), dwQuality));
  852. return S_OK;
  853. }
  854. STDMETHODIMP CMpegAudEnc::get_VariableQ(DWORD *dwVBRq)
  855. {
  856. MPEG_ENCODER_CONFIG mec;
  857. m_Encoder.GetOutputType(&mec);
  858. *dwVBRq=(DWORD)mec.dwVBRq;
  859. DbgLog((LOG_TRACE, 1, TEXT("get_VariableQ -> %d"), *dwVBRq));
  860. return S_OK;
  861. }
  862. STDMETHODIMP CMpegAudEnc::set_VariableQ(DWORD dwVBRq)
  863. {
  864. MPEG_ENCODER_CONFIG mec;
  865. m_Encoder.GetOutputType(&mec);
  866. mec.dwVBRq = dwVBRq;
  867. m_Encoder.SetOutputType(mec);
  868. DbgLog((LOG_TRACE, 1, TEXT("set_VariableQ(%d)"), dwVBRq));
  869. return S_OK;
  870. }
  871. STDMETHODIMP CMpegAudEnc::get_SourceSampleRate(DWORD *dwSampleRate)
  872. {
  873. *dwSampleRate = 0;
  874. WAVEFORMATEX wf;
  875. if(FAILED(m_Encoder.GetInputType(&wf)))
  876. return E_FAIL;
  877. *dwSampleRate = wf.nSamplesPerSec;
  878. DbgLog((LOG_TRACE, 1, TEXT("get_SourceSampleRate -> %d"), *dwSampleRate));
  879. return S_OK;
  880. }
  881. STDMETHODIMP CMpegAudEnc::get_SourceChannels(DWORD *dwChannels)
  882. {
  883. WAVEFORMATEX wf;
  884. if(FAILED(m_Encoder.GetInputType(&wf)))
  885. return E_FAIL;
  886. *dwChannels = wf.nChannels;
  887. DbgLog((LOG_TRACE, 1, TEXT("get_SourceChannels -> %d"), *dwChannels));
  888. return S_OK;
  889. }
  890. STDMETHODIMP CMpegAudEnc::get_SampleRate(DWORD *dwSampleRate)
  891. {
  892. MPEG_ENCODER_CONFIG mec;
  893. m_Encoder.GetOutputType(&mec);
  894. *dwSampleRate = mec.dwSampleRate;
  895. DbgLog((LOG_TRACE, 1, TEXT("get_SampleRate -> %d"), *dwSampleRate));
  896. return S_OK;
  897. }
  898. STDMETHODIMP CMpegAudEnc::set_SampleRate(DWORD dwSampleRate)
  899. {
  900. MPEG_ENCODER_CONFIG mec;
  901. m_Encoder.GetOutputType(&mec);
  902. DWORD dwOldSampleRate = mec.dwSampleRate;
  903. mec.dwSampleRate = dwSampleRate;
  904. m_Encoder.SetOutputType(mec);
  905. DbgLog((LOG_TRACE, 1, TEXT("set_SampleRate(%d)"), dwSampleRate));
  906. return S_OK;
  907. }
  908. STDMETHODIMP CMpegAudEnc::get_ChannelMode(DWORD *dwChannelMode)
  909. {
  910. MPEG_ENCODER_CONFIG mec;
  911. m_Encoder.GetOutputType(&mec);
  912. *dwChannelMode = mec.ChMode;
  913. DbgLog((LOG_TRACE, 1, TEXT("get_ChannelMode -> %d"), *dwChannelMode));
  914. return S_OK;
  915. }
  916. STDMETHODIMP CMpegAudEnc::set_ChannelMode(DWORD dwChannelMode)
  917. {
  918. MPEG_ENCODER_CONFIG mec;
  919. m_Encoder.GetOutputType(&mec);
  920. mec.ChMode = (MPEG_mode)dwChannelMode;
  921. m_Encoder.SetOutputType(mec);
  922. DbgLog((LOG_TRACE, 1, TEXT("set_ChannelMode(%d)"), dwChannelMode));
  923. return S_OK;
  924. }
  925. STDMETHODIMP CMpegAudEnc::get_ForceMS(DWORD *dwFlag)
  926. {
  927. MPEG_ENCODER_CONFIG mec;
  928. m_Encoder.GetOutputType(&mec);
  929. *dwFlag = mec.dwForceMS;
  930. DbgLog((LOG_TRACE, 1, TEXT("get_ForceMS -> %d"), *dwFlag));
  931. return S_OK;
  932. }
  933. STDMETHODIMP CMpegAudEnc::set_ForceMS(DWORD dwFlag)
  934. {
  935. MPEG_ENCODER_CONFIG mec;
  936. m_Encoder.GetOutputType(&mec);
  937. mec.dwForceMS = dwFlag;
  938. m_Encoder.SetOutputType(mec);
  939. DbgLog((LOG_TRACE, 1, TEXT("set_ForceMS(%d)"), dwFlag));
  940. return S_OK;
  941. }
  942. STDMETHODIMP CMpegAudEnc::get_CRCFlag(DWORD *dwFlag)
  943. {
  944. MPEG_ENCODER_CONFIG mec;
  945. m_Encoder.GetOutputType(&mec);
  946. *dwFlag = mec.bCRCProtect;
  947. DbgLog((LOG_TRACE, 1, TEXT("get_CRCFlag -> %d"), *dwFlag));
  948. return S_OK;
  949. }
  950. STDMETHODIMP CMpegAudEnc::get_ForceMono(DWORD *dwFlag)
  951. {
  952. MPEG_ENCODER_CONFIG mec;
  953. m_Encoder.GetOutputType(&mec);
  954. *dwFlag = mec.bForceMono;
  955. DbgLog((LOG_TRACE, 1, TEXT("get_ForceMono -> %d"), *dwFlag));
  956. return S_OK;
  957. }
  958. STDMETHODIMP CMpegAudEnc::get_SetDuration(DWORD *dwFlag)
  959. {
  960. MPEG_ENCODER_CONFIG mec;
  961. m_Encoder.GetOutputType(&mec);
  962. *dwFlag = mec.bSetDuration;
  963. DbgLog((LOG_TRACE, 1, TEXT("get_SetDuration -> %d"), *dwFlag));
  964. return S_OK;
  965. }
  966. STDMETHODIMP CMpegAudEnc::get_SampleOverlap(DWORD *dwFlag)
  967. {
  968. MPEG_ENCODER_CONFIG mec;
  969. m_Encoder.GetOutputType(&mec);
  970. *dwFlag = mec.bSampleOverlap;
  971. DbgLog((LOG_TRACE, 1, TEXT("get_SampleOverlap -> %d"), *dwFlag));
  972. return S_OK;
  973. }
  974. STDMETHODIMP CMpegAudEnc::set_CRCFlag(DWORD dwFlag)
  975. {
  976. MPEG_ENCODER_CONFIG mec;
  977. m_Encoder.GetOutputType(&mec);
  978. mec.bCRCProtect = dwFlag;
  979. m_Encoder.SetOutputType(mec);
  980. DbgLog((LOG_TRACE, 1, TEXT("set_CRCFlag(%d)"), dwFlag));
  981. return S_OK;
  982. }
  983. STDMETHODIMP CMpegAudEnc::set_ForceMono(DWORD dwFlag)
  984. {
  985. MPEG_ENCODER_CONFIG mec;
  986. m_Encoder.GetOutputType(&mec);
  987. mec.bForceMono = dwFlag;
  988. m_Encoder.SetOutputType(mec);
  989. DbgLog((LOG_TRACE, 1, TEXT("set_ForceMono(%d)"), dwFlag));
  990. return S_OK;
  991. }
  992. STDMETHODIMP CMpegAudEnc::set_SetDuration(DWORD dwFlag)
  993. {
  994. MPEG_ENCODER_CONFIG mec;
  995. m_Encoder.GetOutputType(&mec);
  996. mec.bSetDuration = dwFlag;
  997. m_Encoder.SetOutputType(mec);
  998. DbgLog((LOG_TRACE, 1, TEXT("set_SetDuration(%d)"), dwFlag));
  999. return S_OK;
  1000. }
  1001. STDMETHODIMP CMpegAudEnc::set_SampleOverlap(DWORD dwFlag)
  1002. {
  1003. MPEG_ENCODER_CONFIG mec;
  1004. m_Encoder.GetOutputType(&mec);
  1005. mec.bSampleOverlap = dwFlag;
  1006. m_Encoder.SetOutputType(mec);
  1007. DbgLog((LOG_TRACE, 1, TEXT("set_SampleOverlap(%d)"), dwFlag));
  1008. return S_OK;
  1009. }
  1010. STDMETHODIMP CMpegAudEnc::get_EnforceVBRmin(DWORD *dwFlag)
  1011. {
  1012. MPEG_ENCODER_CONFIG mec;
  1013. m_Encoder.GetOutputType(&mec);
  1014. *dwFlag = mec.dwEnforceVBRmin;
  1015. DbgLog((LOG_TRACE, 1, TEXT("get_EnforceVBRmin -> %d"), *dwFlag));
  1016. return S_OK;
  1017. }
  1018. STDMETHODIMP CMpegAudEnc::set_EnforceVBRmin(DWORD dwFlag)
  1019. {
  1020. MPEG_ENCODER_CONFIG mec;
  1021. m_Encoder.GetOutputType(&mec);
  1022. mec.dwEnforceVBRmin = dwFlag;
  1023. m_Encoder.SetOutputType(mec);
  1024. DbgLog((LOG_TRACE, 1, TEXT("set_EnforceVBRmin(%d)"), dwFlag));
  1025. return S_OK;
  1026. }
  1027. STDMETHODIMP CMpegAudEnc::get_VoiceMode(DWORD *dwFlag)
  1028. {
  1029. MPEG_ENCODER_CONFIG mec;
  1030. m_Encoder.GetOutputType(&mec);
  1031. *dwFlag = mec.dwVoiceMode;
  1032. DbgLog((LOG_TRACE, 1, TEXT("get_VoiceMode -> %d"), *dwFlag));
  1033. return S_OK;
  1034. }
  1035. STDMETHODIMP CMpegAudEnc::set_VoiceMode(DWORD dwFlag)
  1036. {
  1037. MPEG_ENCODER_CONFIG mec;
  1038. m_Encoder.GetOutputType(&mec);
  1039. mec.dwVoiceMode = dwFlag;
  1040. m_Encoder.SetOutputType(mec);
  1041. DbgLog((LOG_TRACE, 1, TEXT("set_VoiceMode(%d)"), dwFlag));
  1042. return S_OK;
  1043. }
  1044. STDMETHODIMP CMpegAudEnc::get_KeepAllFreq(DWORD *dwFlag)
  1045. {
  1046. MPEG_ENCODER_CONFIG mec;
  1047. m_Encoder.GetOutputType(&mec);
  1048. *dwFlag = mec.dwKeepAllFreq;
  1049. DbgLog((LOG_TRACE, 1, TEXT("get_KeepAllFreq -> %d"), *dwFlag));
  1050. return S_OK;
  1051. }
  1052. STDMETHODIMP CMpegAudEnc::set_KeepAllFreq(DWORD dwFlag)
  1053. {
  1054. MPEG_ENCODER_CONFIG mec;
  1055. m_Encoder.GetOutputType(&mec);
  1056. mec.dwKeepAllFreq = dwFlag;
  1057. m_Encoder.SetOutputType(mec);
  1058. DbgLog((LOG_TRACE, 1, TEXT("set_KeepAllFreq(%d)"), dwFlag));
  1059. return S_OK;
  1060. }
  1061. STDMETHODIMP CMpegAudEnc::get_StrictISO(DWORD *dwFlag)
  1062. {
  1063. MPEG_ENCODER_CONFIG mec;
  1064. m_Encoder.GetOutputType(&mec);
  1065. *dwFlag = mec.dwStrictISO;
  1066. DbgLog((LOG_TRACE, 1, TEXT("get_StrictISO -> %d"), *dwFlag));
  1067. return S_OK;
  1068. }
  1069. STDMETHODIMP CMpegAudEnc::set_StrictISO(DWORD dwFlag)
  1070. {
  1071. MPEG_ENCODER_CONFIG mec;
  1072. m_Encoder.GetOutputType(&mec);
  1073. mec.dwStrictISO = dwFlag;
  1074. m_Encoder.SetOutputType(mec);
  1075. DbgLog((LOG_TRACE, 1, TEXT("set_StrictISO(%d)"), dwFlag));
  1076. return S_OK;
  1077. }
  1078. STDMETHODIMP CMpegAudEnc::get_NoShortBlock(DWORD *dwNoShortBlock)
  1079. {
  1080. MPEG_ENCODER_CONFIG mec;
  1081. m_Encoder.GetOutputType(&mec);
  1082. *dwNoShortBlock = mec.dwNoShortBlock;
  1083. DbgLog((LOG_TRACE, 1, TEXT("get_NoShortBlock -> %d"), *dwNoShortBlock));
  1084. return S_OK;
  1085. }
  1086. STDMETHODIMP CMpegAudEnc::set_NoShortBlock(DWORD dwNoShortBlock)
  1087. {
  1088. MPEG_ENCODER_CONFIG mec;
  1089. m_Encoder.GetOutputType(&mec);
  1090. mec.dwNoShortBlock = dwNoShortBlock;
  1091. m_Encoder.SetOutputType(mec);
  1092. DbgLog((LOG_TRACE, 1, TEXT("set_NoShortBlock(%d)"), dwNoShortBlock));
  1093. return S_OK;
  1094. }
  1095. STDMETHODIMP CMpegAudEnc::get_XingTag(DWORD *dwXingTag)
  1096. {
  1097. MPEG_ENCODER_CONFIG mec;
  1098. m_Encoder.GetOutputType(&mec);
  1099. *dwXingTag = mec.dwXingTag;
  1100. DbgLog((LOG_TRACE, 1, TEXT("get_XingTag -> %d"), *dwXingTag));
  1101. return S_OK;
  1102. }
  1103. STDMETHODIMP CMpegAudEnc::set_XingTag(DWORD dwXingTag)
  1104. {
  1105. MPEG_ENCODER_CONFIG mec;
  1106. m_Encoder.GetOutputType(&mec);
  1107. mec.dwXingTag = dwXingTag;
  1108. m_Encoder.SetOutputType(mec);
  1109. DbgLog((LOG_TRACE, 1, TEXT("set_XingTag(%d)"), dwXingTag));
  1110. return S_OK;
  1111. }
  1112. STDMETHODIMP CMpegAudEnc::get_OriginalFlag(DWORD *dwFlag)
  1113. {
  1114. MPEG_ENCODER_CONFIG mec;
  1115. m_Encoder.GetOutputType(&mec);
  1116. *dwFlag = mec.bOriginal;
  1117. DbgLog((LOG_TRACE, 1, TEXT("get_OriginalFlag -> %d"), *dwFlag));
  1118. return S_OK;
  1119. }
  1120. STDMETHODIMP CMpegAudEnc::set_OriginalFlag(DWORD dwFlag)
  1121. {
  1122. MPEG_ENCODER_CONFIG mec;
  1123. m_Encoder.GetOutputType(&mec);
  1124. mec.bOriginal = dwFlag;
  1125. m_Encoder.SetOutputType(mec);
  1126. DbgLog((LOG_TRACE, 1, TEXT("set_OriginalFlag(%d)"), dwFlag));
  1127. return S_OK;
  1128. }
  1129. STDMETHODIMP CMpegAudEnc::get_CopyrightFlag(DWORD *dwFlag)
  1130. {
  1131. MPEG_ENCODER_CONFIG mec;
  1132. m_Encoder.GetOutputType(&mec);
  1133. *dwFlag = mec.bCopyright;
  1134. DbgLog((LOG_TRACE, 1, TEXT("get_CopyrightFlag -> %d"), *dwFlag));
  1135. return S_OK;
  1136. }
  1137. STDMETHODIMP CMpegAudEnc::set_CopyrightFlag(DWORD dwFlag)
  1138. {
  1139. MPEG_ENCODER_CONFIG mec;
  1140. m_Encoder.GetOutputType(&mec);
  1141. mec.bCopyright = dwFlag;
  1142. m_Encoder.SetOutputType(mec);
  1143. DbgLog((LOG_TRACE, 1, TEXT("set_CopyrightFlag(%d)"), dwFlag));
  1144. return S_OK;
  1145. }
  1146. STDMETHODIMP CMpegAudEnc::get_ModeFixed(DWORD *dwModeFixed)
  1147. {
  1148. MPEG_ENCODER_CONFIG mec;
  1149. m_Encoder.GetOutputType(&mec);
  1150. *dwModeFixed = mec.dwModeFixed;
  1151. DbgLog((LOG_TRACE, 1, TEXT("get_ModeFixed -> %d"), *dwModeFixed));
  1152. return S_OK;
  1153. }
  1154. STDMETHODIMP CMpegAudEnc::set_ModeFixed(DWORD dwModeFixed)
  1155. {
  1156. MPEG_ENCODER_CONFIG mec;
  1157. m_Encoder.GetOutputType(&mec);
  1158. mec.dwModeFixed = dwModeFixed;
  1159. m_Encoder.SetOutputType(mec);
  1160. DbgLog((LOG_TRACE, 1, TEXT("set_ModeFixed(%d)"), dwModeFixed));
  1161. return S_OK;
  1162. }
  1163. STDMETHODIMP CMpegAudEnc::get_ParameterBlockSize(BYTE *pcBlock, DWORD *pdwSize)
  1164. {
  1165. DbgLog((LOG_TRACE, 1, TEXT("get_ParameterBlockSize -> %d%d"), *pcBlock, *pdwSize));
  1166. if (pcBlock != NULL) {
  1167. if (*pdwSize >= sizeof(MPEG_ENCODER_CONFIG)) {
  1168. m_Encoder.GetOutputType((MPEG_ENCODER_CONFIG*)pcBlock);
  1169. return S_OK;
  1170. }
  1171. else {
  1172. *pdwSize = sizeof(MPEG_ENCODER_CONFIG);
  1173. return E_FAIL;
  1174. }
  1175. }
  1176. else if (pdwSize != NULL) {
  1177. *pdwSize = sizeof(MPEG_ENCODER_CONFIG);
  1178. return S_OK;
  1179. }
  1180. return E_FAIL;
  1181. }
  1182. STDMETHODIMP CMpegAudEnc::set_ParameterBlockSize(BYTE *pcBlock, DWORD dwSize)
  1183. {
  1184. DbgLog((LOG_TRACE, 1, TEXT("get_ParameterBlockSize(%d, %d)"), *pcBlock, dwSize));
  1185. if (sizeof(MPEG_ENCODER_CONFIG) == dwSize){
  1186. m_Encoder.SetOutputType(*(MPEG_ENCODER_CONFIG*)pcBlock);
  1187. return S_OK;
  1188. }
  1189. else return E_FAIL;
  1190. }
  1191. STDMETHODIMP CMpegAudEnc::DefaultAudioEncoderProperties()
  1192. {
  1193. DbgLog((LOG_TRACE, 1, TEXT("DefaultAudioEncoderProperties()")));
  1194. HRESULT hr = InputTypeDefined();
  1195. if (FAILED(hr))
  1196. return hr;
  1197. DWORD dwSourceSampleRate;
  1198. get_SourceSampleRate(&dwSourceSampleRate);
  1199. set_PESOutputEnabled(DEFAULT_PES);
  1200. set_MPEGLayer(DEFAULT_LAYER);
  1201. set_Bitrate(DEFAULT_BITRATE);
  1202. set_Variable(FALSE);
  1203. set_VariableMin(DEFAULT_VARIABLEMIN);
  1204. set_VariableMax(DEFAULT_VARIABLEMAX);
  1205. set_Quality(DEFAULT_ENCODING_QUALITY);
  1206. set_VariableQ(DEFAULT_VBR_QUALITY);
  1207. set_SampleRate(dwSourceSampleRate);
  1208. set_CRCFlag(DEFAULT_CRC);
  1209. set_ForceMono(DEFAULT_FORCE_MONO);
  1210. set_SetDuration(DEFAULT_SET_DURATION);
  1211. set_SampleOverlap(DEFAULT_SAMPLE_OVERLAP);
  1212. set_OriginalFlag(DEFAULT_ORIGINAL);
  1213. set_CopyrightFlag(DEFAULT_COPYRIGHT);
  1214. set_EnforceVBRmin(DEFAULT_ENFORCE_MIN);
  1215. set_VoiceMode(DEFAULT_VOICE);
  1216. set_KeepAllFreq(DEFAULT_KEEP_ALL_FREQ);
  1217. set_StrictISO(DEFAULT_STRICT_ISO);
  1218. set_NoShortBlock(DEFAULT_DISABLE_SHORT_BLOCK);
  1219. set_XingTag(DEFAULT_XING_TAG);
  1220. set_ForceMS(DEFAULT_FORCE_MS);
  1221. set_ChannelMode(DEFAULT_STEREO_MODE);
  1222. set_ModeFixed(DEFAULT_MODE_FIXED);
  1223. return S_OK;
  1224. }
  1225. STDMETHODIMP CMpegAudEnc::LoadAudioEncoderPropertiesFromRegistry()
  1226. {
  1227. DbgLog((LOG_TRACE, 1, TEXT("LoadAudioEncoderPropertiesFromRegistry()")));
  1228. MPEG_ENCODER_CONFIG mec;
  1229. ReadPresetSettings(&mec);
  1230. if(m_Encoder.SetOutputType(mec) == S_FALSE)
  1231. return S_FALSE;
  1232. return S_OK;
  1233. }
  1234. STDMETHODIMP CMpegAudEnc::SaveAudioEncoderPropertiesToRegistry()
  1235. {
  1236. DbgLog((LOG_TRACE, 1, TEXT("SaveAudioEncoderPropertiesToRegistry()")));
  1237. Lame::CRegKey rk;
  1238. MPEG_ENCODER_CONFIG mec;
  1239. if(m_Encoder.GetOutputType(&mec) == S_FALSE)
  1240. return E_FAIL;
  1241. if(rk.Create(HKEY_CURRENT_USER, KEY_LAME_ENCODER))
  1242. {
  1243. rk.setDWORD(VALUE_BITRATE, mec.dwBitrate);
  1244. rk.setDWORD(VALUE_VARIABLE, mec.vmVariable);
  1245. rk.setDWORD(VALUE_VARIABLEMIN, mec.dwVariableMin);
  1246. rk.setDWORD(VALUE_VARIABLEMAX, mec.dwVariableMax);
  1247. rk.setDWORD(VALUE_QUALITY, mec.dwQuality);
  1248. rk.setDWORD(VALUE_VBR_QUALITY, mec.dwVBRq);
  1249. rk.setDWORD(VALUE_CRC, mec.bCRCProtect);
  1250. rk.setDWORD(VALUE_FORCE_MONO, mec.bForceMono);
  1251. rk.setDWORD(VALUE_SET_DURATION, mec.bSetDuration);
  1252. rk.setDWORD(VALUE_SAMPLE_OVERLAP, mec.bSampleOverlap);
  1253. rk.setDWORD(VALUE_PES, mec.dwPES);
  1254. rk.setDWORD(VALUE_COPYRIGHT, mec.bCopyright);
  1255. rk.setDWORD(VALUE_ORIGINAL, mec.bOriginal);
  1256. rk.setDWORD(VALUE_SAMPLE_RATE, mec.dwSampleRate);
  1257. rk.setDWORD(VALUE_STEREO_MODE, mec.ChMode);
  1258. rk.setDWORD(VALUE_FORCE_MS, mec.dwForceMS);
  1259. rk.setDWORD(VALUE_XING_TAG, mec.dwXingTag);
  1260. rk.setDWORD(VALUE_DISABLE_SHORT_BLOCK, mec.dwNoShortBlock);
  1261. rk.setDWORD(VALUE_STRICT_ISO, mec.dwStrictISO);
  1262. rk.setDWORD(VALUE_KEEP_ALL_FREQ, mec.dwKeepAllFreq);
  1263. rk.setDWORD(VALUE_VOICE, mec.dwVoiceMode);
  1264. rk.setDWORD(VALUE_ENFORCE_MIN, mec.dwEnforceVBRmin);
  1265. rk.setDWORD(VALUE_MODE_FIXED, mec.dwModeFixed);
  1266. rk.Close();
  1267. }
  1268. // Reconnect filter graph
  1269. Reconnect();
  1270. return S_OK;
  1271. }
  1272. STDMETHODIMP CMpegAudEnc::InputTypeDefined()
  1273. {
  1274. WAVEFORMATEX wf;
  1275. if(FAILED(m_Encoder.GetInputType(&wf)))
  1276. {
  1277. DbgLog((LOG_TRACE, 1, TEXT("!InputTypeDefined()")));
  1278. return E_FAIL;
  1279. }
  1280. DbgLog((LOG_TRACE, 1, TEXT("InputTypeDefined()")));
  1281. return S_OK;
  1282. }
  1283. STDMETHODIMP CMpegAudEnc::ApplyChanges()
  1284. {
  1285. return Reconnect();
  1286. }
  1287. //
  1288. // CPersistStream stuff
  1289. //
  1290. // what is our class ID?
  1291. STDMETHODIMP CMpegAudEnc::GetClassID(CLSID *pClsid)
  1292. {
  1293. CheckPointer(pClsid, E_POINTER);
  1294. *pClsid = CLSID_LAMEDShowFilter;
  1295. return S_OK;
  1296. }
  1297. HRESULT CMpegAudEnc::WriteToStream(IStream *pStream)
  1298. {
  1299. DbgLog((LOG_TRACE,1,TEXT("WriteToStream()")));
  1300. MPEG_ENCODER_CONFIG mec;
  1301. if(m_Encoder.GetOutputType(&mec) == S_FALSE)
  1302. return E_FAIL;
  1303. return pStream->Write(&mec, sizeof(mec), 0);
  1304. }
  1305. // what device should we use? Used to re-create a .GRF file that we
  1306. // are in
  1307. HRESULT CMpegAudEnc::ReadFromStream(IStream *pStream)
  1308. {
  1309. MPEG_ENCODER_CONFIG mec;
  1310. HRESULT hr = pStream->Read(&mec, sizeof(mec), 0);
  1311. if(FAILED(hr))
  1312. return hr;
  1313. if(m_Encoder.SetOutputType(mec) == S_FALSE)
  1314. return S_FALSE;
  1315. DbgLog((LOG_TRACE,1,TEXT("ReadFromStream() succeeded")));
  1316. hr = S_OK;
  1317. return hr;
  1318. }
  1319. // How long is our data?
  1320. int CMpegAudEnc::SizeMax()
  1321. {
  1322. return sizeof(MPEG_ENCODER_CONFIG);
  1323. }
  1324. //////////////////////////////////////////////////////////////////////////
  1325. // CMpegAudEncOutPin is the one and only output pin of CMpegAudEnc
  1326. //
  1327. //////////////////////////////////////////////////////////////////////////
  1328. CMpegAudEncOutPin::CMpegAudEncOutPin( CMpegAudEnc * pFilter, HRESULT * pHr ) :
  1329. CTransformOutputPin( NAME("LameEncoderOutputPin"), pFilter, pHr, L"Output\0" ),
  1330. m_pFilter(pFilter)
  1331. {
  1332. m_SetFormat = FALSE;
  1333. }
  1334. CMpegAudEncOutPin::~CMpegAudEncOutPin()
  1335. {
  1336. }
  1337. STDMETHODIMP CMpegAudEncOutPin::NonDelegatingQueryInterface(REFIID riid, void **ppv)
  1338. {
  1339. if(riid == IID_IAMStreamConfig) {
  1340. CheckPointer(ppv, E_POINTER);
  1341. return GetInterface((IAMStreamConfig*)(this), ppv);
  1342. }
  1343. return CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv);
  1344. }
  1345. //////////////////////////////////////////////////////////////////////////
  1346. // This is called after the output format has been negotiated and
  1347. // will update the LAME encoder settings so that it matches the
  1348. // settings specified in the MediaType structure.
  1349. //////////////////////////////////////////////////////////////////////////
  1350. HRESULT CMpegAudEncOutPin::SetMediaType(const CMediaType *pmt)
  1351. {
  1352. // Retrieve the current LAME encoder configuration
  1353. MPEG_ENCODER_CONFIG mec;
  1354. m_pFilter->m_Encoder.GetOutputType(&mec);
  1355. // Annotate if we are using the MEDIATYPE_Stream output type
  1356. m_pFilter->m_bStreamOutput = (pmt->majortype == MEDIATYPE_Stream);
  1357. if (pmt->majortype == MEDIATYPE_Stream) {
  1358. // Update the encoder configuration using the settings that were
  1359. // cached in the CMpegAudEncOutPin::GetMediaType() call
  1360. mec.dwSampleRate = m_CurrentOutputFormat.nSampleRate;
  1361. mec.dwBitrate = m_CurrentOutputFormat.nBitRate;
  1362. mec.ChMode = m_CurrentOutputFormat.ChMode;
  1363. }
  1364. else {
  1365. // Update the encoder configuration directly using the values
  1366. // passed via the CMediaType structure.
  1367. MPEGLAYER3WAVEFORMAT *pfmt = (MPEGLAYER3WAVEFORMAT*) pmt->Format();
  1368. mec.dwSampleRate = pfmt->wfx.nSamplesPerSec;
  1369. mec.dwBitrate = pfmt->wfx.nAvgBytesPerSec * 8 / 1000;
  1370. if (pfmt->wfx.nChannels == 1) { mec.ChMode = MONO; }
  1371. else if (pfmt->wfx.nChannels == 2 && mec.ChMode == MONO && !mec.bForceMono) { mec.ChMode = STEREO; }
  1372. }
  1373. m_pFilter->m_Encoder.SetOutputType(mec);
  1374. // Now configure this MediaType on the output pin
  1375. HRESULT hr = CTransformOutputPin::SetMediaType(pmt);
  1376. return hr;
  1377. }
  1378. //////////////////////////////////////////////////////////////////////////
  1379. // Retrieve the various MediaTypes that match the advertised formats
  1380. // supported on the output pin and configure an AM_MEDIA_TYPE output
  1381. // structure that is based on the selected format.
  1382. //////////////////////////////////////////////////////////////////////////
  1383. HRESULT CMpegAudEncOutPin::GetMediaType(int iPosition, CMediaType *pmt)
  1384. {
  1385. if (iPosition < 0) return E_INVALIDARG;
  1386. // If iPosition equals zero then we always return the currently configured MediaType
  1387. if (iPosition == 0) {
  1388. *pmt = m_mt;
  1389. return S_OK;
  1390. }
  1391. switch (iPosition)
  1392. {
  1393. case 1:
  1394. {
  1395. pmt->SetType(&MEDIATYPE_Audio);
  1396. pmt->SetSubtype(&MEDIASUBTYPE_MP3);
  1397. break;
  1398. }
  1399. case 2:
  1400. {
  1401. pmt->SetType(&MEDIATYPE_Stream);
  1402. pmt->SetSubtype(&MEDIASUBTYPE_MPEG1Audio);
  1403. pmt->SetFormatType(&GUID_NULL);
  1404. break;
  1405. }
  1406. case 3:
  1407. { // The last case that we evaluate is the MPEG2_PES format, but if the
  1408. // encoder isn't configured for it then just return VFW_S_NO_MORE_ITEMS
  1409. if ( !m_pFilter->m_Encoder.IsPES() ) { return VFW_S_NO_MORE_ITEMS; }
  1410. pmt->SetType(&MEDIATYPE_MPEG2_PES);
  1411. pmt->SetSubtype(&MEDIASUBTYPE_MPEG2_AUDIO);
  1412. break;
  1413. }
  1414. default:
  1415. return VFW_S_NO_MORE_ITEMS;
  1416. }
  1417. // Output capabilities are dependent on the input so insure it is connected
  1418. if ( !m_pFilter->m_pInput->IsConnected() ) {
  1419. pmt->SetFormatType(&FORMAT_None);
  1420. return NOERROR;
  1421. }
  1422. // Annotate the current MediaType index for recall in CMpegAudEnc::Reconnect()
  1423. m_pFilter->m_currentMediaTypeIndex = iPosition;
  1424. // Configure the remaining AM_MEDIA_TYPE parameters using the cached encoder settings.
  1425. // Since MEDIATYPE_Stream doesn't have a format block the current settings
  1426. // for CHANNEL MODE, BITRATE and SAMPLERATE are cached in m_CurrentOutputFormat for use
  1427. // when we setup the LAME encoder in the call to CMpegAudEncOutPin::SetMediaType()
  1428. MPEG_ENCODER_CONFIG mec;
  1429. m_pFilter->m_Encoder.GetOutputType(&mec); // Retrieve the current encoder config
  1430. WAVEFORMATEX wf; // Retrieve the input configuration
  1431. m_pFilter->m_Encoder.GetInputType(&wf);
  1432. // Use the current encoder sample rate unless it isn't a modulus of the input rate
  1433. if ((wf.nSamplesPerSec % mec.dwSampleRate) == 0) {
  1434. m_CurrentOutputFormat.nSampleRate = mec.dwSampleRate;
  1435. }
  1436. else {
  1437. m_CurrentOutputFormat.nSampleRate = wf.nSamplesPerSec;
  1438. }
  1439. // Select the output channel config based on the encoder config and input channel count
  1440. m_CurrentOutputFormat.ChMode = mec.ChMode;
  1441. switch (wf.nChannels) // Determine if we need to alter ChMode based upon the channel count and ForceMono flag
  1442. {
  1443. case 1:
  1444. {
  1445. m_CurrentOutputFormat.ChMode = MONO;
  1446. break;
  1447. }
  1448. case 2:
  1449. {
  1450. if (mec.ChMode == MONO && !mec.bForceMono) { m_CurrentOutputFormat.ChMode = STEREO; }
  1451. else if ( mec.bForceMono ) { m_CurrentOutputFormat.ChMode = MONO; }
  1452. break;
  1453. }
  1454. }
  1455. // Select the encoder bit rate. In VBR mode we set the data rate parameter
  1456. // of the WAVE_FORMAT_MPEGLAYER3 structure to the minimum VBR value
  1457. m_CurrentOutputFormat.nBitRate = (mec.vmVariable == vbr_off) ? mec.dwBitrate : mec.dwVariableMin;
  1458. if (pmt->majortype == MEDIATYPE_Stream) return NOERROR; // No further config required for MEDIATYPE_Stream
  1459. // Now configure the remainder of the WAVE_FORMAT_MPEGLAYER3 format block
  1460. // and its parent AM_MEDIA_TYPE structure
  1461. DECLARE_PTR(MPEGLAYER3WAVEFORMAT, p_mp3wvfmt, pmt->AllocFormatBuffer(sizeof(MPEGLAYER3WAVEFORMAT)));
  1462. ZeroMemory(p_mp3wvfmt, sizeof(MPEGLAYER3WAVEFORMAT));
  1463. p_mp3wvfmt->wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3;
  1464. p_mp3wvfmt->wfx.nChannels = (m_CurrentOutputFormat.ChMode == MONO) ? 1 : 2;
  1465. p_mp3wvfmt->wfx.nSamplesPerSec = m_CurrentOutputFormat.nSampleRate;
  1466. p_mp3wvfmt->wfx.nAvgBytesPerSec = GET_DATARATE(m_CurrentOutputFormat.nBitRate);
  1467. p_mp3wvfmt->wfx.nBlockAlign = 1;
  1468. p_mp3wvfmt->wfx.wBitsPerSample = 0;
  1469. p_mp3wvfmt->wfx.cbSize = sizeof(MPEGLAYER3WAVEFORMAT) - sizeof(WAVEFORMATEX);
  1470. p_mp3wvfmt->wID = MPEGLAYER3_ID_MPEG;
  1471. p_mp3wvfmt->fdwFlags = MPEGLAYER3_FLAG_PADDING_ISO;
  1472. p_mp3wvfmt->nBlockSize = GET_FRAMELENGTH(m_CurrentOutputFormat.nBitRate, p_mp3wvfmt->wfx.nSamplesPerSec);
  1473. p_mp3wvfmt->nFramesPerBlock = 1;
  1474. p_mp3wvfmt->nCodecDelay = 0;
  1475. pmt->SetTemporalCompression(FALSE);
  1476. pmt->SetSampleSize(OUT_BUFFER_SIZE);
  1477. pmt->SetFormat((LPBYTE)p_mp3wvfmt, sizeof(MPEGLAYER3WAVEFORMAT));
  1478. pmt->SetFormatType(&FORMAT_WaveFormatEx);
  1479. return NOERROR;
  1480. }
  1481. //////////////////////////////////////////////////////////////////////////
  1482. // This method is called to see if a given output format is supported
  1483. //////////////////////////////////////////////////////////////////////////
  1484. HRESULT CMpegAudEncOutPin::CheckMediaType(const CMediaType *pmtOut)
  1485. {
  1486. // Fail if the input pin is not connected.
  1487. if (!m_pFilter->m_pInput->IsConnected()) {
  1488. return VFW_E_NOT_CONNECTED;
  1489. }
  1490. // Reject any media types that we know in advance our
  1491. // filter cannot use.
  1492. if (pmtOut->majortype != MEDIATYPE_Audio && pmtOut->majortype != MEDIATYPE_Stream) { return S_FALSE; }
  1493. // If SetFormat was previously called, check whether pmtOut exactly
  1494. // matches the format that was specified in SetFormat.
  1495. // Return S_OK if they match, or VFW_E_INVALIDMEDIATYPE otherwise.)
  1496. if ( m_SetFormat ) {
  1497. if (*pmtOut != m_mt) { return VFW_E_INVALIDMEDIATYPE; }
  1498. else { return S_OK; }
  1499. }
  1500. // Now do the normal check for this media type.
  1501. HRESULT hr;
  1502. hr = m_pFilter->CheckTransform (&m_pFilter->m_pInput->CurrentMediaType(), // The input type.
  1503. pmtOut); // The proposed output type.
  1504. if (hr == S_OK) {
  1505. return S_OK; // This format is compatible with the current input type.
  1506. }
  1507. // This format is not compatible with the current input type.
  1508. // Maybe we can reconnect the input pin with a new input type.
  1509. // Enumerate the upstream filter's preferred output types, and
  1510. // see if one of them will work.
  1511. CMediaType *pmtEnum;
  1512. BOOL fFound = FALSE;
  1513. IEnumMediaTypes *pEnum;
  1514. hr = m_pFilter->m_pInput->GetConnected()->EnumMediaTypes(&pEnum);
  1515. if (hr != S_OK) {
  1516. return E_FAIL;
  1517. }
  1518. while (hr = pEnum->Next(1, (AM_MEDIA_TYPE **)&pmtEnum, NULL), hr == S_OK)
  1519. {
  1520. // Check this input type against the proposed output type.
  1521. hr = m_pFilter->CheckTransform(pmtEnum, pmtOut);
  1522. if (hr != S_OK) {
  1523. DeleteMediaType(pmtEnum);
  1524. continue; // Try the next one.
  1525. }
  1526. // This input type is a possible candidate. But, we have to make
  1527. // sure that the upstream filter can switch to this type.
  1528. hr = m_pFilter->m_pInput->GetConnected()->QueryAccept(pmtEnum);
  1529. if (hr != S_OK) {
  1530. // The upstream filter will not switch to this type.
  1531. DeleteMediaType(pmtEnum);
  1532. continue; // Try the next one.
  1533. }
  1534. fFound = TRUE;
  1535. DeleteMediaType(pmtEnum);
  1536. break;
  1537. }
  1538. pEnum->Release();
  1539. if (fFound) {
  1540. // This output type is OK, but if we are asked to use it, we will
  1541. // need to reconnect our input pin. (See SetFormat, below.)
  1542. return S_OK;
  1543. }
  1544. else {
  1545. return VFW_E_INVALIDMEDIATYPE;
  1546. }
  1547. }
  1548. //////////////////////////////////////////////////////////////////////////
  1549. // IAMStreamConfig
  1550. //////////////////////////////////////////////////////////////////////////
  1551. HRESULT STDMETHODCALLTYPE CMpegAudEncOutPin::SetFormat(AM_MEDIA_TYPE *pmt)
  1552. {
  1553. CheckPointer(pmt, E_POINTER);
  1554. HRESULT hr;
  1555. // Hold the filter state lock, to make sure that streaming isn't
  1556. // in the middle of starting or stopping:
  1557. CAutoLock cObjectLock(&m_pFilter->m_csFilter);
  1558. // Cannot set the format unless the filter is stopped.
  1559. if (m_pFilter->m_State != State_Stopped) {
  1560. return VFW_E_NOT_STOPPED;
  1561. }
  1562. // The set of possible output formats depends on the input format,
  1563. // so if the input pin is not connected, return a failure code.
  1564. if (!m_pFilter->m_pInput->IsConnected()) {
  1565. return VFW_E_NOT_CONNECTED;
  1566. }
  1567. // If the pin is already using this format, there's nothing to do.
  1568. if (IsConnected() && CurrentMediaType() == *pmt) {
  1569. if ( m_SetFormat ) return S_OK;
  1570. }
  1571. // See if this media type is acceptable.
  1572. if ((hr = CheckMediaType((CMediaType *)pmt)) != S_OK) {
  1573. return hr;
  1574. }
  1575. // If we're connected to a downstream filter, we have to make
  1576. // sure that the downstream filter accepts this media type.
  1577. if (IsConnected()) {
  1578. hr = GetConnected()->QueryAccept(pmt);
  1579. if (hr != S_OK) {
  1580. return VFW_E_INVALIDMEDIATYPE;
  1581. }
  1582. }
  1583. // Now make a note that from now on, this is the only format allowed,
  1584. // and refuse anything but this in the CheckMediaType() code above.
  1585. m_SetFormat = TRUE;
  1586. m_mt = *pmt;
  1587. // Changing the format means reconnecting if necessary.
  1588. if (IsConnected()) {
  1589. m_pFilter->m_pGraph->Reconnect(this);
  1590. }
  1591. return NOERROR;
  1592. }
  1593. HRESULT STDMETHODCALLTYPE CMpegAudEncOutPin::GetFormat(AM_MEDIA_TYPE **ppmt)
  1594. {
  1595. *ppmt = CreateMediaType(&m_mt);
  1596. return S_OK;
  1597. }
  1598. HRESULT STDMETHODCALLTYPE CMpegAudEncOutPin::GetNumberOfCapabilities(int *piCount, int *piSize)
  1599. {
  1600. // The set of possible output formats depends on the input format,
  1601. // so if the input pin is not connected, return a failure code.
  1602. if (!m_pFilter->m_pInput->IsConnected()) {
  1603. return VFW_E_NOT_CONNECTED;
  1604. }
  1605. // Retrieve the current encoder configuration
  1606. MPEG_ENCODER_CONFIG mec;
  1607. m_pFilter->m_Encoder.GetOutputType(&mec);
  1608. // If the encoder is in VBR mode GetStreamCaps() isn't implemented
  1609. if (mec.vmVariable != vbr_off) { *piCount = 0; }
  1610. else { *piCount = m_pFilter->m_CapsNum; }
  1611. *piSize = sizeof(AUDIO_STREAM_CONFIG_CAPS);
  1612. return S_OK;
  1613. }
  1614. HRESULT STDMETHODCALLTYPE CMpegAudEncOutPin::GetStreamCaps(int iIndex, AM_MEDIA_TYPE **pmt, BYTE *pSCC)
  1615. {
  1616. // The set of possible output formats depends on the input format,
  1617. // so if the input pin is not connected, return a failure code.
  1618. if (!m_pFilter->m_pInput->IsConnected()) {
  1619. return VFW_E_NOT_CONNECTED;
  1620. }
  1621. // If we don't have a capabilities array GetStreamCaps() isn't implemented
  1622. if (m_pFilter->m_CapsNum == 0) return E_NOTIMPL;
  1623. // If the encoder is in VBR mode GetStreamCaps() isn't implemented
  1624. MPEG_ENCODER_CONFIG mec;
  1625. m_pFilter->m_Encoder.GetOutputType(&mec);
  1626. if (mec.vmVariable != vbr_off) return E_NOTIMPL;
  1627. if (iIndex < 0) return E_INVALIDARG;
  1628. if (iIndex > m_pFilter->m_CapsNum) return S_FALSE;
  1629. // Load the MPEG Layer3 WaveFormatEx structure with the appropriate entries
  1630. // for this IAMStreamConfig index element.
  1631. *pmt = CreateMediaType(&m_mt);
  1632. if (*pmt == NULL) return E_OUTOFMEMORY;
  1633. DECLARE_PTR(MPEGLAYER3WAVEFORMAT, p_mp3wvfmt, (*pmt)->pbFormat);
  1634. (*pmt)->majortype = MEDIATYPE_Audio;
  1635. (*pmt)->subtype = MEDIASUBTYPE_MP3;
  1636. (*pmt)->bFixedSizeSamples = TRUE;
  1637. (*pmt)->bTemporalCompression = FALSE;
  1638. (*pmt)->lSampleSize = OUT_BUFFER_SIZE;
  1639. (*pmt)->formattype = FORMAT_WaveFormatEx;
  1640. (*pmt)->cbFormat = sizeof(MPEGLAYER3WAVEFORMAT);
  1641. p_mp3wvfmt->wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3;
  1642. p_mp3wvfmt->wfx.nChannels = 2;
  1643. p_mp3wvfmt->wfx.nSamplesPerSec = m_pFilter->OutputCaps[iIndex].nSampleRate;
  1644. p_mp3wvfmt->wfx.nAvgBytesPerSec = GET_DATARATE(m_pFilter->OutputCaps[iIndex].nBitRate);
  1645. p_mp3wvfmt->wfx.nBlockAlign = 1;
  1646. p_mp3wvfmt->wfx.wBitsPerSample = 0;
  1647. p_mp3wvfmt->wfx.cbSize = sizeof(MPEGLAYER3WAVEFORMAT) - sizeof(WAVEFORMATEX);
  1648. p_mp3wvfmt->wID = MPEGLAYER3_ID_MPEG;
  1649. p_mp3wvfmt->fdwFlags = MPEGLAYER3_FLAG_PADDING_ISO;
  1650. p_mp3wvfmt->nBlockSize = GET_FRAMELENGTH(m_pFilter->OutputCaps[iIndex].nBitRate, m_pFilter->OutputCaps[iIndex].nSampleRate);
  1651. p_mp3wvfmt->nFramesPerBlock = 1;
  1652. p_mp3wvfmt->nCodecDelay = 0;
  1653. // Set up the companion AUDIO_STREAM_CONFIG_CAPS structure
  1654. // We are only using the CHANNELS element of the structure
  1655. DECLARE_PTR(AUDIO_STREAM_CONFIG_CAPS, pascc, pSCC);
  1656. ZeroMemory(pascc, sizeof(AUDIO_STREAM_CONFIG_CAPS));
  1657. pascc->guid = MEDIATYPE_Audio;
  1658. pascc->MinimumChannels = 1;
  1659. pascc->MaximumChannels = 2;
  1660. pascc->ChannelsGranularity = 1;
  1661. pascc->MinimumSampleFrequency = p_mp3wvfmt->wfx.nSamplesPerSec;
  1662. pascc->MaximumSampleFrequency = p_mp3wvfmt->wfx.nSamplesPerSec;
  1663. pascc->SampleFrequencyGranularity = 0;
  1664. pascc->MinimumBitsPerSample = p_mp3wvfmt->wfx.wBitsPerSample;
  1665. pascc->MaximumBitsPerSample = p_mp3wvfmt->wfx.wBitsPerSample;
  1666. pascc->BitsPerSampleGranularity = 0;
  1667. return S_OK;
  1668. }