MatroskaSplitter.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 "MatroskaSplitter.h"
00025 #include "..\..\..\DSUtil\DSUtil.h"
00026 
00027 #include <initguid.h>
00028 #include "..\..\..\..\include\matroska\matroska.h"
00029 #include "..\..\..\..\include\ogg\OggDS.h"
00030 #include "..\..\..\..\include\moreuuids.h"
00031 
00032 using namespace MatroskaReader;
00033 
00034 #ifdef REGISTER_FILTER
00035 
00036 const AMOVIESETUP_MEDIATYPE sudPinTypesIn[] =
00037 {       
00038         {&MEDIATYPE_Stream, &MEDIASUBTYPE_Matroska},
00039         {&MEDIATYPE_Stream, &MEDIASUBTYPE_NULL}
00040 };
00041 
00042 const AMOVIESETUP_PIN sudpPins[] =
00043 {
00044     {L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesIn), sudPinTypesIn},
00045     {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, 0, NULL}
00046 };
00047 
00048 const AMOVIESETUP_FILTER sudFilter[] =
00049 {
00050         {&__uuidof(CMatroskaSplitterFilter), L"Matroska Splitter", MERIT_NORMAL, countof(sudpPins), sudpPins},
00051         {&__uuidof(CMatroskaSourceFilter), L"Matroska Source", MERIT_NORMAL, 0, NULL},
00052 };
00053 
00054 CFactoryTemplate g_Templates[] =
00055 {
00056         {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CMatroskaSplitterFilter>, NULL, &sudFilter[0]},
00057         {sudFilter[1].strName, sudFilter[1].clsID, CreateInstance<CMatroskaSourceFilter>, NULL, &sudFilter[1]},
00058 };
00059 
00060 int g_cTemplates = countof(g_Templates);
00061 
00062 STDAPI DllRegisterServer()
00063 {
00064         RegisterSourceFilter(
00065                 CLSID_AsyncReader, 
00066                 MEDIASUBTYPE_Matroska, 
00067                 _T("0,4,,1A45DFA3"), 
00068                 _T(".mkv"), _T(".mka"), _T(".mks"), NULL);
00069 
00070         return AMovieDllRegisterServer2(TRUE);
00071 }
00072 
00073 STDAPI DllUnregisterServer()
00074 {
00075         UnRegisterSourceFilter(MEDIASUBTYPE_Matroska);
00076 
00077         return AMovieDllRegisterServer2(FALSE);
00078 }
00079 
00080 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00081 
00082 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00083 {
00084     return DllEntryPoint((HINSTANCE)hModule, dwReason, 0); // "DllMain" of the dshow baseclasses;
00085 }
00086 
00087 #endif
00088 
00089 //
00090 // CMatroskaSplitterFilter
00091 //
00092 
00093 CMatroskaSplitterFilter::CMatroskaSplitterFilter(LPUNKNOWN pUnk, HRESULT* phr)
00094         : CBaseSplitterFilter(NAME("CMatroskaSplitterFilter"), pUnk, phr, __uuidof(this))
00095 {
00096 }
00097 
00098 CMatroskaSplitterFilter::~CMatroskaSplitterFilter()
00099 {
00100 }
00101 
00102 STDMETHODIMP CMatroskaSplitterFilter::NonDelegatingQueryInterface(REFIID riid, void** ppv)
00103 {
00104         CheckPointer(ppv, E_POINTER);
00105 
00106         return 
00107                 QI(ITrackInfo)
00108                 __super::NonDelegatingQueryInterface(riid, ppv);
00109 }
00110 
00111 #include <vector>
00112 
00113 HRESULT CMatroskaSplitterFilter::CreateOutputs(IAsyncReader* pAsyncReader)
00114 {
00115         CheckPointer(pAsyncReader, E_POINTER);
00116 
00117         HRESULT hr = E_FAIL;
00118 
00119         m_pFile.Free();
00120         m_pTrackEntryMap.RemoveAll();
00121         m_pOrderedTrackArray.RemoveAll();
00122 
00123         m_pFile.Attach(new CMatroskaFile(pAsyncReader, hr));
00124         if(!m_pFile) return E_OUTOFMEMORY;
00125         if(FAILED(hr)) {m_pFile.Free(); return hr;}
00126 
00127         m_rtNewStart = m_rtCurrent = 0;
00128         m_rtNewStop = m_rtStop = 0;
00129 
00130         int iVideo = 1, iAudio = 1, iSubtitle = 1;
00131 
00132         POSITION pos = m_pFile->m_segment.Tracks.GetHeadPosition();
00133         while(pos)
00134         {
00135                 Track* pT = m_pFile->m_segment.Tracks.GetNext(pos);
00136 
00137                 POSITION pos2 = pT->TrackEntries.GetHeadPosition();
00138                 while(pos2)
00139                 {
00140                         TrackEntry* pTE = pT->TrackEntries.GetNext(pos2);
00141 
00142                         if(!pTE->Expand(pTE->CodecPrivate, ContentEncoding::TracksPrivateData))
00143                                 continue;
00144 
00145                         CStringA CodecID = pTE->CodecID.ToString();
00146 
00147                         CStringW Name;
00148                         Name.Format(L"Output %I64d", (UINT64)pTE->TrackNumber);
00149 
00150                         CMediaType mt;
00151                         CArray<CMediaType> mts;
00152 
00153                         mt.SetSampleSize(1);
00154 
00155                         if(pTE->TrackType == TrackEntry::TypeVideo)
00156                         {
00157                                 Name.Format(L"Video %d", iVideo++);
00158 
00159                                 mt.majortype = MEDIATYPE_Video;
00160 
00161                                 if(CodecID == "V_MS/VFW/FOURCC")
00162                                 {
00163                                         mt.formattype = FORMAT_VideoInfo;
00164                                         VIDEOINFOHEADER* pvih = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER) + pTE->CodecPrivate.GetCount() - sizeof(BITMAPINFOHEADER));
00165                                         memset(mt.Format(), 0, mt.FormatLength());
00166                                         memcpy(&pvih->bmiHeader, (BYTE*)pTE->CodecPrivate, pTE->CodecPrivate.GetCount());
00167                                         mt.subtype = FOURCCMap(pvih->bmiHeader.biCompression);
00168                                         switch(pvih->bmiHeader.biCompression)
00169                                         {
00170                                         case BI_RGB: case BI_BITFIELDS: mt.subtype = 
00171                                                 pvih->bmiHeader.biBitCount == 1 ? MEDIASUBTYPE_RGB1 :
00172                                                 pvih->bmiHeader.biBitCount == 4 ? MEDIASUBTYPE_RGB4 :
00173                                                 pvih->bmiHeader.biBitCount == 8 ? MEDIASUBTYPE_RGB8 :
00174                                                 pvih->bmiHeader.biBitCount == 16 ? MEDIASUBTYPE_RGB565 :
00175                                                 pvih->bmiHeader.biBitCount == 24 ? MEDIASUBTYPE_RGB24 :
00176                                                 pvih->bmiHeader.biBitCount == 32 ? MEDIASUBTYPE_ARGB32 :
00177                                                 MEDIASUBTYPE_NULL;
00178                                                 break;
00179 //                                      case BI_RLE8: mt.subtype = MEDIASUBTYPE_RGB8; break;
00180 //                                      case BI_RLE4: mt.subtype = MEDIASUBTYPE_RGB4; break;
00181                                         }
00182                                         mts.Add(mt);
00183                                 }
00184                                 else if(CodecID == "V_UNCOMPRESSED")
00185                                 {
00186                                 }
00187                                 else if(CodecID.Find("V_MPEG4/ISO/AVC") == 0)
00188                                 {
00189                                         if(pTE->CodecPrivate.GetSize() >= 6)
00190                                         {
00191                                         BYTE sps = pTE->CodecPrivate[5] & 0x1f;
00192 
00193 
00194         std::vector<BYTE> avcC;
00195         for(int i = 0, j = pTE->CodecPrivate.GetSize(); i < j; i++)
00196                 avcC.push_back(pTE->CodecPrivate[i]);
00197 
00198         std::vector<BYTE> sh;
00199 
00200         unsigned jj = 6;
00201 
00202         while (sps--) {
00203           if (jj + 2 > avcC.size())
00204             goto avcfail;
00205           unsigned spslen = ((unsigned)avcC[jj] << 8) | avcC[jj+1];
00206           if (jj + 2 + spslen > avcC.size())
00207             goto avcfail;
00208           unsigned cur = sh.size();
00209           sh.resize(cur + spslen + 2, 0);
00210           std::copy(avcC.begin() + jj, avcC.begin() + jj + 2 + spslen,sh.begin() + cur);
00211           jj += 2 + spslen;
00212         }
00213 
00214         if (jj + 1 > avcC.size())
00215           continue;
00216 
00217         unsigned pps = avcC[jj++];
00218 
00219         while (pps--) {
00220           if (jj + 2 > avcC.size())
00221             goto avcfail;
00222           unsigned ppslen = ((unsigned)avcC[jj] << 8) | avcC[jj+1];
00223           if (jj + 2 + ppslen > avcC.size())
00224             goto avcfail;
00225           unsigned cur = sh.size();
00226           sh.resize(cur + ppslen + 2, 0);
00227           std::copy(avcC.begin() + jj, avcC.begin() + jj + 2 + ppslen, sh.begin() + cur);
00228           jj += 2 + ppslen;
00229         }
00230 
00231         goto avcsuccess;
00232 avcfail:
00233         continue;
00234 avcsuccess:
00235 
00236                                         CArray<BYTE> data;
00237                                         data.SetSize(sh.size());
00238                                         std::copy(sh.begin(), sh.end(), (BYTE*)data.GetData());
00239 
00240                                         mt.subtype = FOURCCMap('1CVA');
00241                                         mt.formattype = FORMAT_MPEG2Video;
00242                                         MPEG2VIDEOINFO* pm2vi = (MPEG2VIDEOINFO*)mt.AllocFormatBuffer(FIELD_OFFSET(MPEG2VIDEOINFO, dwSequenceHeader) + data.GetSize());
00243                                         memset(mt.Format(), 0, mt.FormatLength());
00244                                         pm2vi->hdr.bmiHeader.biSize = sizeof(pm2vi->hdr.bmiHeader);
00245                                         pm2vi->hdr.bmiHeader.biWidth = (LONG)pTE->v.PixelWidth;
00246                                         pm2vi->hdr.bmiHeader.biHeight = (LONG)pTE->v.PixelHeight;
00247                                         pm2vi->hdr.bmiHeader.biCompression = '1cva';
00248                                         pm2vi->hdr.bmiHeader.biPlanes = 1;
00249                                         pm2vi->hdr.bmiHeader.biBitCount = 24;
00250 
00251                                         pm2vi->dwProfile = pTE->CodecPrivate[1];
00252                                         pm2vi->dwLevel = pTE->CodecPrivate[3];
00253                                         pm2vi->dwFlags = (pTE->CodecPrivate[4] & 3) + 1;
00254 
00255                                         BYTE* pSequenceHeader = (BYTE*)pm2vi->dwSequenceHeader;
00256                                         memcpy(pSequenceHeader, data.GetData(), data.GetSize());
00257                                         pm2vi->cbSequenceHeader = data.GetSize();
00258 
00259                                         mts.Add(mt);
00260 
00261                                         }
00262                                 }
00263                                 else if(CodecID.Find("V_MPEG4/") == 0) // TODO: find out which V_MPEG4/*/* ids can be mapped to 'mp4v'
00264                                 {
00265                                         mt.subtype = FOURCCMap('v4pm');
00266                                         mt.formattype = FORMAT_VideoInfo;
00267                                         VIDEOINFOHEADER* pvih = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER));
00268                                         memset(pvih, 0, mt.FormatLength());
00269                                         pvih->bmiHeader.biSize = sizeof(pvih->bmiHeader);
00270                                         pvih->bmiHeader.biWidth = (LONG)pTE->v.PixelWidth;
00271                                         pvih->bmiHeader.biHeight = (LONG)pTE->v.PixelHeight;
00272                                         pvih->bmiHeader.biCompression = 'v4pm';
00273                                         mts.Add(mt);
00274 
00275                                         // TODO: add (-1,0) dummy frame to timeoverride when it is /asp (that is having b-frames almost certainly)
00276                                 }
00277                                 else if(CodecID.Find("V_REAL/RV") == 0)
00278                                 {
00279                                         mt.subtype = FOURCCMap('00VR' + ((CodecID[9]-0x30)<<16));
00280                                         mt.formattype = FORMAT_VideoInfo;
00281                                         VIDEOINFOHEADER* pvih = (VIDEOINFOHEADER*)mt.AllocFormatBuffer(sizeof(VIDEOINFOHEADER) + pTE->CodecPrivate.GetCount());
00282                                         memset(mt.Format(), 0, mt.FormatLength());
00283                                         memcpy(mt.Format() + sizeof(VIDEOINFOHEADER), pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetCount());
00284                                         pvih->bmiHeader.biSize = sizeof(pvih->bmiHeader);
00285                                         pvih->bmiHeader.biWidth = (LONG)pTE->v.PixelWidth;
00286                                         pvih->bmiHeader.biHeight = (LONG)pTE->v.PixelHeight;
00287                                         pvih->bmiHeader.biCompression = mt.subtype.Data1;
00288                                         mts.Add(mt);
00289                                 }
00290                                 else if(CodecID == "V_DIRAC")
00291                                 {
00292                                         mt.subtype = MEDIASUBTYPE_DiracVideo;
00293                                         mt.formattype = FORMAT_DiracVideoInfo;
00294                                         DIRACINFOHEADER* dvih = (DIRACINFOHEADER*)mt.AllocFormatBuffer(FIELD_OFFSET(DIRACINFOHEADER, dwSequenceHeader) + pTE->CodecPrivate.GetSize());
00295                                         memset(mt.Format(), 0, mt.FormatLength());
00296                                         dvih->hdr.bmiHeader.biSize = sizeof(dvih->hdr.bmiHeader);
00297                                         dvih->hdr.bmiHeader.biWidth = (LONG)pTE->v.PixelWidth;
00298                                         dvih->hdr.bmiHeader.biHeight = (LONG)pTE->v.PixelHeight;
00299                                         dvih->hdr.dwPictAspectRatioX = dvih->hdr.bmiHeader.biWidth;
00300                                         dvih->hdr.dwPictAspectRatioY = dvih->hdr.bmiHeader.biHeight;
00301 
00302                                         BYTE* pSequenceHeader = (BYTE*)dvih->dwSequenceHeader;
00303                                         memcpy(pSequenceHeader, pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetSize());
00304                                         dvih->cbSequenceHeader = pTE->CodecPrivate.GetSize();
00305 
00306                                         mts.Add(mt);
00307                                 }
00308                                 else if(CodecID == "V_MPEG2")
00309                                 {
00310                                         BYTE* seqhdr = pTE->CodecPrivate.GetData();
00311                                         DWORD len = pTE->CodecPrivate.GetSize();
00312                                         int w = pTE->v.PixelWidth;
00313                                         int h = pTE->v.PixelHeight;
00314 
00315                                         if(MakeMPEG2MediaType(mt, seqhdr, len, w, h))
00316                                                 mts.Add(mt);
00317                                 }
00318 /*
00319                                 else if(CodecID == "V_DSHOW/MPEG1VIDEO") // V_MPEG1
00320                                 {
00321                                         mt.majortype = MEDIATYPE_Video;
00322                                         mt.subtype = MEDIASUBTYPE_MPEG1Payload;
00323                                         mt.formattype = FORMAT_MPEGVideo;
00324                                         MPEG1VIDEOINFO* pm1vi = (MPEG1VIDEOINFO*)mt.AllocFormatBuffer(pTE->CodecPrivate.GetSize());
00325                                         memcpy(pm1vi, pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetSize());
00326                                         mt.SetSampleSize(pm1vi->hdr.bmiHeader.biWidth*pm1vi->hdr.bmiHeader.biHeight*4);
00327                                         mts.Add(mt);
00328                                 }
00329 */
00330                                 REFERENCE_TIME AvgTimePerFrame = 0;
00331 
00332                 if(pTE->v.FramePerSec > 0)
00333                                         AvgTimePerFrame = (REFERENCE_TIME)(10000000i64 / pTE->v.FramePerSec);
00334                                 else if(pTE->DefaultDuration > 0)
00335                                         AvgTimePerFrame = (REFERENCE_TIME)pTE->DefaultDuration / 100;
00336 
00337                                 if(AvgTimePerFrame)
00338                                 {
00339                                         for(int i = 0; i < mts.GetCount(); i++)
00340                                         {
00341                                                 if(mts[i].formattype == FORMAT_VideoInfo
00342                                                 || mts[i].formattype == FORMAT_VideoInfo2
00343                                                 || mts[i].formattype == FORMAT_MPEG2Video)
00344                                                 {
00345                                                         ((VIDEOINFOHEADER*)mts[i].Format())->AvgTimePerFrame = AvgTimePerFrame;
00346                                                 }
00347                                         }
00348                                 }
00349 
00350                                 if(pTE->v.DisplayWidth != 0 && pTE->v.DisplayHeight != 0)
00351                                 {
00352                                         for(int i = 0; i < mts.GetCount(); i++)
00353                                         {
00354                                                 if(mts[i].formattype == FORMAT_VideoInfo)
00355                                                 {
00356                                                         DWORD vih1 = FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader);
00357                                                         DWORD vih2 = FIELD_OFFSET(VIDEOINFOHEADER2, bmiHeader);
00358                                                         DWORD bmi = mts[i].FormatLength() - FIELD_OFFSET(VIDEOINFOHEADER, bmiHeader);
00359                                                         mt.formattype = FORMAT_VideoInfo2;
00360                                                         mt.AllocFormatBuffer(vih2 + bmi);
00361                                                         memcpy(mt.Format(), mts[i].Format(), vih1);
00362                                                         memset(mt.Format() + vih1, 0, vih2 - vih1);
00363                                                         memcpy(mt.Format() + vih2, mts[i].Format() + vih1, bmi);
00364                                                         ((VIDEOINFOHEADER2*)mt.Format())->dwPictAspectRatioX = (DWORD)pTE->v.DisplayWidth;
00365                                                         ((VIDEOINFOHEADER2*)mt.Format())->dwPictAspectRatioY = (DWORD)pTE->v.DisplayHeight;
00366                                                         mts.InsertAt(i++, mt);
00367                                                 }
00368                                                 else if(mts[i].formattype == FORMAT_MPEG2Video)
00369                                                 {
00370                                                         ((MPEG2VIDEOINFO*)mts[i].Format())->hdr.dwPictAspectRatioX = (DWORD)pTE->v.DisplayWidth;
00371                                                         ((MPEG2VIDEOINFO*)mts[i].Format())->hdr.dwPictAspectRatioY = (DWORD)pTE->v.DisplayHeight;
00372                                                 }
00373                                         }
00374                                 }
00375                         }
00376                         else if(pTE->TrackType == TrackEntry::TypeAudio)
00377                         {
00378                                 Name.Format(L"Audio %d", iAudio++);
00379 
00380                                 mt.majortype = MEDIATYPE_Audio;
00381                                 mt.formattype = FORMAT_WaveFormatEx;
00382                                 WAVEFORMATEX* pwfe = (WAVEFORMATEX*)mt.AllocFormatBuffer(sizeof(WAVEFORMATEX));
00383                                 memset(pwfe, 0, mt.FormatLength());
00384                                 pwfe->nChannels = (WORD)pTE->a.Channels;
00385                                 pwfe->nSamplesPerSec = (DWORD)pTE->a.SamplingFrequency;
00386                                 pwfe->wBitsPerSample = (WORD)pTE->a.BitDepth;
00387                                 pwfe->nBlockAlign = (WORD)((pwfe->nChannels * pwfe->wBitsPerSample) / 8);
00388                                 pwfe->nAvgBytesPerSec = pwfe->nSamplesPerSec * pwfe->nBlockAlign;
00389                                 mt.SetSampleSize(256000);
00390 
00391                                 if(CodecID == "A_VORBIS")
00392                                 {
00393                                         BYTE* p = (BYTE*)pTE->CodecPrivate;
00394                                         CArray<long> sizes;
00395                                         for(BYTE n = *p++; n > 0; n--)
00396                                         {
00397                                                 long size = 0;
00398                                                 do {size += *p;} while(*p++ == 0xff);
00399                                                 sizes.Add(size);
00400                                         }
00401 
00402                                         long totalsize = 0;
00403                                         for(int i = 0; i < sizes.GetCount(); i++)
00404                                                 totalsize += sizes[i];
00405 
00406                                         sizes.Add(pTE->CodecPrivate.GetSize() - (p - (BYTE*)pTE->CodecPrivate) - totalsize);
00407                                         totalsize += sizes[sizes.GetCount()-1];
00408 
00409                                         if(sizes.GetCount() == 3)
00410                                         {
00411                                                 mt.subtype = MEDIASUBTYPE_Vorbis2;
00412                                                 mt.formattype = FORMAT_VorbisFormat2;
00413                                                 VORBISFORMAT2* pvf2 = (VORBISFORMAT2*)mt.AllocFormatBuffer(sizeof(VORBISFORMAT2) + totalsize);
00414                                                 memset(pvf2, 0, mt.FormatLength());
00415                                                 pvf2->Channels = (WORD)pTE->a.Channels;
00416                                                 pvf2->SamplesPerSec = (DWORD)pTE->a.SamplingFrequency;
00417                                                 pvf2->BitsPerSample = (DWORD)pTE->a.BitDepth;
00418                                                 BYTE* p2 = mt.Format() + sizeof(VORBISFORMAT2);
00419                                                 for(int i = 0; i < sizes.GetCount(); p += sizes[i], p2 += sizes[i], i++)
00420                                                         memcpy(p2, p, pvf2->HeaderSize[i] = sizes[i]);
00421 
00422                                                 mts.Add(mt);
00423                                         }
00424 
00425                                         mt.subtype = MEDIASUBTYPE_Vorbis;
00426                                         mt.formattype = FORMAT_VorbisFormat;
00427                                         VORBISFORMAT* pvf = (VORBISFORMAT*)mt.AllocFormatBuffer(sizeof(VORBISFORMAT));
00428                                         memset(pvf, 0, mt.FormatLength());
00429                                         pvf->nChannels = (WORD)pTE->a.Channels;
00430                                         pvf->nSamplesPerSec = (DWORD)pTE->a.SamplingFrequency;
00431                                         pvf->nMinBitsPerSec = pvf->nMaxBitsPerSec = pvf->nAvgBitsPerSec = -1;
00432                                         mts.Add(mt);
00433                                 }
00434                                 else if(CodecID == "A_MPEG/L3")
00435                                 {
00436                                         mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_MP3);
00437                                         mts.Add(mt);
00438                                 }
00439                                 else if(CodecID == "A_MPEG/L2")
00440                                 {                                       
00441                                         mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_MPEG);
00442                                         mts.Add(mt);
00443                                         // TODO : add MPEG1WAVEFORMAT
00444                                 }
00445                                 else if(CodecID == "A_AC3")
00446                                 {
00447                                         mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_DOLBY_AC3);
00448                                         mts.Add(mt);
00449                                 }
00450                                 else if(CodecID == "A_DTS")
00451                                 {
00452                                         mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_DVD_DTS);
00453                                         mts.Add(mt);
00454                                 }
00455                                 else if(CodecID == "A_FLAC")
00456                                 {
00457                                         mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_FLAC);
00458                                         pwfe->cbSize = pTE->CodecPrivate.GetCount();
00459                                         BYTE* pExtra = mt.ReallocFormatBuffer(sizeof(WAVEFORMATEX) + pTE->CodecPrivate.GetCount()) + sizeof(WAVEFORMATEX);
00460                                         memcpy(pExtra, pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetCount());
00461                                         mts.Add(mt);
00462 
00463                                         mt.subtype = MEDIASUBTYPE_FLAC_FRAMED;
00464                                         mts.InsertAt(0, mt);
00465                                 }
00466                                 else if(CodecID == "A_TTA1")
00467                                 {
00468                                         mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_TTA1);
00469                                         mts.Add(mt);
00470                                 }
00471                                 else if(CodecID == "A_MS/ACM")
00472                                 {
00473                                         pwfe = (WAVEFORMATEX*)mt.AllocFormatBuffer(pTE->CodecPrivate.GetCount());
00474                                         memcpy(pwfe, (WAVEFORMATEX*)(BYTE*)pTE->CodecPrivate, pTE->CodecPrivate.GetCount());
00475                                         mt.subtype = FOURCCMap(pwfe->wFormatTag);
00476                                         mts.Add(mt);
00477                                 }
00478                                 else if(CodecID == "A_PCM/INT/LIT")
00479                                 {
00480                                         mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_PCM);
00481                                         mts.Add(mt);
00482                                 }
00483                                 else if(CodecID == "A_PCM/FLOAT/IEEE")
00484                                 {
00485                                         mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_IEEE_FLOAT);
00486                                         mts.Add(mt);
00487                                 }
00488                                 else if(CodecID.Find("A_AAC/") == 0)
00489                                 {
00490                                         mt.subtype = FOURCCMap(pwfe->wFormatTag = WAVE_FORMAT_AAC);
00491                                         BYTE* pExtra = mt.ReallocFormatBuffer(sizeof(WAVEFORMATEX)+5) + sizeof(WAVEFORMATEX);
00492                                         (pwfe = (WAVEFORMATEX*)mt.pbFormat)->cbSize = 2;
00493 
00494                                         int profile;
00495 
00496                                         if(CodecID.Find("/MAIN") > 0) profile = 0;
00497                                         else if(CodecID.Find("/SBR") > 0) profile = -1;
00498                                         else if(CodecID.Find("/LC") > 0) profile = 1;
00499                                         else if(CodecID.Find("/SSR") > 0) profile = 2;
00500                                         else if(CodecID.Find("/LTP") > 0) profile = 3;
00501                                         else continue;
00502 
00503                                         WORD cbSize = MakeAACInitData(pExtra, profile, pwfe->nSamplesPerSec, pTE->a.Channels);
00504 
00505                                         mts.Add(mt);
00506 
00507                                         if(profile < 0)
00508                                         {
00509                                                 pwfe->cbSize = cbSize;
00510                                                 pwfe->nSamplesPerSec *= 2;
00511                                                 pwfe->nAvgBytesPerSec *= 2;
00512 
00513                                                 mts.InsertAt(0, mt);
00514                                         }
00515                                 }
00516                                 else if(CodecID.Find("A_REAL/") == 0 && CodecID.GetLength() >= 11)
00517                                 {
00518                                         mt.bTemporalCompression = TRUE;
00519                                         mt.subtype = FOURCCMap((DWORD)CodecID[7]|((DWORD)CodecID[8]<<8)|((DWORD)CodecID[9]<<16)|((DWORD)CodecID[10]<<24));
00520                                         BYTE* p = mt.ReallocFormatBuffer(sizeof(WAVEFORMATEX) + pTE->CodecPrivate.GetCount());
00521                                         memcpy(p + sizeof(WAVEFORMATEX), pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetCount());
00522 
00523                                         mts.Add(mt);
00524                                 }
00525                         }
00526                         else if(pTE->TrackType == TrackEntry::TypeSubtitle)
00527                         {
00528                                 if(iSubtitle == 1) InstallFonts();
00529 
00530                                 Name.Format(L"Subtitle %d", iSubtitle++);
00531 
00532                                 mt.SetSampleSize(1);
00533 
00534                                 if(CodecID == "S_TEXT/ASCII")
00535                                 {
00536                                         mt.majortype = MEDIATYPE_Text;
00537                                         mt.subtype = MEDIASUBTYPE_NULL;
00538                                         mt.formattype = FORMAT_None;
00539                                         mts.Add(mt);
00540                                 }
00541                                 else
00542                                 {
00543                                         mt.majortype = MEDIATYPE_Subtitle;
00544                                         mt.formattype = FORMAT_SubtitleInfo;
00545                                         SUBTITLEINFO* psi = (SUBTITLEINFO*)mt.AllocFormatBuffer(sizeof(SUBTITLEINFO) + pTE->CodecPrivate.GetSize());
00546                                         memset(psi, 0, mt.FormatLength());
00547                                         strncpy(psi->IsoLang, pTE->Language, countof(psi->IsoLang)-1);
00548                                         wcsncpy(psi->TrackName, pTE->Name, countof(psi->TrackName)-1);
00549                                         memcpy(mt.pbFormat + (psi->dwOffset = sizeof(SUBTITLEINFO)), pTE->CodecPrivate.GetData(), pTE->CodecPrivate.GetSize());
00550 
00551                                         mt.subtype = 
00552                                                 CodecID == "S_TEXT/UTF8" ? MEDIASUBTYPE_UTF8 :
00553                                                 CodecID == "S_TEXT/SSA" || CodecID == "S_SSA" ? MEDIASUBTYPE_SSA :
00554                                                 CodecID == "S_TEXT/ASS" || CodecID == "S_ASS" ? MEDIASUBTYPE_ASS :
00555                                                 CodecID == "S_TEXT/USF" || CodecID == "S_USF" ? MEDIASUBTYPE_USF :
00556                                                 CodecID == "S_VOBSUB" ? MEDIASUBTYPE_VOBSUB :
00557                                                 MEDIASUBTYPE_NULL;
00558 
00559                                         if(mt.subtype != MEDIASUBTYPE_NULL)
00560                                                 mts.Add(mt);
00561                                 }
00562                         }
00563 
00564                         if(mts.IsEmpty())
00565                         {
00566                                 TRACE(_T("CMatroskaSourceFilter: Unsupported TrackType %s (%I64d)\n"), CString(CodecID), (UINT64)pTE->TrackType);
00567                                 continue;
00568                         }
00569 
00570                         Name = CStringW(pTE->Language.IsEmpty() ? L"English" : CStringW(ISO6392ToLanguage(pTE->Language)))
00571                                 + (pTE->Name.IsEmpty() ? L"" : L", " + pTE->Name)
00572                                 + (L" (" + Name + L")");
00573 
00574                         HRESULT hr;
00575 
00576                         CAutoPtr<CBaseSplitterOutputPin> pPinOut(new CMatroskaSplitterOutputPin((int)pTE->MinCache, pTE->DefaultDuration/100, mts, Name, this, this, &hr));
00577                         if(!pTE->Name.IsEmpty()) pPinOut->SetProperty(L"NAME", pTE->Name);
00578                         if(pTE->Language.GetLength() == 3) pPinOut->SetProperty(L"LANG", CStringW(CString(pTE->Language)));
00579                         AddOutputPin((DWORD)pTE->TrackNumber, pPinOut);
00580 
00581                         m_pTrackEntryMap[(DWORD)pTE->TrackNumber] = pTE;                                
00582                         m_pOrderedTrackArray.Add(pTE);
00583                 }
00584         }
00585 
00586         Info& info = m_pFile->m_segment.SegmentInfo;
00587         m_rtNewStart = m_rtCurrent = 0;
00588         m_rtNewStop = m_rtStop = (REFERENCE_TIME)(info.Duration*info.TimeCodeScale/100);
00589 
00590 #ifdef DEBUG
00591         /*
00592         for(int i = 1, j = GetChapterCount(CHAPTER_ROOT_ID); i <= j; i++)
00593         {
00594                 UINT id = GetChapterId(CHAPTER_ROOT_ID, i);
00595                 struct ChapterElement ce;
00596                 BOOL b = GetChapterInfo(id, &ce);
00597                 BSTR bstr = GetChapterStringInfo(id, "eng", "");
00598                 if(bstr) ::SysFreeString(bstr);
00599         }
00600         */
00601 #endif
00602 
00603         SetProperty(L"TITL", info.Title);
00604         // TODO
00605 
00606         // resources
00607 
00608         {
00609                 POSITION pos = m_pFile->m_segment.Attachments.GetHeadPosition();
00610                 while(pos)
00611                 {
00612                         Attachment* pA = m_pFile->m_segment.Attachments.GetNext(pos);
00613 
00614                         POSITION pos = pA->AttachedFiles.GetHeadPosition();
00615                         while(pos)
00616                         {
00617                                 AttachedFile* pF = pA->AttachedFiles.GetNext(pos);
00618 
00619                                 CArray<BYTE> pData;
00620                                 pData.SetSize(pF->FileDataLen);
00621                                 m_pFile->Seek(pF->FileDataPos);
00622                                 if(SUCCEEDED(m_pFile->Read(pData.GetData(), pData.GetSize())))
00623                                         ResAppend(pF->FileName, pF->FileDescription, CStringW(pF->FileMimeType), pData.GetData(), pData.GetSize());
00624                         }
00625                 }
00626         }
00627 
00628         // chapters
00629 
00630         if(ChapterAtom* caroot = m_pFile->m_segment.FindChapterAtom(0))
00631         {
00632                 CStringA str;
00633                 str.ReleaseBufferSetLength(GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, str.GetBuffer(3), 3));
00634                 CStringA ChapLanguage = CStringA(ISO6391To6392(str));
00635                 if(ChapLanguage.GetLength() < 3) ChapLanguage = "eng";
00636 
00637                 POSITION pos = caroot->ChapterAtoms.GetHeadPosition();
00638                 while(pos)
00639                 {
00640                         // ca == caroot->ChapterAtoms.GetNext(pos) ?
00641                         if(ChapterAtom* ca = m_pFile->m_segment.FindChapterAtom(caroot->ChapterAtoms.GetNext(pos)->ChapterUID))
00642                         {
00643                                 CStringW name, first;
00644 
00645                                 POSITION pos = ca->ChapterDisplays.GetHeadPosition();
00646                                 while(pos)
00647                                 {
00648                                         ChapterDisplay* cd = ca->ChapterDisplays.GetNext(pos);
00649                                         if(first.IsEmpty()) first = cd->ChapString;
00650                                         if(cd->ChapLanguage == ChapLanguage) name = cd->ChapString;
00651                                 }
00652 
00653                                 ChapAppend(ca->ChapterTimeStart / 100 - m_pFile->m_rtOffset, !name.IsEmpty() ? name : first);
00654                         }                       
00655                 }
00656         }
00657 
00658         return m_pOutputs.GetCount() > 0 ? S_OK : E_FAIL;
00659 }
00660 
00661 void CMatroskaSplitterFilter::InstallFonts()
00662 {
00663         POSITION pos = m_pFile->m_segment.Attachments.GetHeadPosition();
00664         while(pos)
00665         {
00666                 Attachment* pA = m_pFile->m_segment.Attachments.GetNext(pos);
00667 
00668                 POSITION p2 = pA->AttachedFiles.GetHeadPosition();
00669                 while(p2)
00670                 {
00671                         AttachedFile* pF = pA->AttachedFiles.GetNext(p2);
00672 
00673                         if(pF->FileMimeType == "application/x-truetype-font")
00674                         {
00675                                 // assume this is a font resource
00676 
00677                                 if(BYTE* pData = new BYTE[(UINT)pF->FileDataLen])
00678                                 {
00679                                         m_pFile->Seek(pF->FileDataPos);
00680 
00681                                         if(SUCCEEDED(m_pFile->Read(pData, pF->FileDataLen)))
00682                                                 m_fontinst.InstallFont(pData, (UINT)pF->FileDataLen);
00683 
00684                                         delete [] pData;
00685                                 }
00686                         }
00687                 }
00688         }
00689 }
00690 
00691 void CMatroskaSplitterFilter::SendVorbisHeaderSample()
00692 {
00693         HRESULT hr;
00694 
00695         POSITION pos = m_pTrackEntryMap.GetStartPosition();
00696         while(pos)
00697         {
00698                 DWORD TrackNumber = 0;
00699                 TrackEntry* pTE = NULL;
00700                 m_pTrackEntryMap.GetNextAssoc(pos, TrackNumber, pTE);
00701 
00702                 CBaseSplitterOutputPin* pPin = GetOutputPin(TrackNumber);
00703 
00704                 if(!(pTE && pPin && pPin->IsConnected()))
00705                         continue;
00706 
00707                 if(pTE->CodecID.ToString() == "A_VORBIS" && pPin->CurrentMediaType().subtype == MEDIASUBTYPE_Vorbis
00708                 && pTE->CodecPrivate.GetSize() > 0)
00709                 {
00710                         BYTE* ptr = (BYTE*)pTE->CodecPrivate;
00711 
00712                         CList<long> sizes;
00713                         long last = 0;
00714                         for(BYTE n = *ptr++; n > 0; n--)
00715                         {
00716                                 long size = 0;
00717                                 do {size += *ptr;} while(*ptr++ == 0xff);
00718                                 sizes.AddTail(size);
00719                                 last += size;
00720                         }
00721                         sizes.AddTail(pTE->CodecPrivate.GetSize() - (ptr - (BYTE*)pTE->CodecPrivate) - last);
00722 
00723                         hr = S_OK;
00724 
00725                         POSITION pos = sizes.GetHeadPosition();
00726                         while(pos && SUCCEEDED(hr))
00727                         {
00728                                 long len = sizes.GetNext(pos);
00729 
00730                                 CAutoPtr<Packet> p(new Packet());
00731                                 p->TrackNumber = (DWORD)pTE->TrackNumber;
00732                                 p->rtStart = 0; p->rtStop = 1;
00733                                 p->bSyncPoint = FALSE;
00734                                 p->pData.SetSize(len);
00735                                 memcpy(p->pData.GetData(), ptr, len);
00736                                 ptr += len;
00737 
00738                                 hr = DeliverPacket(p);
00739                         }
00740 
00741                         if(FAILED(hr))
00742                                 TRACE(_T("ERROR: Vorbis initialization failed for stream %I64d\n"), TrackNumber);
00743                 }
00744         }
00745 }
00746 
00747 bool CMatroskaSplitterFilter::DemuxInit()
00748 {
00749         CMatroskaNode Root(m_pFile);
00750         if(!m_pFile
00751         || !(m_pSegment = Root.Child(0x18538067))
00752         || !(m_pCluster = m_pSegment->Child(0x1F43B675)))
00753                 return(false);
00754 
00755         // reindex if needed
00756 
00757         if(m_pFile->m_segment.Cues.GetCount() == 0)
00758         {
00759                 m_nOpenProgress = 0;
00760                 m_pFile->m_segment.SegmentInfo.Duration.Set(0);
00761 
00762                 UINT64 TrackNumber = m_pFile->m_segment.GetMasterTrack();
00763 
00764                 CAutoPtr<Cue> pCue(new Cue());
00765 
00766                 do
00767                 {
00768                         Cluster c;
00769                         c.ParseTimeCode(m_pCluster);
00770 
00771                         m_pFile->m_segment.SegmentInfo.Duration.Set((float)c.TimeCode - m_pFile->m_rtOffset/10000);
00772 
00773                         CAutoPtr<CuePoint> pCuePoint(new CuePoint());
00774                         CAutoPtr<CueTrackPosition> pCueTrackPosition(new CueTrackPosition());
00775                         pCuePoint->CueTime.Set(c.TimeCode);
00776                         pCueTrackPosition->CueTrack.Set(TrackNumber);
00777                         pCueTrackPosition->CueClusterPosition.Set(m_pCluster->m_filepos - m_pSegment->m_start);
00778                         pCuePoint->CueTrackPositions.AddTail(pCueTrackPosition);
00779                         pCue->CuePoints.AddTail(pCuePoint);
00780 
00781                         m_nOpenProgress = m_pFile->GetPos()*100/m_pFile->GetLength();
00782 
00783                         DWORD cmd;
00784                         if(CheckRequest(&cmd))
00785                         {
00786                                 if(cmd == CMD_EXIT) m_fAbort = true;
00787                                 else Reply(S_OK);
00788                         }
00789                 }
00790                 while(!m_fAbort && m_pCluster->Next(true));
00791 
00792                 m_nOpenProgress = 100;
00793 
00794                 if(!m_fAbort) m_pFile->m_segment.Cues.AddTail(pCue);
00795 
00796                 m_fAbort = false;
00797         }
00798 
00799         m_pCluster.Free();
00800         m_pBlock.Free();
00801 
00802         return(true);
00803 }
00804 
00805 void CMatroskaSplitterFilter::DemuxSeek(REFERENCE_TIME rt)
00806 {
00807         m_pCluster = m_pSegment->Child(0x1F43B675);
00808         m_pBlock.Free();
00809 
00810         if(rt > 0)
00811         {
00812                 rt += m_pFile->m_rtOffset;
00813 
00814                 QWORD lastCueClusterPosition = -1;
00815 
00816                 Segment& s = m_pFile->m_segment;
00817 
00818                 UINT64 TrackNumber = s.GetMasterTrack();
00819 
00820                 POSITION pos1 = s.Cues.GetHeadPosition();
00821                 while(pos1)
00822                 {
00823                         Cue* pCue = s.Cues.GetNext(pos1);
00824 
00825                         POSITION pos2 = pCue->CuePoints.GetTailPosition();
00826                         while(pos2)
00827                         {
00828                                 CuePoint* pCuePoint = pCue->CuePoints.GetPrev(pos2);
00829 
00830                                 if(rt < s.GetRefTime(pCuePoint->CueTime))
00831                                         continue;
00832 
00833                                 POSITION pos3 = pCuePoint->CueTrackPositions.GetHeadPosition();
00834                                 while(pos3)
00835                                 {
00836                                         CueTrackPosition* pCueTrackPositions = pCuePoint->CueTrackPositions.GetNext(pos3);
00837 
00838                                         if(TrackNumber != pCueTrackPositions->CueTrack)
00839                                                 continue;
00840 
00841                                         if(lastCueClusterPosition == pCueTrackPositions->CueClusterPosition)
00842                                                 continue;
00843 
00844                                         lastCueClusterPosition = pCueTrackPositions->CueClusterPosition;
00845 
00846                                         m_pCluster->SeekTo(m_pSegment->m_start + pCueTrackPositions->CueClusterPosition);
00847                                         m_pCluster->Parse();
00848 
00849                                         bool fFoundKeyFrame = false;
00850 /*
00851                                         if(pCueTrackPositions->CueBlockNumber > 0)
00852                                         {
00853                                                 // TODO: CueBlockNumber only tells the block num of the track and not for all mixed in the cluster
00854                                                 m_nLastBlock = (int)pCueTrackPositions->CueBlockNumber;
00855                                                 fFoundKeyFrame = true;
00856                                         }
00857                                         else
00858 */
00859                                         {
00860                                                 Cluster c;
00861                                                 c.ParseTimeCode(m_pCluster);
00862 
00863                                                 if(CAutoPtr<CMatroskaNode> pBlock = m_pCluster->GetFirstBlock())
00864                                                 {
00865                                                         bool fPassedCueTime = false;
00866 
00867                                                         do
00868                                                         {
00869                                                                 CBlockGroupNode bgn;
00870 
00871                                                                 if(pBlock->m_id == 0xA0)
00872                                                                 {
00873                                                                         bgn.Parse(pBlock, true);
00874                                                                 }
00875                                                                 else if(pBlock->m_id == 0xA3)
00876                                                                 {
00877                                                                         CAutoPtr<BlockGroup> bg(new BlockGroup());
00878                                                                         bg->Block.Parse(pBlock, true);
00879                                                                         if(!(bg->Block.Lacing & 0x80)) bg->ReferenceBlock.Set(0); // not a kf
00880                                                                         bgn.AddTail(bg);
00881                                                                 }
00882 
00883                                                                 POSITION pos4 = bgn.GetHeadPosition();
00884                                                                 while(!fPassedCueTime && pos4)
00885                                                                 {
00886                                                                         BlockGroup* bg = bgn.GetNext(pos4);
00887 
00888                                                                         if(bg->Block.TrackNumber == pCueTrackPositions->CueTrack && rt < s.GetRefTime(c.TimeCode + bg->Block.TimeCode)
00889                                                                         || rt + 5000000i64 < s.GetRefTime(c.TimeCode + bg->Block.TimeCode)) // allow 500ms difference between tracks, just in case intreleaving wasn't that much precise
00890                                                                         {
00891                                                                                 fPassedCueTime = true;
00892                                                                         }
00893                                                                         else if(bg->Block.TrackNumber == pCueTrackPositions->CueTrack && !bg->ReferenceBlock.IsValid())
00894                                                                         {
00895                                                                                 fFoundKeyFrame = true;
00896                                                                                 m_pBlock = pBlock->Copy();
00897                                                                         }
00898                                                                 }
00899                                                         }
00900                                                         while(!fPassedCueTime && pBlock->NextBlock());
00901                                                 }
00902                                         }
00903 
00904                                         if(fFoundKeyFrame)
00905                                                 pos1 = pos2 = pos3 = NULL;
00906                                 }
00907                         }
00908                 }
00909 
00910                 if(!m_pBlock)
00911                 {
00912                         m_pCluster = m_pSegment->Child(0x1F43B675);
00913                 }
00914         }
00915 }
00916 
00917 bool CMatroskaSplitterFilter::DemuxLoop()
00918 {
00919         HRESULT hr = S_OK;
00920         
00921         SendVorbisHeaderSample(); // HACK: init vorbis decoder with the headers
00922 
00923         do
00924         {
00925                 Cluster c;
00926                 c.ParseTimeCode(m_pCluster);
00927 
00928                 if(!m_pBlock) m_pBlock = m_pCluster->GetFirstBlock();
00929                 if(!m_pBlock) continue;
00930 
00931                 do
00932                 {
00933                         CBlockGroupNode bgn;
00934 
00935                         if(m_pBlock->m_id == 0xA0)
00936                         {
00937                                 bgn.Parse(m_pBlock, true);
00938                         }
00939                         else if(m_pBlock->m_id == 0xA3)
00940                         {
00941                                 CAutoPtr<BlockGroup> bg(new BlockGroup());
00942                                 bg->Block.Parse(m_pBlock, true);
00943                                 if(!(bg->Block.Lacing & 0x80)) bg->ReferenceBlock.Set(0); // not a kf
00944                                 bgn.AddTail(bg);
00945                         }
00946 
00947                         while(bgn.GetCount())
00948                         {
00949                                 CAutoPtr<MatroskaPacket> p(new MatroskaPacket());
00950                                 p->bg = bgn.RemoveHead();
00951 
00952                                 p->bSyncPoint = !p->bg->ReferenceBlock.IsValid();
00953                                 p->TrackNumber = (DWORD)p->bg->Block.TrackNumber;
00954 
00955                                 TrackEntry *pTE = m_pTrackEntryMap[p->TrackNumber];
00956                                 p->rtStart = m_pFile->m_segment.GetRefTime((REFERENCE_TIME)c.TimeCode + p->bg->Block.TimeCode);
00957                                 p->rtStop = p->rtStart + (p->bg->BlockDuration.IsValid() ? m_pFile->m_segment.GetRefTime(p->bg->BlockDuration) : 1);
00958 
00959                                 // Fix subtitle with duration = 0
00960                                 if(pTE && (pTE->TrackType == TrackEntry::TypeSubtitle) && (!p->bg->BlockDuration.IsValid()))
00961                                 {
00962                                         p->bg->BlockDuration.Set(1); // just setting it to be valid
00963                                         p->rtStop = p->rtStart;
00964                                 }
00965 
00966                                 POSITION pos = p->bg->Block.BlockData.GetHeadPosition();
00967                                 while(pos)
00968                                 {
00969                                         CBinary* pb = p->bg->Block.BlockData.GetNext(pos);
00970                                         m_pTrackEntryMap[p->TrackNumber]->Expand(*pb, ContentEncoding::AllFrameContents);
00971                                 }
00972 
00973                                 // HACK
00974                                 p->rtStart -= m_pFile->m_rtOffset;
00975                                 p->rtStop -= m_pFile->m_rtOffset;
00976 
00977                                 hr = DeliverPacket(p);
00978                         }
00979                 }
00980                 while(m_pBlock->NextBlock() && SUCCEEDED(hr) && !CheckRequest(NULL));
00981 
00982                 m_pBlock.Free();
00983         }
00984         while(m_pFile->GetPos() < m_pFile->m_segment.pos + m_pFile->m_segment.len 
00985                 && m_pCluster->Next(true) && SUCCEEDED(hr) && !CheckRequest(NULL));
00986 
00987         m_pCluster.Free();
00988 
00989         return(true);
00990 }
00991 
00992 // IMediaSeeking
00993 
00994 STDMETHODIMP CMatroskaSplitterFilter::GetDuration(LONGLONG* pDuration)
00995 {
00996         CheckPointer(pDuration, E_POINTER);
00997         CheckPointer(m_pFile, VFW_E_NOT_CONNECTED);
00998 
00999         Segment& s = m_pFile->m_segment;
01000         *pDuration = s.GetRefTime((INT64)s.SegmentInfo.Duration);
01001 
01002         return S_OK;
01003 }
01004 
01005 // IKeyFrameInfo
01006 
01007 STDMETHODIMP CMatroskaSplitterFilter::GetKeyFrameCount(UINT& nKFs)
01008 {
01009         if(!m_pFile) return E_UNEXPECTED;
01010 
01011         HRESULT hr = S_OK;
01012 
01013         nKFs = 0;
01014 
01015         POSITION pos = m_pFile->m_segment.Cues.GetHeadPosition();
01016         while(pos) nKFs += m_pFile->m_segment.Cues.GetNext(pos)->CuePoints.GetCount();
01017 
01018         return hr;
01019 }
01020 
01021 STDMETHODIMP CMatroskaSplitterFilter::GetKeyFrames(const GUID* pFormat, REFERENCE_TIME* pKFs, UINT& nKFs)
01022 {
01023         CheckPointer(pFormat, E_POINTER);
01024         CheckPointer(pKFs, E_POINTER);
01025 
01026         if(!m_pFile) return E_UNEXPECTED;
01027         if(*pFormat != TIME_FORMAT_MEDIA_TIME) return E_INVALIDARG;
01028 
01029         UINT nKFsTmp = 0;
01030 
01031         POSITION pos1 = m_pFile->m_segment.Cues.GetHeadPosition();
01032         while(pos1 && nKFsTmp < nKFs)
01033         {
01034                 Cue* pCue = m_pFile->m_segment.Cues.GetNext(pos1);
01035 
01036                 POSITION pos2 = pCue->CuePoints.GetHeadPosition();
01037                 while(pos2 && nKFsTmp < nKFs)
01038                         pKFs[nKFsTmp++] = m_pFile->m_segment.GetRefTime(pCue->CuePoints.GetNext(pos2)->CueTime);
01039         }
01040 
01041         nKFs = nKFsTmp;
01042 
01043         return S_OK;
01044 }
01045 
01046 //
01047 // CMatroskaSourceFilter
01048 //
01049 
01050 CMatroskaSourceFilter::CMatroskaSourceFilter(LPUNKNOWN pUnk, HRESULT* phr)
01051         : CMatroskaSplitterFilter(pUnk, phr)
01052 {
01053         m_clsid = __uuidof(this);
01054         m_pInput.Free();
01055 }
01056 
01057 //
01058 // CMatroskaSplitterOutputPin
01059 //
01060 
01061 CMatroskaSplitterOutputPin::CMatroskaSplitterOutputPin(
01062                 int nMinCache, REFERENCE_TIME rtDefaultDuration,
01063                 CArray<CMediaType>& mts, LPCWSTR pName, CBaseFilter* pFilter, CCritSec* pLock, HRESULT* phr)
01064         : CBaseSplitterOutputPin(mts, pName, pFilter, pLock, phr)
01065         , m_nMinCache(nMinCache), m_rtDefaultDuration(rtDefaultDuration)
01066 {
01067         m_nMinCache = max(m_nMinCache, 1);
01068 }
01069 
01070 CMatroskaSplitterOutputPin::~CMatroskaSplitterOutputPin()
01071 {
01072 }
01073 
01074 HRESULT CMatroskaSplitterOutputPin::DeliverEndFlush()
01075 {
01076         {
01077                 CAutoLock cAutoLock(&m_csQueue);
01078                 m_packets.RemoveAll();
01079                 m_rob.RemoveAll();
01080                 m_tos.RemoveAll();
01081         }
01082 
01083         return __super::DeliverEndFlush();
01084 }
01085 
01086 HRESULT CMatroskaSplitterOutputPin::DeliverEndOfStream()
01087 {
01088         CAutoLock cAutoLock(&m_csQueue);
01089 
01090         // send out the last remaining packets from the queue
01091 
01092         while(m_rob.GetCount())
01093         {
01094                 MatroskaPacket* mp = m_rob.RemoveHead();
01095                 if(m_rob.GetCount() && !mp->bg->BlockDuration.IsValid()) 
01096                         mp->rtStop = m_rob.GetHead()->rtStart;
01097                 else if(m_rob.GetCount() == 0 && m_rtDefaultDuration > 0)
01098                         mp->rtStop = mp->rtStart + m_rtDefaultDuration;
01099 
01100                 timeoverride to = {mp->rtStart, mp->rtStop};
01101                 m_tos.AddTail(to);
01102         }
01103 
01104         while(m_packets.GetCount())
01105         {
01106                 HRESULT hr = DeliverBlock(m_packets.RemoveHead());
01107                 if(hr != S_OK) return hr;
01108         }
01109 
01110         return __super::DeliverEndOfStream();
01111 }
01112 
01113 HRESULT CMatroskaSplitterOutputPin::DeliverPacket(CAutoPtr<Packet> p)
01114 {
01115         MatroskaPacket* mp = dynamic_cast<MatroskaPacket*>(p.m_p);
01116         if(!mp) return __super::DeliverPacket(p);
01117 
01118         // don't try to understand what's happening here, it's magic
01119 
01120         CAutoLock cAutoLock(&m_csQueue);
01121 
01122         CAutoPtr<MatroskaPacket> p2;
01123         p.Detach();
01124         p2.Attach(mp);
01125         m_packets.AddTail(p2);
01126 
01127         POSITION pos = m_rob.GetTailPosition();
01128         for(int i = m_nMinCache-1; i > 0 && pos && mp->bg->ReferencePriority < m_rob.GetAt(pos)->bg->ReferencePriority; i--)
01129                 m_rob.GetPrev(pos);
01130 
01131         if(!pos) m_rob.AddHead(mp);
01132         else m_rob.InsertAfter(pos, mp);
01133 
01134         mp = NULL;
01135 
01136         if(m_rob.GetCount() == m_nMinCache+1)
01137         {
01138                 ASSERT(m_nMinCache > 0);
01139                 pos = m_rob.GetHeadPosition();
01140                 MatroskaPacket* mp1 = m_rob.GetNext(pos);
01141                 MatroskaPacket* mp2 = m_rob.GetNext(pos);
01142                 if(!mp1->bg->BlockDuration.IsValid())
01143                 {
01144                         mp1->bg->BlockDuration.Set(1); // just to set it valid
01145 
01146                         if(mp1->rtStart >= mp2->rtStart)
01147                         {
01148 /*                              CString str;
01149                                 str.Format(_T("mp1->rtStart (%I64d) >= mp2->rtStart (%I64d)!!!\n"), mp1->rtStart, mp2->rtStart);
01150                                 AfxMessageBox(str);
01151 */                              
01152                                 // TRACE(_T("mp1->rtStart (%I64d) >= mp2->rtStart (%I64d)!!!\n"), mp1->rtStart, mp2->rtStart);
01153                         }
01154                         else
01155                         {
01156                                 mp1->rtStop = mp2->rtStart;
01157                         }
01158                 }
01159         }
01160 
01161         while(m_packets.GetCount())
01162         {
01163                 mp = m_packets.GetHead();
01164                 if(!mp->bg->BlockDuration.IsValid()) break;
01165         
01166                 mp = m_rob.RemoveHead();
01167                 timeoverride to = {mp->rtStart, mp->rtStop};
01168                 m_tos.AddTail(to);
01169 
01170                 HRESULT hr = DeliverBlock(m_packets.RemoveHead());
01171                 if(hr != S_OK) return hr;
01172         }
01173 
01174         return S_OK;
01175 }
01176 
01177 HRESULT CMatroskaSplitterOutputPin::DeliverBlock(MatroskaPacket* p)
01178 {
01179         HRESULT hr = S_FALSE;
01180 
01181         if(m_tos.GetCount())
01182         {
01183                 timeoverride to = m_tos.RemoveHead();
01184 //              if(p->TrackNumber == 2)
01185                 TRACE(_T("(track=%d) %I64d, %I64d -> %I64d, %I64d (buffcnt=%d)\n"), 
01186                         p->TrackNumber, p->rtStart, p->rtStop, to.rtStart, to.rtStop,
01187                         QueueCount());
01188 
01189                 p->rtStart = to.rtStart;
01190                 p->rtStop = to.rtStop;
01191         }
01192                 
01193         REFERENCE_TIME 
01194                 rtStart = p->rtStart,
01195                 rtDelta = (p->rtStop - p->rtStart) / p->bg->Block.BlockData.GetCount(),
01196                 rtStop = p->rtStart + rtDelta;
01197 
01198         POSITION pos = p->bg->Block.BlockData.GetHeadPosition();
01199         while(pos)
01200         {
01201                 CAutoPtr<Packet> tmp(new Packet());
01202                 tmp->TrackNumber = p->TrackNumber;
01203                 tmp->bDiscontinuity = p->bDiscontinuity;
01204                 tmp->bSyncPoint = p->bSyncPoint;
01205                 tmp->rtStart = rtStart;
01206                 tmp->rtStop = rtStop;
01207                 tmp->pData.Copy(*p->bg->Block.BlockData.GetNext(pos));
01208                 if(S_OK != (hr = DeliverPacket(tmp))) break;
01209 
01210                 rtStart += rtDelta;
01211                 rtStop += rtDelta;
01212 
01213                 p->bSyncPoint = false;
01214                 p->bDiscontinuity = false;
01215         }
01216 
01217         return hr;
01218 }
01219 
01220 // ITrackInfo
01221 
01222 TrackEntry* CMatroskaSplitterFilter::GetTrackEntryAt(UINT aTrackIdx)
01223 {
01224         if(aTrackIdx < 0 || aTrackIdx >= m_pOrderedTrackArray.GetCount())
01225                 return NULL;    
01226         return m_pOrderedTrackArray[aTrackIdx];
01227 }
01228 
01229 STDMETHODIMP_(UINT) CMatroskaSplitterFilter::GetTrackCount()
01230 {       
01231         return m_pTrackEntryMap.GetCount();
01232 }
01233 
01234 STDMETHODIMP_(BOOL) CMatroskaSplitterFilter::GetTrackInfo(UINT aTrackIdx, struct TrackElement* pStructureToFill)
01235 {
01236         TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
01237         if(pTE == NULL)
01238                 return FALSE;
01239 
01240         pStructureToFill->FlagDefault = !!pTE->FlagDefault;
01241         pStructureToFill->FlagLacing = !!pTE->FlagLacing;
01242         strncpy(pStructureToFill->Language, pTE->Language, 3);
01243         if(pStructureToFill->Language[0] == '\0')
01244                 strncpy(pStructureToFill->Language, "eng", 3);
01245         pStructureToFill->Language[3] = '\0';
01246         pStructureToFill->MaxCache = (UINT)pTE->MaxCache;
01247         pStructureToFill->MinCache = (UINT)pTE->MinCache;
01248         pStructureToFill->Type = (BYTE)pTE->TrackType;
01249         return TRUE;
01250 }
01251 
01252 STDMETHODIMP_(BOOL) CMatroskaSplitterFilter::GetTrackExtendedInfo(UINT aTrackIdx, void* pStructureToFill)
01253 {
01254         TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
01255         if(pTE == NULL)
01256                 return FALSE;
01257 
01258         if(pTE->TrackType == TrackEntry::TypeVideo)
01259         {
01260                 TrackExtendedInfoVideo* pTEIV = (TrackExtendedInfoVideo*)pStructureToFill;
01261                 pTEIV->AspectRatioType = (BYTE)pTE->v.AspectRatioType;          
01262                 pTEIV->DisplayUnit = (BYTE)pTE->v.DisplayUnit;
01263                 pTEIV->DisplayWidth = (UINT)pTE->v.DisplayWidth;                
01264                 pTEIV->DisplayHeight = (UINT)pTE->v.DisplayHeight;
01265                 pTEIV->Interlaced = !!pTE->v.FlagInterlaced;
01266                 pTEIV->PixelWidth = (UINT)pTE->v.PixelWidth;
01267                 pTEIV->PixelHeight = (UINT)pTE->v.PixelHeight;
01268         } else if(pTE->TrackType == TrackEntry::TypeAudio) {
01269                 TrackExtendedInfoAudio* pTEIA = (TrackExtendedInfoAudio*)pStructureToFill;
01270                 pTEIA->BitDepth = (UINT)pTE->a.BitDepth;
01271                 pTEIA->Channels = (UINT)pTE->a.Channels;
01272                 pTEIA->OutputSamplingFrequency = pTE->a.OutputSamplingFrequency;
01273                 pTEIA->SamplingFreq = pTE->a.SamplingFrequency;
01274         } else {
01275                 return FALSE;
01276         }
01277         
01278         return TRUE;
01279 }
01280 
01281 STDMETHODIMP_(BSTR) CMatroskaSplitterFilter::GetTrackName(UINT aTrackIdx)
01282 {
01283         TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
01284         if(pTE == NULL)
01285                 return NULL;
01286         return pTE->Name.AllocSysString();
01287 }
01288 
01289 STDMETHODIMP_(BSTR) CMatroskaSplitterFilter::GetTrackCodecID(UINT aTrackIdx)
01290 {
01291         TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
01292         if(pTE == NULL)
01293                 return NULL;
01294         return pTE->CodecID.ToString().AllocSysString();
01295 }
01296 
01297 STDMETHODIMP_(BSTR) CMatroskaSplitterFilter::GetTrackCodecName(UINT aTrackIdx)
01298 {
01299         TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
01300         if(pTE == NULL)
01301                 return NULL;
01302         return pTE->CodecName.AllocSysString();
01303 }
01304 
01305 STDMETHODIMP_(BSTR) CMatroskaSplitterFilter::GetTrackCodecInfoURL(UINT aTrackIdx)
01306 {
01307         TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
01308         if(pTE == NULL)
01309                 return NULL;
01310         return pTE->CodecInfoURL.AllocSysString();
01311 }
01312 
01313 STDMETHODIMP_(BSTR) CMatroskaSplitterFilter::GetTrackCodecDownloadURL(UINT aTrackIdx)
01314 {
01315         TrackEntry* pTE = GetTrackEntryAt(aTrackIdx);
01316         if(pTE == NULL)
01317                 return NULL;
01318         return pTE->CodecDownloadURL.AllocSysString();
01319 }

Generated on Tue Dec 13 14:47:18 2005 for guliverkli by  doxygen 1.4.5