- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# DTSAC3Source.cpp

    00001 /*
    00002  *      Copyright (C) 2003-2005 Gabest
    00003  *      http://www.gabest.org
    00004  *
    00005  *  This Program is free software; you can redistribute it and/or modify
    00006  *  it under the terms of the GNU General Public License as published by
    00007  *  the Free Software Foundation; either version 2, or (at your option)
    00008  *  any later version.
    00009  *
    00010  *  This Program is distributed in the hope that it will be useful,
    00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    00013  *  GNU General Public License for more details.
    00014  *
    00015  *  You should have received a copy of the GNU General Public License
    00016  *  along with GNU Make; see the file COPYING.  If not, write to
    00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    00018  *  http://www.gnu.org/copyleft/gpl.html
    00019  *
    00020  */
    00021
    00022 #include "stdafx.h"
    00023 #include <mmreg.h>
    00024 #include <ks.h>
    00025 #include <initguid.h>
    00026 #include <uuids.h>
    00027 #include "..\..\..\..\include\moreuuids.h"
    00028 #include "dtsac3source.h"
    00029 #include "..\..\..\DSUtil\DSUtil.h"
    00030
    00031 #ifdef REGISTER_FILTER
    00032
    00033 const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
    00034 {
    00035         {&MEDIATYPE_Audio, &MEDIASUBTYPE_DTS},
    00036         {&MEDIATYPE_DVD_ENCRYPTED_PACK, &MEDIASUBTYPE_DTS},
    00037         {&MEDIATYPE_Audio, &MEDIASUBTYPE_DOLBY_AC3},
    00038         {&MEDIATYPE_DVD_ENCRYPTED_PACK, &MEDIASUBTYPE_DOLBY_AC3},
    00039 };
    00040
    00041 const AMOVIESETUP_PIN sudOpPin[] =
    00042 {
    00043         {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
    00044 };
    00045
    00046 const AMOVIESETUP_FILTER sudFilter[] =
    00047 {
    00048         {&__uuidof(CDTSAC3Source), L"DTS/AC3 Source", MERIT_UNLIKELY, countof(sudOpPin), sudOpPin}
    00049 };
    00050
    00051 CFactoryTemplate g_Templates[] =
    00052 {
    00053         {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CDTSAC3Source>, NULL, &sudFilter[0]}
    00054 };
    00055
    00056 int g_cTemplates = countof(g_Templates);
    00057
    00058 STDAPI DllRegisterServer()
    00059 {
    00060         SetRegKeyValue(
    00061                 _T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{B4A7BE85-551D-4594-BDC7-832B09185041}"),
    00062                 _T("0"), _T("0,4,,7FFE8001"));
    00063
    00064         SetRegKeyValue(
    00065                 _T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{B4A7BE85-551D-4594-BDC7-832B09185041}"),
    00066                 _T("1"), _T("0,2,,0B77"));
    00067
    00068         SetRegKeyValue(
    00069                 _T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{B4A7BE85-551D-4594-BDC7-832B09185041}"),
    00070                 _T("2"), _T("0,2,,770B"));
    00071
    00072         SetRegKeyValue(
    00073                 _T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{B4A7BE85-551D-4594-BDC7-832B09185041}"),
    00074                 _T("Source Filter"), _T("{B4A7BE85-551D-4594-BDC7-832B09185041}"));
    00075
    00076         SetRegKeyValue(
    00077                 _T("Media Type\\Extensions"), _T(".dts"),
    00078                 _T("Source Filter"), _T("{B4A7BE85-551D-4594-BDC7-832B09185041}"));
    00079
    00080         SetRegKeyValue(
    00081                 _T("Media Type\\Extensions"), _T(".ac3"),
    00082                 _T("Source Filter"), _T("{B4A7BE85-551D-4594-BDC7-832B09185041}"));
    00083
    00084         return AMovieDllRegisterServer2(TRUE);
    00085 }
    00086
    00087 STDAPI DllUnregisterServer()
    00088 {
    00089         DeleteRegKey(_T("Media Type\\{e436eb83-524f-11ce-9f53-0020af0ba770}"), _T("{B4A7BE85-551D-4594-BDC7-832B09185041}"));
    00090         DeleteRegKey(_T("Media Type\\Extensions"), _T(".dts"));
    00091         DeleteRegKey(_T("Media Type\\Extensions"), _T(".ac3"));
    00092
    00093         return AMovieDllRegisterServer2(FALSE);
    00094 }
    00095
    00096 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
    00097
    00098 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
    00099 {
    00100     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
    00101 }
    00102
    00103 #endif
    00104
    00105 //
    00106 // CDTSAC3Source
    00107 //
    00108
    00109 CDTSAC3Source::CDTSAC3Source(LPUNKNOWN lpunk, HRESULT* phr)
    00110         : CBaseSource<CDTSAC3Stream>(NAME("CDTSAC3Source"), lpunk, phr, __uuidof(this))
    00111 {
    00112 }
    00113
    00114 CDTSAC3Source::~CDTSAC3Source()
    00115 {
    00116 }
    00117
    00118 // CDTSAC3Stream
    00119
    00120 CDTSAC3Stream::CDTSAC3Stream(const WCHAR* wfn, CSource* pParent, HRESULT* phr)
    00121         : CBaseStream(NAME("CDTSAC3Stream"), pParent, phr)
    00122         , m_nFileOffset(0)
    00123 {
    00124         CAutoLock cAutoLock(&m_cSharedState);
    00125
    00126         m_subtype = GUID_NULL;
    00127         m_wFormatTag = 0;
    00128         m_streamid = 0;
    00129
    00130         CString fn(wfn);
    00131
    00132         if(!m_file.Open(fn, CFile::modeRead|CFile::shareDenyWrite))
    00133         {
    00134                 if(phr) *phr = E_FAIL;
    00135                 return;
    00136         }
    00137
    00138         DWORD id = 0;
    00139         if(m_file.Read(&id, sizeof(id)) != sizeof(id)
    00140         || id != 0x0180FE7F && (WORD)id != 0x0b77 && (WORD)id != 0x770b)
    00141         {
    00142                 if(phr) *phr = E_FAIL;
    00143                 return;
    00144         }
    00145
    00146         if(id == 0x0180FE7F)
    00147         {
    00148                 BYTE buff[8];
    00149                 m_file.Read(buff, 8);
    00150
    00151                 int frametype = (buff[0]>>7); // 1
    00152                 int deficitsamplecount = (buff[0]>>2)&31; // 5
    00153                 int crcpresent = (buff[0]>>1)&1; // 1
    00154                 int npcmsampleblocks = ((buff[0]&1)<<6)|(buff[1]>>2); // 7
    00155                 int framebytes = (((buff[1]&3)<<12)|(buff[2]<<4)|(buff[3]>>4)) + 1; // 14
    00156                 int audiochannelarrangement = (buff[3]&15)<<2|(buff[4]>>6); // 6
    00157                 int freq = (buff[4]>>2)&15; // 4
    00158                 int transbitrate = ((buff[4]&3)<<3)|(buff[5]>>5); // 5
    00159
    00160                 int freqtbl[] =
    00161                 {
    00162                         0,8000,16000,32000,
    00163                         0,0,
    00164                         11025,22050,44100,
    00165                         0,0,
    00166                         12000,24000,48000,
    00167                         0,0
    00168                 };
    00169
    00170                 int bitratetbl[] =
    00171                 {
    00172                         32000,56000,64000,96000,112000,128000,192000,224000,
    00173                         256000,320000,384000,448000,512000,576000,640000,754500,
    00174                         960000,1024000,1152000,1280000,1344000,1408000,1411200,1472000,
    00175                         1509750,1920000,2048000,3072000,3840000,0,0,0
    00176                 };
    00177
    00178                 m_nSamplesPerSec = freqtbl[freq];
    00179                 m_nAvgBytesPerSec = (bitratetbl[transbitrate] + 4) / 8;
    00180 //              m_nBytesPerFrame = m_nAvgBytesPerSec*10.656063618290258449304174950298/1000 + 0.5;
    00181                 m_nBytesPerFrame = framebytes;
    00182                 m_AvgTimePerFrame = 10000000i64 * m_nBytesPerFrame * 8 / bitratetbl[transbitrate];
    00183
    00184                 m_subtype = MEDIASUBTYPE_DTS;
    00185                 m_wFormatTag = WAVE_FORMAT_DVD_DTS;
    00186                 m_streamid = 0x88;
    00187         }
    00188         else
    00189         {
    00190                 BYTE info;
    00191                 if((BYTE)id == 0x77) m_file.Seek(1, CFile::current); // LE
    00192                 m_file.Read(&info, 1);
    00193
    00194                 BYTE freq = info>>6;
    00195                 BYTE bitrate = info&0x3f;
    00196
    00197                 if(bitrate >= 38)
    00198                 {
    00199                         if(phr) *phr = E_FAIL;
    00200                         return;
    00201                 }
    00202
    00203                 int freqtbl[] = {48000,44000,32000,48000};
    00204
    00205                 int bitratetbl[] =
    00206                 {
    00207                         32000,32000,40000,40000,48000,48000,56000,56000,64000,64000,
    00208                         80000,80000,96000,96000,112000,112000,128000,128000,160000,160000,
    00209                         192000,192000,224000,224000,256000,256000,320000,320000,384000,384000,
    00210                         448000,448000,512000,512000,576000,576000,640000,640000
    00211                 };
    00212
    00213                 m_nSamplesPerSec = freqtbl[freq];
    00214                 m_nAvgBytesPerSec = (bitratetbl[bitrate] + 4) / 8;
    00215                 m_nBytesPerFrame = m_nAvgBytesPerSec*32/1000;
    00216                 m_AvgTimePerFrame = 10000000i64 * m_nBytesPerFrame * 8 / bitratetbl[bitrate];
    00217
    00218                 m_subtype = MEDIASUBTYPE_DOLBY_AC3;
    00219                 m_wFormatTag = WAVE_FORMAT_DOLBY_AC3;
    00220                 m_streamid = 0x80;
    00221         }
    00222
    00223         m_rtDuration = m_AvgTimePerFrame * m_file.GetLength() / m_nBytesPerFrame;
    00224         m_rtStop = m_rtDuration;
    00225 }
    00226
    00227 CDTSAC3Stream::~CDTSAC3Stream()
    00228 {
    00229 }
    00230
    00231 HRESULT CDTSAC3Stream::DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pProperties)
    00232 {
    00233     ASSERT(pAlloc);
    00234     ASSERT(pProperties);
    00235
    00236     HRESULT hr = NOERROR;
    00237
    00238         pProperties->cBuffers = 1;
    00239         pProperties->cbBuffer = m_nBytesPerFrame+35;
    00240
    00241     ALLOCATOR_PROPERTIES Actual;
    00242     if(FAILED(hr = pAlloc->SetProperties(pProperties, &Actual))) return hr;
    00243
    00244     if(Actual.cbBuffer < pProperties->cbBuffer) return E_FAIL;
    00245     ASSERT(Actual.cBuffers == pProperties->cBuffers);
    00246
    00247     return NOERROR;
    00248 }
    00249
    00250 HRESULT CDTSAC3Stream::FillBuffer(IMediaSample* pSample, int nFrame, BYTE* pOut, long& len)
    00251 {
    00252         BYTE* pOutOrg = pOut;
    00253
    00254         const GUID* majortype = &m_mt.majortype;
    00255         const GUID* subtype = &m_mt.subtype;
    00256
    00257         if(*majortype == MEDIATYPE_DVD_ENCRYPTED_PACK)
    00258         {
    00259                 BYTE PESHeader[] =
    00260                 {
    00261                         0x00,0x00,0x01,0xBA,                    // PES id
    00262                         0x44,0x00,0x04,0x00,0x04,0x01,  // SCR (0)
    00263                         0x01,0x89,0xC3,0xF8,                    // mux rate (1260000 bytes/sec, 22bits), marker (2bits), reserved (~0, 5bits), stuffing (0, 3bits)
    00264                 };
    00265
    00266                 memcpy(pOut, &PESHeader, sizeof(PESHeader));
    00267                 pOut += sizeof(PESHeader);
    00268
    00269                 majortype = &MEDIATYPE_MPEG2_PES;
    00270         }
    00271
    00272         if(*majortype == MEDIATYPE_MPEG2_PES)
    00273         {
    00274                 BYTE Private1Header[] =
    00275                 {
    00276                         0x00,0x00,0x01,0xBD,                    // private stream 1 id
    00277                         0x07,0xEC,                                              // packet length (TODO: modify it later)
    00278                         0x81,0x80,                                              // marker, original, PTS - flags
    00279                         0x08,                                                   // packet data starting offset
    00280                         0x21,0x00,0x01,0x00,0x01,               // PTS (0)
    00281                         0xFF,0xFF,0xFF,                                 // stuffing
    00282                         m_streamid,                                             // stream id (0)
    00283                         0x01,0x00,0x01,                                 // no idea about this (might be the current sector on the disc), but dvd2avi doesn't output it to the ac3/dts file so we have to put it back
    00284                 };
    00285
    00286                 memcpy(pOut, &Private1Header, sizeof(Private1Header));
    00287                 pOut += sizeof(Private1Header);
    00288
    00289                 majortype = &MEDIATYPE_Audio;
    00290         }
    00291
    00292         if(*majortype == MEDIATYPE_Audio)
    00293         {
    00294                 m_file.Seek(m_nFileOffset + nFrame*m_nBytesPerFrame, CFile::begin);
    00295                 if(m_file.Read(pOut, m_nBytesPerFrame) < m_nBytesPerFrame) return S_FALSE;
    00296                 pOut += m_nBytesPerFrame;
    00297         }
    00298
    00299         len = pOut - pOutOrg;
    00300
    00301         return S_OK;
    00302 }
    00303
    00304 bool CDTSAC3Stream::CheckDTS(const CMediaType* pmt)
    00305 {
    00306         return (pmt->majortype == MEDIATYPE_Audio
    00307                         || pmt->majortype == MEDIATYPE_MPEG2_PES
    00308                         || pmt->majortype == MEDIATYPE_DVD_ENCRYPTED_PACK)
    00309                 && pmt->subtype == MEDIASUBTYPE_DTS;
    00310 }
    00311
    00312 bool CDTSAC3Stream::CheckWAVEDTS(const CMediaType* pmt)
    00313 {
    00314         return pmt->majortype == MEDIATYPE_Audio
    00315                 && pmt->subtype == MEDIASUBTYPE_WAVE_DTS
    00316                 && pmt->formattype == FORMAT_WaveFormatEx
    00317                 && ((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag == WAVE_FORMAT_DVD_DTS;
    00318 }
    00319
    00320 bool CDTSAC3Stream::CheckAC3(const CMediaType* pmt)
    00321 {
    00322         return (pmt->majortype == MEDIATYPE_Audio
    00323                         || pmt->majortype == MEDIATYPE_MPEG2_PES
    00324                         || pmt->majortype == MEDIATYPE_DVD_ENCRYPTED_PACK)
    00325                 && pmt->subtype == MEDIASUBTYPE_DOLBY_AC3;
    00326 }
    00327
    00328 bool CDTSAC3Stream::CheckWAVEAC3(const CMediaType* pmt)
    00329 {
    00330         return pmt->majortype == MEDIATYPE_Audio
    00331                 && pmt->subtype == MEDIASUBTYPE_DOLBY_AC3
    00332                 && pmt->formattype == FORMAT_WaveFormatEx
    00333                 && ((WAVEFORMATEX*)pmt->pbFormat)->wFormatTag == WAVE_FORMAT_DOLBY_AC3;
    00334 }
    00335
    00336 HRESULT CDTSAC3Stream::GetMediaType(int iPosition, CMediaType* pmt)
    00337 {
    00338     CAutoLock cAutoLock(m_pFilter->pStateLock());
    00339
    00340         if(iPosition >= 0 && iPosition < 5)
    00341         {
    00342                 pmt->subtype = m_subtype;
    00343                 pmt->formattype = FORMAT_WaveFormatEx;
    00344                 WAVEFORMATEX* wfe = (WAVEFORMATEX*)pmt->AllocFormatBuffer(sizeof(WAVEFORMATEX));
    00345                 memset(wfe, 0, sizeof(WAVEFORMATEX));
    00346                 wfe->cbSize = sizeof(WAVEFORMATEX);
    00347                 wfe->wFormatTag = WAVE_FORMAT_PCM;
    00348                 wfe->nSamplesPerSec = m_nSamplesPerSec;
    00349                 wfe->nAvgBytesPerSec = m_nAvgBytesPerSec;
    00350                 wfe->nChannels = 6;
    00351
    00352                 switch(iPosition)
    00353                 {
    00354                 case 0:
    00355                         pmt->majortype = MEDIATYPE_Audio;
    00356                         break;
    00357                 case 1:
    00358                         pmt->ResetFormatBuffer();
    00359                         pmt->formattype = FORMAT_None;
    00360                 case 2:
    00361                         pmt->majortype = MEDIATYPE_MPEG2_PES;
    00362                         break;
    00363                 case 3:
    00364                         pmt->ResetFormatBuffer();
    00365                         pmt->formattype = FORMAT_None;
    00366                 case 4:
    00367                         pmt->majortype = MEDIATYPE_DVD_ENCRYPTED_PACK;
    00368                         break;
    00369                 default:
    00370                         return E_INVALIDARG;
    00371                 }
    00372         }
    00373         else if(iPosition == 5)
    00374         {
    00375                 pmt->majortype = MEDIATYPE_Audio;
    00376                 pmt->subtype = FOURCCMap(m_wFormatTag);
    00377                 pmt->formattype = FORMAT_WaveFormatEx;
    00378                 WAVEFORMATEX* wfe = (WAVEFORMATEX*)pmt->AllocFormatBuffer(sizeof(WAVEFORMATEX));
    00379                 memset(wfe, 0, sizeof(WAVEFORMATEX));
    00380                 wfe->cbSize = sizeof(WAVEFORMATEX);
    00381                 wfe->wFormatTag = m_wFormatTag;
    00382                 wfe->nSamplesPerSec = m_nSamplesPerSec;
    00383                 wfe->nAvgBytesPerSec = m_nAvgBytesPerSec;
    00384                 wfe->nChannels = 2;
    00385                 wfe->nBlockAlign = 1;
    00386         }
    00387         else
    00388         {
    00389                 return VFW_S_NO_MORE_ITEMS;
    00390         }
    00391
    00392     pmt->SetTemporalCompression(FALSE);
    00393
    00394         return S_OK;
    00395 }
    00396
    00397 HRESULT CDTSAC3Stream::CheckMediaType(const CMediaType* pmt)
    00398 {
    00399         return CheckDTS(pmt) || CheckWAVEDTS(pmt)
    00400                 || CheckAC3(pmt) || CheckWAVEAC3(pmt)
    00401                 ? S_OK
    00402                 : E_INVALIDARG;
    00403 }