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