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 23 #include <mmreg.h> 24 #include "Encoder.h" 25 26 #define KEY_LAME_ENCODER "SOFTWARE\\GNU\\LAME MPEG Layer III Audio Encoder Filter" 27 28 #define VALUE_BITRATE "Bitrate" 29 #define VALUE_VARIABLE "Variable" 30 #define VALUE_VARIABLEMIN "VariableMin" 31 #define VALUE_VARIABLEMAX "VariableMax" 32 #define VALUE_QUALITY "Quality" 33 #define VALUE_VBR_QUALITY "VBR Quality" 34 #define VALUE_SAMPLE_RATE "Sample Rate" 35 36 #define VALUE_STEREO_MODE "Stereo Mode" 37 #define VALUE_FORCE_MS "Force MS" 38 39 #define VALUE_LAYER "Layer" 40 #define VALUE_ORIGINAL "Original" 41 #define VALUE_COPYRIGHT "Copyright" 42 #define VALUE_CRC "CRC" 43 #define VALUE_FORCE_MONO "Force Mono" 44 #define VALUE_SET_DURATION "Set Duration" 45 #define VALUE_SAMPLE_OVERLAP "Allow sample overlap" 46 #define VALUE_PES "PES" 47 48 #define VALUE_ENFORCE_MIN "EnforceVBRmin" 49 #define VALUE_VOICE "Voice Mode" 50 #define VALUE_KEEP_ALL_FREQ "Keep All Frequencies" 51 #define VALUE_STRICT_ISO "Strict ISO" 52 #define VALUE_DISABLE_SHORT_BLOCK "No Short Block" 53 #define VALUE_XING_TAG "Xing Tag" 54 #define VALUE_MODE_FIXED "Mode Fixed" 55 56 57 typedef struct 58 { 59 DWORD nSampleRate; 60 DWORD nBitRate; 61 MPEG_mode ChMode; //Channel coding mode 62 } current_output_format_t; 63 64 typedef struct 65 { 66 DWORD nSampleRate; 67 DWORD nBitRate; 68 } output_caps_t; 69 70 typedef struct 71 { 72 LONGLONG sample; 73 REFERENCE_TIME delta; 74 75 BOOL applied; 76 } resync_point_t; 77 78 #define RESYNC_COUNT 4 79 80 // The maximum number of capabilities that we can expose in our IAMStreamConfig 81 // implementation is currently set to 100. This number is larger than we 82 // should ever realistically need. However, a cleaner implementation might 83 // be to use a dynamically sized array like std::vector or CAtlArray to 84 // hold this data. 85 #define MAX_IAMSTREAMCONFIG_CAPS 100 86 87 /////////////////////////////////////////////////////////////////// 88 // CMpegAudEnc class - implementation for ITransformFilter interface 89 /////////////////////////////////////////////////////////////////// 90 class CMpegAudEncOutPin; 91 class CMpegAudEncPropertyPage; 92 class CMpegAudEnc : public CTransformFilter, 93 public ISpecifyPropertyPages, 94 public IAudioEncoderProperties, 95 public CPersistStream 96 { 97 public: 98 DECLARE_IUNKNOWN 99 100 static CUnknown *CreateInstance(LPUNKNOWN lpunk, HRESULT *phr); 101 102 LPAMOVIESETUP_FILTER GetSetupData(); 103 104 HRESULT Reconnect(); 105 106 HRESULT Receive(IMediaSample *pSample); 107 108 HRESULT CheckInputType(const CMediaType* mtIn); 109 HRESULT CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut); 110 HRESULT DecideBufferSize(IMemAllocator * pAllocator, ALLOCATOR_PROPERTIES *pProperties); 111 112 HRESULT GetMediaType (int iPosition, CMediaType *pMediaType); 113 HRESULT SetMediaType (PIN_DIRECTION direction,const CMediaType *pmt); 114 115 116 // 117 HRESULT StartStreaming(); 118 HRESULT StopStreaming(); 119 HRESULT EndOfStream(); 120 HRESULT BeginFlush(); 121 122 ~CMpegAudEnc(void); 123 124 // ISpecifyPropertyPages 125 STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv); 126 STDMETHODIMP GetPages(CAUUID *pcauuid); 127 128 // IAudioEncoderProperties 129 STDMETHODIMP get_PESOutputEnabled(DWORD *dwEnabled); // PES header. Obsolete 130 STDMETHODIMP set_PESOutputEnabled(DWORD dwEnabled); // PES header. Obsolete 131 132 STDMETHODIMP get_MPEGLayer(DWORD *dwLayer); 133 STDMETHODIMP set_MPEGLayer(DWORD dwLayer); 134 135 STDMETHODIMP get_Bitrate(DWORD *dwBitrate); 136 STDMETHODIMP set_Bitrate(DWORD dwBitrate); 137 STDMETHODIMP get_Variable(DWORD *dwVariable); 138 STDMETHODIMP set_Variable(DWORD dwVariable); 139 STDMETHODIMP get_VariableMin(DWORD *dwMin); 140 STDMETHODIMP set_VariableMin(DWORD dwMin); 141 STDMETHODIMP get_VariableMax(DWORD *dwMax); 142 STDMETHODIMP set_VariableMax(DWORD dwMax); 143 STDMETHODIMP get_Quality(DWORD *dwQuality); 144 STDMETHODIMP set_Quality(DWORD dwQuality); 145 STDMETHODIMP get_VariableQ(DWORD *dwVBRq); 146 STDMETHODIMP set_VariableQ(DWORD dwVBRq); 147 STDMETHODIMP get_SourceSampleRate(DWORD *dwSampleRate); 148 STDMETHODIMP get_SourceChannels(DWORD *dwChannels); 149 STDMETHODIMP get_SampleRate(DWORD *dwSampleRate); 150 STDMETHODIMP set_SampleRate(DWORD dwSampleRate); 151 152 STDMETHODIMP get_ChannelMode(DWORD *dwChannelMode); 153 STDMETHODIMP set_ChannelMode(DWORD dwChannelMode); 154 STDMETHODIMP get_ForceMS(DWORD *dwFlag); 155 STDMETHODIMP set_ForceMS(DWORD dwFlag); 156 STDMETHODIMP get_EnforceVBRmin(DWORD *dwFlag); 157 STDMETHODIMP set_EnforceVBRmin(DWORD dwFlag); 158 STDMETHODIMP get_VoiceMode(DWORD *dwFlag); 159 STDMETHODIMP set_VoiceMode(DWORD dwFlag); 160 STDMETHODIMP get_KeepAllFreq(DWORD *dwFlag); 161 STDMETHODIMP set_KeepAllFreq(DWORD dwFlag); 162 STDMETHODIMP get_StrictISO(DWORD *dwFlag); 163 STDMETHODIMP set_StrictISO(DWORD dwFlag); 164 STDMETHODIMP get_NoShortBlock(DWORD *dwNoShortBlock); 165 STDMETHODIMP set_NoShortBlock(DWORD dwNoShortBlock); 166 STDMETHODIMP get_XingTag(DWORD *dwXingTag); 167 STDMETHODIMP set_XingTag(DWORD dwXingTag); 168 STDMETHODIMP get_ModeFixed(DWORD *dwModeFixed); 169 STDMETHODIMP set_ModeFixed(DWORD dwModeFixed); 170 171 172 STDMETHODIMP get_CRCFlag(DWORD *dwFlag); 173 STDMETHODIMP set_CRCFlag(DWORD dwFlag); 174 STDMETHODIMP get_ForceMono(DWORD *dwFlag); 175 STDMETHODIMP set_ForceMono(DWORD dwFlag); 176 STDMETHODIMP get_SetDuration(DWORD *dwFlag); 177 STDMETHODIMP set_SetDuration(DWORD dwFlag); 178 STDMETHODIMP get_OriginalFlag(DWORD *dwFlag); 179 STDMETHODIMP set_OriginalFlag(DWORD dwFlag); 180 STDMETHODIMP get_CopyrightFlag(DWORD *dwFlag); 181 STDMETHODIMP set_CopyrightFlag(DWORD dwFlag); 182 STDMETHODIMP get_SampleOverlap(DWORD *dwFlag); 183 STDMETHODIMP set_SampleOverlap(DWORD dwFlag); 184 185 STDMETHODIMP get_ParameterBlockSize(BYTE *pcBlock, DWORD *pdwSize); 186 STDMETHODIMP set_ParameterBlockSize(BYTE *pcBlock, DWORD dwSize); 187 188 STDMETHODIMP DefaultAudioEncoderProperties(); 189 STDMETHODIMP LoadAudioEncoderPropertiesFromRegistry(); 190 STDMETHODIMP SaveAudioEncoderPropertiesToRegistry(); 191 STDMETHODIMP InputTypeDefined(); 192 193 STDMETHODIMP ApplyChanges(); 194 195 // CPersistStream 196 HRESULT WriteToStream(IStream *pStream); 197 HRESULT ReadFromStream(IStream *pStream); 198 199 int SizeMax(); 200 STDMETHODIMP GetClassID(CLSID *pClsid); 201 202 private: 203 CMpegAudEnc(LPUNKNOWN lpunk, HRESULT *phr); 204 205 HRESULT FlushEncodedSamples(); 206 207 void ReadPresetSettings(MPEG_ENCODER_CONFIG *pmec); 208 209 void LoadOutputCapabilities(DWORD sample_rate); 210 211 // Encoder object 212 CEncoder m_Encoder; 213 214 REFERENCE_TIME m_rtStreamTime; 215 REFERENCE_TIME m_rtFrameTime; 216 REFERENCE_TIME m_rtEstimated; 217 218 // Synchronization data 219 LONGLONG m_samplesIn; 220 LONGLONG m_samplesOut; 221 int m_samplesPerFrame; 222 int m_bytesPerSample; 223 float m_bytesToDuration; 224 225 resync_point_t m_sync[RESYNC_COUNT]; 226 int m_sync_in_idx; 227 int m_sync_out_idx; 228 229 BOOL m_hasFinished; 230 231 CCritSec m_cs; 232 233 DWORD m_setDuration; 234 DWORD m_allowOverlap; 235 236 REFERENCE_TIME m_rtBytePos; 237 238 BOOL m_bStreamOutput; // Binary stream output 239 long m_cbStreamAlignment; // Stream block size 240 int m_CapsNum; 241 int m_currentMediaTypeIndex; 242 output_caps_t OutputCaps[MAX_IAMSTREAMCONFIG_CAPS]; 243 244 protected: 245 friend class CMpegAudEncOutPin; 246 friend class CMpegAudEncPropertyPage; 247 }; 248 249 250 class CMpegAudEncOutPin : public CTransformOutputPin, public IAMStreamConfig 251 { 252 public: 253 254 ////////////////////////////////////////////////////////////////////////// 255 // IUnknown 256 ////////////////////////////////////////////////////////////////////////// 257 DECLARE_IUNKNOWN 258 STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv); 259 260 ////////////////////////////////////////////////////////////////////////// 261 // IAMStreamConfig 262 ////////////////////////////////////////////////////////////////////////// 263 HRESULT STDMETHODCALLTYPE SetFormat(AM_MEDIA_TYPE *pmt); 264 HRESULT STDMETHODCALLTYPE GetFormat(AM_MEDIA_TYPE **ppmt); 265 HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities(int *piCount, int *piSize); 266 HRESULT STDMETHODCALLTYPE GetStreamCaps(int iIndex, AM_MEDIA_TYPE **pmt, BYTE *pSCC); 267 268 ////////////////////////////////////////////////////////////////////////// 269 // CTransformOutputPin 270 ////////////////////////////////////////////////////////////////////////// 271 CMpegAudEncOutPin( CMpegAudEnc * pFilter, HRESULT * pHr ); 272 ~CMpegAudEncOutPin(); 273 274 HRESULT CheckMediaType(const CMediaType *pmtOut); 275 HRESULT GetMediaType(int iPosition, CMediaType *pmt); 276 HRESULT SetMediaType(const CMediaType *pmt); 277 278 private: 279 BOOL m_SetFormat; 280 CMpegAudEnc *m_pFilter; 281 282 current_output_format_t m_CurrentOutputFormat; 283 284 protected: 285 friend class CMpegAudEnc; 286 287 }; 288