diff options
Diffstat (limited to 'src/libw32dll/DirectShow/DS_AudioDecoder.c')
-rw-r--r-- | src/libw32dll/DirectShow/DS_AudioDecoder.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/src/libw32dll/DirectShow/DS_AudioDecoder.c b/src/libw32dll/DirectShow/DS_AudioDecoder.c new file mode 100644 index 000000000..c86da0675 --- /dev/null +++ b/src/libw32dll/DirectShow/DS_AudioDecoder.c @@ -0,0 +1,172 @@ +/******************************************************** + + DirectShow audio decoder + Copyright 2001 Eugene Kuznetsov (divx@euro.ru) + +*********************************************************/ +#define NOAVIFILE_HEADERS + +#include "DS_AudioDecoder.h" +#include <string.h> +#include <stdio.h> +#include <stdlib.h> + +#define __MODULE__ "DirectShow audio decoder" +const GUID FORMAT_WaveFormatEx = { + 0x05589f81, 0xc356, 0x11CE, + { 0xBF, 0x01, 0x00, 0xAA, 0x00, 0x55, 0x59, 0x5A } +}; +const GUID MEDIATYPE_Audio = { + 0x73647561, 0x0000, 0x0010, + { 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 } +}; +const GUID MEDIASUBTYPE_PCM = { + 0x00000001, 0x0000, 0x0010, + { 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 } +}; + +typedef long STDCALL (*GETCLASS) (GUID*, GUID*, void**); + +DS_AudioDecoder * DS_AudioDecoder_Create(const CodecInfo * info, const WAVEFORMATEX* wf) +{ + DS_AudioDecoder *this; + int sz; + WAVEFORMATEX* pWF; + + this = malloc(sizeof(DS_AudioDecoder)); + + sz = 18 + wf->cbSize; + this->m_sVhdr = malloc(sz); + memcpy(this->m_sVhdr, wf, sz); + this->m_sVhdr2 = malloc(sz); + memcpy(this->m_sVhdr2, this->m_sVhdr, sz); + + pWF = (WAVEFORMATEX*)this->m_sVhdr2; + pWF->wFormatTag = 1; + pWF->wBitsPerSample = 16; + pWF->nBlockAlign = 2*pWF->nChannels; + pWF->cbSize = 0; + + memcpy(&this->in_fmt,wf,sizeof(WAVEFORMATEX)); + + memset(&this->m_sOurType, 0, sizeof(this->m_sOurType)); + this->m_sOurType.majortype=MEDIATYPE_Audio; + this->m_sOurType.subtype=MEDIASUBTYPE_PCM; + this->m_sOurType.subtype.f1=wf->wFormatTag; + this->m_sOurType.formattype=FORMAT_WaveFormatEx; + this->m_sOurType.lSampleSize=wf->nBlockAlign; + this->m_sOurType.bFixedSizeSamples=1; + this->m_sOurType.bTemporalCompression=0; + this->m_sOurType.pUnk=0; + this->m_sOurType.cbFormat=sz; + this->m_sOurType.pbFormat=this->m_sVhdr; + + memset(&this->m_sDestType, 0, sizeof(this->m_sDestType)); + this->m_sDestType.majortype=MEDIATYPE_Audio; + this->m_sDestType.subtype=MEDIASUBTYPE_PCM; + this->m_sDestType.formattype=FORMAT_WaveFormatEx; + this->m_sDestType.bFixedSizeSamples=1; + this->m_sDestType.bTemporalCompression=0; + this->m_sDestType.lSampleSize=2*wf->nChannels; + this->m_sDestType.pUnk=0; + this->m_sDestType.cbFormat=pWF->cbSize; + this->m_sDestType.pbFormat=this->m_sVhdr2; + + /*try*/ + { + ALLOCATOR_PROPERTIES props, props1; + this->m_pDS_Filter = DS_Filter_Create((const char*)info->dll, &info->guid, &this->m_sOurType, &this->m_sDestType); + DS_Filter_Start(this->m_pDS_Filter); + + props.cBuffers=1; + props.cbBuffer=this->m_sOurType.lSampleSize; + props.cbAlign=props.cbPrefix=0; + this->m_pDS_Filter->m_pAll->vt->SetProperties(this->m_pDS_Filter->m_pAll, &props, &props1); + this->m_pDS_Filter->m_pAll->vt->Commit(this->m_pDS_Filter->m_pAll); + } + /* + catch (FatalError& e) + { + e.PrintAll(); + delete[] m_sVhdr; + delete[] m_sVhdr2; + delete m_pDS_Filter; + throw; + } + */ + return this; +} + +void DS_AudioDecoder_Destroy(DS_AudioDecoder *this) +{ + free(this->m_sVhdr); + free(this->m_sVhdr2); + DS_Filter_Destroy(this->m_pDS_Filter); + free(this); +} + +int DS_AudioDecoder_Convert(DS_AudioDecoder *this, const void* in_data, uint_t in_size, + void* out_data, uint_t out_size, + uint_t* size_read, uint_t* size_written) +{ + uint_t written = 0; + uint_t read = 0; + + if (!in_data || !out_data) + return -1; + + in_size -= in_size%this->in_fmt.nBlockAlign; + while (in_size>0) + { + uint_t frame_size = 0; + char* frame_pointer; + IMediaSample* sample=0; + char* ptr; + int result; + +// this->m_pOurOutput->SetFramePointer(out_data+written); + COutputPin_SetFramePointer(this->m_pDS_Filter->m_pOurOutput,&frame_pointer); + COutputPin_SetFrameSizePointer(this->m_pDS_Filter->m_pOurOutput,(long*)&frame_size); + this->m_pDS_Filter->m_pAll->vt->GetBuffer(this->m_pDS_Filter->m_pAll, &sample, 0, 0, 0); + if (!sample) + { + Debug printf("DS_AudioDecoder::Convert() Error: null sample\n"); + break; + } + sample->vt->GetPointer(sample, (BYTE **)&ptr); + memcpy(ptr, (const uint8_t*)in_data + read, this->in_fmt.nBlockAlign); + sample->vt->SetActualDataLength(sample, this->in_fmt.nBlockAlign); + sample->vt->SetSyncPoint(sample, 1); + sample->vt->SetPreroll(sample, 0); + result = this->m_pDS_Filter->m_pImp->vt->Receive(this->m_pDS_Filter->m_pImp, sample); + if (result) + Debug printf("DS_AudioDecoder::Convert() Error: putting data into input pin %x\n", result); + if ((written + frame_size) > out_size) + { + sample->vt->Release((IUnknown*)sample); + break; + } + memcpy((uint8_t*)out_data + written, frame_pointer, frame_size); + sample->vt->Release((IUnknown*)sample); + read+=this->in_fmt.nBlockAlign; + written+=frame_size; + } + if (size_read) + *size_read = read; + if (size_written) + *size_written = written; + return 0; +} + +int DS_AudioDecoder_GetSrcSize(DS_AudioDecoder *this, int dest_size) +{ + double efficiency; + int frames; + + efficiency = (double) this->in_fmt.nAvgBytesPerSec + / (this->in_fmt.nSamplesPerSec*this->in_fmt.nBlockAlign); + frames = (int)(dest_size*efficiency); + if (frames < 1) + frames = 1; + return frames * this->in_fmt.nBlockAlign; +} |