/*
* LAME MP3 encoder for DirectShow
* DirectShow filter implementation
*
* Copyright (c) 2000-2005 Marie Orlova, Peter Gubanov, Vitaly Ivanov, Elecard Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <mmreg.h>
#include "Encoder.h"
#define KEY_LAME_ENCODER "SOFTWARE\\GNU\\LAME MPEG Layer III Audio Encoder Filter"
#define VALUE_BITRATE "Bitrate"
#define VALUE_VARIABLE "Variable"
#define VALUE_VARIABLEMIN "VariableMin"
#define VALUE_VARIABLEMAX "VariableMax"
#define VALUE_QUALITY "Quality"
#define VALUE_VBR_QUALITY "VBR Quality"
#define VALUE_SAMPLE_RATE "Sample Rate"
#define VALUE_STEREO_MODE "Stereo Mode"
#define VALUE_FORCE_MS "Force MS"
#define VALUE_LAYER "Layer"
#define VALUE_ORIGINAL "Original"
#define VALUE_COPYRIGHT "Copyright"
#define VALUE_CRC "CRC"
#define VALUE_FORCE_MONO "Force Mono"
#define VALUE_SET_DURATION "Set Duration"
#define VALUE_SAMPLE_OVERLAP "Allow sample overlap"
#define VALUE_PES "PES"
#define VALUE_ENFORCE_MIN "EnforceVBRmin"
#define VALUE_VOICE "Voice Mode"
#define VALUE_KEEP_ALL_FREQ "Keep All Frequencies"
#define VALUE_STRICT_ISO "Strict ISO"
#define VALUE_DISABLE_SHORT_BLOCK "No Short Block"
#define VALUE_XING_TAG "Xing Tag"
#define VALUE_MODE_FIXED "Mode Fixed"
typedef struct
{
DWORD nSampleRate;
DWORD nBitRate;
MPEG_mode ChMode; //Channel coding mode
} current_output_format_t;
typedef struct
{
DWORD nSampleRate;
DWORD nBitRate;
} output_caps_t;
typedef struct
{
LONGLONG sample;
REFERENCE_TIME delta;
BOOL applied;
} resync_point_t;
#define RESYNC_COUNT 4
// The maximum number of capabilities that we can expose in our IAMStreamConfig
// implementation is currently set to 100. This number is larger than we
// should ever realistically need. However, a cleaner implementation might
// be to use a dynamically sized array like std::vector or CAtlArray to
// hold this data.
#define MAX_IAMSTREAMCONFIG_CAPS 100
///////////////////////////////////////////////////////////////////
// CMpegAudEnc class - implementation for ITransformFilter interface
///////////////////////////////////////////////////////////////////
class CMpegAudEncOutPin;
class CMpegAudEncPropertyPage;
class CMpegAudEnc : public CTransformFilter,
public ISpecifyPropertyPages,
public IAudioEncoderProperties,
public CPersistStream
{
public:
DECLARE_IUNKNOWN
static CUnknown *CreateInstance(LPUNKNOWN lpunk, HRESULT *phr);
LPAMOVIESETUP_FILTER GetSetupData();
HRESULT Reconnect();
HRESULT Receive(IMediaSample *pSample);
HRESULT CheckInputType(const CMediaType* mtIn);
HRESULT CheckTransform(const CMediaType* mtIn, const CMediaType* mtOut);
HRESULT DecideBufferSize(IMemAllocator * pAllocator, ALLOCATOR_PROPERTIES *pprop);
HRESULT GetMediaType (int iPosition, CMediaType *pMediaType);
HRESULT SetMediaType (PIN_DIRECTION direction,const CMediaType *pmt);
//
HRESULT StartStreaming();
HRESULT StopStreaming();
HRESULT EndOfStream();
HRESULT BeginFlush();
~CMpegAudEnc(void);
// ISpecifyPropertyPages
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
STDMETHODIMP GetPages(CAUUID *pPages);
// IAudioEncoderProperties
STDMETHODIMP get_PESOutputEnabled(DWORD *dwEnabled); // PES header. Obsolete
STDMETHODIMP set_PESOutputEnabled(DWORD dwEnabled); // PES header. Obsolete
STDMETHODIMP get_MPEGLayer(DWORD *dwLayer);
STDMETHODIMP set_MPEGLayer(DWORD dwLayer);
STDMETHODIMP get_Bitrate(DWORD *dwBitrate);
STDMETHODIMP set_Bitrate(DWORD dwBitrate);
STDMETHODIMP get_Variable(DWORD *dwVariable);
STDMETHODIMP set_Variable(DWORD dwVariable);
STDMETHODIMP get_VariableMin(DWORD *dwMin);
STDMETHODIMP set_VariableMin(DWORD dwMin);
STDMETHODIMP get_VariableMax(DWORD *dwMax);
STDMETHODIMP set_VariableMax(DWORD dwMax);
STDMETHODIMP get_Quality(DWORD *dwQuality);
STDMETHODIMP set_Quality(DWORD dwQuality);
STDMETHODIMP get_VariableQ(DWORD *dwVBRq);
STDMETHODIMP set_VariableQ(DWORD dwVBRq);
STDMETHODIMP get_SourceSampleRate(DWORD *dwSampleRate);
STDMETHODIMP get_SourceChannels(DWORD *dwChannels);
STDMETHODIMP get_SampleRate(DWORD *dwSampleRate);
STDMETHODIMP set_SampleRate(DWORD dwSampleRate);
STDMETHODIMP get_ChannelMode(DWORD *dwChannelMode);
STDMETHODIMP set_ChannelMode(DWORD dwChannelMode);
STDMETHODIMP get_ForceMS(DWORD *dwFlag);
STDMETHODIMP set_ForceMS(DWORD dwFlag);
STDMETHODIMP get_EnforceVBRmin(DWORD *dwFlag);
STDMETHODIMP set_EnforceVBRmin(DWORD dwFlag);
STDMETHODIMP get_VoiceMode(DWORD *dwFlag);
STDMETHODIMP set_VoiceMode(DWORD dwFlag);
STDMETHODIMP get_KeepAllFreq(DWORD *dwFlag);
STDMETHODIMP set_KeepAllFreq(DWORD dwFlag);
STDMETHODIMP get_StrictISO(DWORD *dwFlag);
STDMETHODIMP set_StrictISO(DWORD dwFlag);
STDMETHODIMP get_NoShortBlock(DWORD *dwNoShortBlock);
STDMETHODIMP set_NoShortBlock(DWORD dwNoShortBlock);
STDMETHODIMP get_XingTag(DWORD *dwXingTag);
STDMETHODIMP set_XingTag(DWORD dwXingTag);
STDMETHODIMP get_ModeFixed(DWORD *dwModeFixed);
STDMETHODIMP set_ModeFixed(DWORD dwModeFixed);
STDMETHODIMP get_CRCFlag(DWORD *dwFlag);
STDMETHODIMP set_CRCFlag(DWORD dwFlag);
STDMETHODIMP get_ForceMono(DWORD *dwFlag);
STDMETHODIMP set_ForceMono(DWORD dwFlag);
STDMETHODIMP get_SetDuration(DWORD *dwFlag);
STDMETHODIMP set_SetDuration(DWORD dwFlag);
STDMETHODIMP get_OriginalFlag(DWORD *dwFlag);
STDMETHODIMP set_OriginalFlag(DWORD dwFlag);
STDMETHODIMP get_CopyrightFlag(DWORD *dwFlag);
STDMETHODIMP set_CopyrightFlag(DWORD dwFlag);
STDMETHODIMP get_SampleOverlap(DWORD *dwFlag);
STDMETHODIMP set_SampleOverlap(DWORD dwFlag);
STDMETHODIMP get_ParameterBlockSize(BYTE *pcBlock, DWORD *pdwSize);
STDMETHODIMP set_ParameterBlockSize(BYTE *pcBlock, DWORD dwSize);
STDMETHODIMP DefaultAudioEncoderProperties();
STDMETHODIMP LoadAudioEncoderPropertiesFromRegistry();
STDMETHODIMP SaveAudioEncoderPropertiesToRegistry();
STDMETHODIMP InputTypeDefined();
STDMETHODIMP ApplyChanges();
// CPersistStream
HRESULT WriteToStream(IStream *pStream);
HRESULT ReadFromStream(IStream *pStream);
int SizeMax();
STDMETHODIMP GetClassID(CLSID *pClsid);
private:
CMpegAudEnc(LPUNKNOWN lpunk, HRESULT *phr);
HRESULT FlushEncodedSamples();
void ReadPresetSettings(MPEG_ENCODER_CONFIG *pmabsi);
void LoadOutputCapabilities(DWORD sample_rate);
// Encoder object
CEncoder m_Encoder;
REFERENCE_TIME m_rtStreamTime;
REFERENCE_TIME m_rtFrameTime;
REFERENCE_TIME m_rtEstimated;
// Synchronization data
LONGLONG m_samplesIn;
LONGLONG m_samplesOut;
int m_samplesPerFrame;
int m_bytesPerSample;
float m_bytesToDuration;
resync_point_t m_sync[RESYNC_COUNT];
int m_sync_in_idx;
int m_sync_out_idx;
BOOL m_hasFinished;
CCritSec m_cs;
DWORD m_setDuration;
DWORD m_allowOverlap;
REFERENCE_TIME m_rtBytePos;
BOOL m_bStreamOutput; // Binary stream output
long m_cbStreamAlignment; // Stream block size
int m_CapsNum;
int m_currentMediaTypeIndex;
output_caps_t OutputCaps[MAX_IAMSTREAMCONFIG_CAPS];
protected:
friend class CMpegAudEncOutPin;
friend class CMpegAudEncPropertyPage;
};
class CMpegAudEncOutPin : public CTransformOutputPin, public IAMStreamConfig
{
public:
//////////////////////////////////////////////////////////////////////////
// IUnknown
//////////////////////////////////////////////////////////////////////////
DECLARE_IUNKNOWN
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);
//////////////////////////////////////////////////////////////////////////
// IAMStreamConfig
//////////////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE SetFormat(AM_MEDIA_TYPE *pmt);
HRESULT STDMETHODCALLTYPE GetFormat(AM_MEDIA_TYPE **ppmt);
HRESULT STDMETHODCALLTYPE GetNumberOfCapabilities(int *piCount, int *piSize);
HRESULT STDMETHODCALLTYPE GetStreamCaps(int iIndex, AM_MEDIA_TYPE **pmt, BYTE *pSCC);
//////////////////////////////////////////////////////////////////////////
// CTransformOutputPin
//////////////////////////////////////////////////////////////////////////
CMpegAudEncOutPin( CMpegAudEnc * pFilter, HRESULT * pHr );
~CMpegAudEncOutPin();
HRESULT CheckMediaType(const CMediaType *pmtOut);
HRESULT GetMediaType(int iPosition, CMediaType *pmt);
HRESULT SetMediaType(const CMediaType *pmt);
private:
BOOL m_SetFormat;
CMpegAudEnc *m_pFilter;
current_output_format_t m_CurrentOutputFormat;
protected:
friend class CMpegAudEnc;
};