00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "DSMMuxer.h"
00024 #include "..\..\..\DSUtil\DSUtil.h"
00025
00026 #include <initguid.h>
00027 #include <qnetwork.h>
00028 #include "..\..\..\..\include\moreuuids.h"
00029
00030 #ifdef REGISTER_FILTER
00031
00032 const AMOVIESETUP_MEDIATYPE sudPinTypesOut[] =
00033 {
00034 {&MEDIATYPE_Stream, &MEDIASUBTYPE_DirectShowMedia}
00035 };
00036
00037 const AMOVIESETUP_PIN sudpPins[] =
00038 {
00039 {L"Input", FALSE, FALSE, FALSE, TRUE, &CLSID_NULL, NULL, 0, NULL},
00040 {L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, countof(sudPinTypesOut), sudPinTypesOut}
00041 };
00042
00043 const AMOVIESETUP_FILTER sudFilter[] =
00044 {
00045 {&__uuidof(CDSMMuxerFilter), L"DSM Muxer", MERIT_DO_NOT_USE, countof(sudpPins), sudpPins}
00046 };
00047
00048 CFactoryTemplate g_Templates[] =
00049 {
00050 {sudFilter[0].strName, sudFilter[0].clsID, CreateInstance<CDSMMuxerFilter>, NULL, &sudFilter[0]}
00051 };
00052
00053 int g_cTemplates = countof(g_Templates);
00054
00055 STDAPI DllRegisterServer()
00056 {
00057 return AMovieDllRegisterServer2(TRUE);
00058 }
00059
00060 STDAPI DllUnregisterServer()
00061 {
00062 return AMovieDllRegisterServer2(FALSE);
00063 }
00064
00065 extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
00066
00067 BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
00068 {
00069 return DllEntryPoint((HINSTANCE)hModule, dwReason, 0);
00070 }
00071
00072 #endif
00073
00074 template<typename T> static T myabs(T n) {return n >= 0 ? n : -n;}
00075
00076 static int GetByteLength(UINT64 data, int min = 0)
00077 {
00078 int i = 7;
00079 while(i >= min && ((BYTE*)&data)[i] == 0) i--;
00080 return ++i;
00081 }
00082
00083
00084
00085
00086
00087 CDSMMuxerFilter::CDSMMuxerFilter(LPUNKNOWN pUnk, HRESULT* phr, bool fAutoChap, bool fAutoRes)
00088 : CBaseMuxerFilter(pUnk, phr, __uuidof(this))
00089 , m_fAutoChap(fAutoChap)
00090 , m_fAutoRes(fAutoRes)
00091 {
00092 if(phr) *phr = S_OK;
00093 }
00094
00095 CDSMMuxerFilter::~CDSMMuxerFilter()
00096 {
00097 }
00098
00099 void CDSMMuxerFilter::MuxPacketHeader(IBitStream* pBS, dsmp_t type, UINT64 len)
00100 {
00101 ASSERT(type < 32);
00102
00103 int i = GetByteLength(len, 1);
00104
00105 pBS->BitWrite(DSMSW, DSMSW_SIZE<<3);
00106 pBS->BitWrite(type, 5);
00107 pBS->BitWrite(i-1, 3);
00108 pBS->BitWrite(len, i<<3);
00109 }
00110
00111 void CDSMMuxerFilter::MuxFileInfo(IBitStream* pBS)
00112 {
00113 int len = 1;
00114 CSimpleMap<CStringA, CStringA> si;
00115
00116 for(int i = 0; i < GetSize(); i++)
00117 {
00118 CStringA key = CStringA(CString(GetKeyAt(i))), value = UTF16To8(GetValueAt(i));
00119 if(key.GetLength() != 4) continue;
00120 si.Add(key, value);
00121 len += 4 + value.GetLength() + 1;
00122 }
00123
00124 MuxPacketHeader(pBS, DSMP_FILEINFO, len);
00125 pBS->BitWrite(DSMF_VERSION, 8);
00126 for(int i = 0; i < si.GetSize(); i++)
00127 {
00128 CStringA key = si.GetKeyAt(i), value = si.GetValueAt(i);
00129 pBS->ByteWrite((LPCSTR)key, 4);
00130 pBS->ByteWrite((LPCSTR)value, value.GetLength()+1);
00131 }
00132
00133 }
00134
00135 void CDSMMuxerFilter::MuxStreamInfo(IBitStream* pBS, CBaseMuxerInputPin* pPin)
00136 {
00137 int len = 1;
00138 CSimpleMap<CStringA, CStringA> si;
00139
00140 for(int i = 0; i < pPin->GetSize(); i++)
00141 {
00142 CStringA key = CStringA(CString(pPin->GetKeyAt(i))), value = UTF16To8(pPin->GetValueAt(i));
00143 if(key.GetLength() != 4) continue;
00144 si.Add(key, value);
00145 len += 4 + value.GetLength() + 1;
00146 }
00147
00148 if(len > 1)
00149 {
00150 MuxPacketHeader(pBS, DSMP_STREAMINFO, len);
00151 pBS->BitWrite(pPin->GetID(), 8);
00152 for(int i = 0; i < si.GetSize(); i++)
00153 {
00154 CStringA key = si.GetKeyAt(i), value = si.GetValueAt(i);
00155 pBS->ByteWrite((LPCSTR)key, 4);
00156 pBS->ByteWrite((LPCSTR)value, value.GetLength()+1);
00157 }
00158 }
00159 }
00160
00161 void CDSMMuxerFilter::MuxInit()
00162 {
00163 m_sps.RemoveAll();
00164 m_isps.RemoveAll();
00165 m_rtPrevSyncPoint = _I64_MIN;
00166 }
00167
00168 void CDSMMuxerFilter::MuxHeader(IBitStream* pBS)
00169 {
00170 CString muxer;
00171 muxer.Format(_T("DSM Muxer (%s)"), CString(__TIMESTAMP__));
00172
00173 SetProperty(L"MUXR", CStringW(muxer));
00174 SetProperty(L"DATE", CStringW(CTime::GetCurrentTime().FormatGmt(_T("%Y-%m-%d %H:%M:%S"))));
00175
00176 MuxFileInfo(pBS);
00177
00178 POSITION pos = m_pPins.GetHeadPosition();
00179 while(pos)
00180 {
00181 CBaseMuxerInputPin* pPin = m_pPins.GetNext(pos);
00182 const CMediaType& mt = pPin->CurrentMediaType();
00183
00184 ASSERT((mt.lSampleSize >> 30) == 0);
00185
00186 MuxPacketHeader(pBS, DSMP_MEDIATYPE, 5 + sizeof(GUID)*3 + mt.FormatLength());
00187 pBS->BitWrite(pPin->GetID(), 8);
00188 pBS->ByteWrite(&mt.majortype, sizeof(mt.majortype));
00189 pBS->ByteWrite(&mt.subtype, sizeof(mt.subtype));
00190 pBS->BitWrite(mt.bFixedSizeSamples, 1);
00191 pBS->BitWrite(mt.bTemporalCompression, 1);
00192 pBS->BitWrite(mt.lSampleSize, 30);
00193 pBS->ByteWrite(&mt.formattype, sizeof(mt.formattype));
00194 pBS->ByteWrite(mt.Format(), mt.FormatLength());
00195
00196 MuxStreamInfo(pBS, pPin);
00197 }
00198
00199
00200
00201 CInterfaceList<IDSMResourceBag> pRBs;
00202 pRBs.AddTail(this);
00203
00204 CComQIPtr<IDSMChapterBag> pCB = (IUnknown*)(INonDelegatingUnknown*)this;
00205
00206 pos = m_pPins.GetHeadPosition();
00207 while(pos)
00208 {
00209 for(CComPtr<IPin> pPin = m_pPins.GetNext(pos)->GetConnected(); pPin; pPin = GetUpStreamPin(GetFilterFromPin(pPin)))
00210 {
00211 if(m_fAutoRes)
00212 {
00213 CComQIPtr<IDSMResourceBag> pPB = GetFilterFromPin(pPin);
00214 if(pPB && !pRBs.Find(pPB)) pRBs.AddTail(pPB);
00215 }
00216
00217 if(m_fAutoChap)
00218 {
00219 if(!pCB || pCB->ChapGetCount() == 0) pCB = GetFilterFromPin(pPin);
00220 }
00221 }
00222 }
00223
00224
00225
00226 pos = pRBs.GetHeadPosition();
00227 while(pos)
00228 {
00229 IDSMResourceBag* pRB = pRBs.GetNext(pos);
00230
00231 for(DWORD i = 0, j = pRB->ResGetCount(); i < j; i++)
00232 {
00233 CComBSTR name, desc, mime;
00234 BYTE* pData = NULL;
00235 DWORD len = 0;
00236 if(SUCCEEDED(pRB->ResGet(i, &name, &desc, &mime, &pData, &len, NULL)))
00237 {
00238 CStringA utf8_name = UTF16To8(name);
00239 CStringA utf8_desc = UTF16To8(desc);
00240 CStringA utf8_mime = UTF16To8(mime);
00241
00242 MuxPacketHeader(pBS, DSMP_RESOURCE,
00243 1 +
00244 utf8_name.GetLength()+1 +
00245 utf8_desc.GetLength()+1 +
00246 utf8_mime.GetLength()+1 +
00247 len);
00248
00249 pBS->BitWrite(0, 2);
00250 pBS->BitWrite(0, 6);
00251 pBS->ByteWrite(utf8_name, utf8_name.GetLength()+1);
00252 pBS->ByteWrite(utf8_desc, utf8_desc.GetLength()+1);
00253 pBS->ByteWrite(utf8_mime, utf8_mime.GetLength()+1);
00254 pBS->ByteWrite(pData, len);
00255
00256 CoTaskMemFree(pData);
00257 }
00258 }
00259 }
00260
00261
00262
00263 if(pCB)
00264 {
00265 CList<CDSMChapter> chapters;
00266 REFERENCE_TIME rtPrev = 0;
00267 int len = 0;
00268
00269 pCB->ChapSort();
00270
00271 for(DWORD i = 0; i < pCB->ChapGetCount(); i++)
00272 {
00273 CDSMChapter c;
00274 CComBSTR name;
00275 if(SUCCEEDED(pCB->ChapGet(i, &c.rt, &name)))
00276 {
00277 REFERENCE_TIME rtDiff = c.rt - rtPrev; rtPrev = c.rt; c.rt = rtDiff;
00278 c.name = name;
00279 len += 1 + GetByteLength(myabs(c.rt)) + UTF16To8(c.name).GetLength()+1;
00280 chapters.AddTail(c);
00281 }
00282 }
00283
00284 if(chapters.GetCount())
00285 {
00286 MuxPacketHeader(pBS, DSMP_CHAPTERS, len);
00287
00288 pos = chapters.GetHeadPosition();
00289 while(pos)
00290 {
00291 CDSMChapter& c = chapters.GetNext(pos);
00292 CStringA name = UTF16To8(c.name);
00293 int irt = GetByteLength(myabs(c.rt));
00294 pBS->BitWrite(c.rt < 0, 1);
00295 pBS->BitWrite(irt, 3);
00296 pBS->BitWrite(0, 4);
00297 pBS->BitWrite(myabs(c.rt), irt<<3);
00298 pBS->ByteWrite((LPCSTR)name, name.GetLength()+1);
00299 }
00300 }
00301 }
00302 }
00303
00304 void CDSMMuxerFilter::MuxPacket(IBitStream* pBS, const MuxerPacket* pPacket)
00305 {
00306 if(pPacket->IsEOS())
00307 return;
00308
00309 if(pPacket->pPin->CurrentMediaType().majortype == MEDIATYPE_Text)
00310 {
00311 CStringA str((char*)pPacket->pData.GetData(), pPacket->pData.GetCount());
00312 str.Replace("\xff", " ");
00313 str.Replace(" ", " ");
00314 str.Replace(" ", " ");
00315 str.Trim();
00316 if(str.IsEmpty())
00317 return;
00318 }
00319
00320 ASSERT(!pPacket->IsSyncPoint() || pPacket->IsTimeValid());
00321
00322 REFERENCE_TIME rtTimeStamp = _I64_MIN, rtDuration = 0;
00323 int iTimeStamp = 0, iDuration = 0;
00324
00325 if(pPacket->IsTimeValid())
00326 {
00327 rtTimeStamp = pPacket->rtStart;
00328 rtDuration = max(pPacket->rtStop - pPacket->rtStart, 0);
00329
00330 iTimeStamp = GetByteLength(myabs(rtTimeStamp));
00331 ASSERT(iTimeStamp <= 7);
00332
00333 iDuration = GetByteLength(rtDuration);
00334 ASSERT(iDuration <= 7);
00335
00336 IndexSyncPoint(pPacket, pBS->GetPos());
00337 }
00338
00339 int len = 2 + iTimeStamp + iDuration + pPacket->pData.GetCount();
00340
00341 MuxPacketHeader(pBS, DSMP_SAMPLE, len);
00342 pBS->BitWrite(pPacket->pPin->GetID(), 8);
00343 pBS->BitWrite(pPacket->IsSyncPoint(), 1);
00344 pBS->BitWrite(rtTimeStamp < 0, 1);
00345 pBS->BitWrite(iTimeStamp, 3);
00346 pBS->BitWrite(iDuration, 3);
00347 pBS->BitWrite(myabs(rtTimeStamp), iTimeStamp<<3);
00348 pBS->BitWrite(rtDuration, iDuration<<3);
00349 pBS->ByteWrite(pPacket->pData.GetData(), pPacket->pData.GetCount());
00350 }
00351
00352 void CDSMMuxerFilter::MuxFooter(IBitStream* pBS)
00353 {
00354
00355
00356 int len = 0;
00357 CList<IndexedSyncPoint> isps;
00358 REFERENCE_TIME rtPrev = 0, rt;
00359 UINT64 fpPrev = 0, fp;
00360
00361 POSITION pos = m_isps.GetHeadPosition();
00362 while(pos)
00363 {
00364 IndexedSyncPoint& isp = m_isps.GetNext(pos);
00365 TRACE(_T("sp[%d]: %I64d %I64x\n"), isp.id, isp.rt, isp.fp);
00366
00367 rt = isp.rt - rtPrev; rtPrev = isp.rt;
00368 fp = isp.fp - fpPrev; fpPrev = isp.fp;
00369
00370 IndexedSyncPoint isp2;
00371 isp2.fp = fp;
00372 isp2.rt = rt;
00373 isps.AddTail(isp2);
00374
00375 len += 1 + GetByteLength(myabs(rt)) + GetByteLength(fp);
00376 }
00377
00378 MuxPacketHeader(pBS, DSMP_SYNCPOINTS, len);
00379
00380 pos = isps.GetHeadPosition();
00381 while(pos)
00382 {
00383 IndexedSyncPoint& isp = isps.GetNext(pos);
00384
00385 int irt = GetByteLength(myabs(isp.rt));
00386 int ifp = GetByteLength(isp.fp);
00387
00388 pBS->BitWrite(isp.rt < 0, 1);
00389 pBS->BitWrite(irt, 3);
00390 pBS->BitWrite(ifp, 3);
00391 pBS->BitWrite(0, 1);
00392 pBS->BitWrite(myabs(isp.rt), irt<<3);
00393 pBS->BitWrite(isp.fp, ifp<<3);
00394 }
00395 }
00396
00397 void CDSMMuxerFilter::IndexSyncPoint(const MuxerPacket* p, __int64 fp)
00398 {
00399
00400
00401
00402
00403
00404
00405 if(fp < 0 || !p || !p->IsTimeValid() || !p->IsSyncPoint())
00406 return;
00407
00408 ASSERT(p->rtStart >= m_rtPrevSyncPoint);
00409 m_rtPrevSyncPoint = p->rtStart;
00410
00411 SyncPoint sp;
00412 sp.id = p->pPin->GetID();
00413 sp.rtStart = p->rtStart;
00414 sp.rtStop = p->pPin->IsSubtitleStream() ? p->rtStop : _I64_MAX;
00415 sp.fp = fp;
00416
00417 {
00418 SyncPoint& head = !m_sps.IsEmpty() ? m_sps.GetHead() : sp;
00419 SyncPoint& tail = !m_sps.IsEmpty() ? m_sps.GetTail() : sp;
00420 REFERENCE_TIME rtfp = !m_isps.IsEmpty() ? m_isps.GetTail().rtfp : _I64_MIN;
00421
00422 if(head.rtStart > rtfp + 1000000)
00423 {
00424 IndexedSyncPoint isp;
00425 isp.id = head.id;
00426 isp.rt = tail.rtStart;
00427 isp.rtfp = head.rtStart;
00428 isp.fp = head.fp;
00429 m_isps.AddTail(isp);
00430 }
00431 }
00432
00433 POSITION pos = m_sps.GetHeadPosition();
00434 while(pos)
00435 {
00436 POSITION cur = pos;
00437 SyncPoint& sp2 = m_sps.GetNext(pos);
00438 if(sp2.id == sp.id && sp2.rtStop <= sp.rtStop || sp2.rtStop <= sp.rtStart)
00439 m_sps.RemoveAt(cur);
00440 }
00441
00442 m_sps.AddTail(sp);
00443 }