00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "stdafx.h"
00036
00037 #include "cmmldecodefilter.h"
00038
00039
00040 CFactoryTemplate g_Templates[] =
00041 {
00042 {
00043 L"CMML Decode Filter",
00044 &CLSID_CMMLDecodeFilter,
00045 CMMLDecodeFilter::CreateInstance,
00046 NULL,
00047 NULL
00048 }
00049
00050 };
00051
00052
00053 int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
00054
00055
00056 CMMLDecodeFilter::CMMLDecodeFilter(void)
00057 : CTransformFilter(NAME("CMML Decoder"), NULL, CLSID_CMMLDecodeFilter)
00058
00059 , mCMMLParser(NULL)
00060 , mSeenHead(false)
00061 , mHeadTag(NULL)
00062 , mCMMLCallbacks(NULL)
00063 , mInputPin(NULL)
00064 {
00065
00066 mCMMLParser = new CMMLParser;
00067
00068
00069 }
00070
00071 CMMLDecodeFilter::~CMMLDecodeFilter(void)
00072 {
00073
00074
00075 delete mCMMLParser;
00076 }
00077
00078 CUnknown* WINAPI CMMLDecodeFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr)
00079 {
00080
00081 CMMLDecodeFilter *pNewObject = new CMMLDecodeFilter();
00082 if (pNewObject == NULL) {
00083 *pHr = E_OUTOFMEMORY;
00084 }
00085 return pNewObject;
00086 }
00087
00088 STDMETHODIMP CMMLDecodeFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv) {
00089 if (riid == IID_ICMMLAppControl) {
00090 *ppv = (ICMMLAppControl*)this;
00091 ((IUnknown*)*ppv)->AddRef();
00092 return NOERROR;
00093 }
00094
00095 return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
00096 }
00097
00098 HRESULT CMMLDecodeFilter::CheckInputType(const CMediaType* inInputMediaType)
00099 {
00100 return mInputPin->CheckMediaType(inInputMediaType);
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 }
00111 HRESULT CMMLDecodeFilter::CheckTransform(const CMediaType* inInputMediaType, const CMediaType* inOutputMediaType) {
00112
00113
00114
00115
00116
00117
00118
00119 return S_OK;
00120
00121
00122
00123
00124 }
00125
00126 CBasePin* CMMLDecodeFilter::GetPin(int inPinNo)
00127 {
00128
00129 HRESULT locHR = S_OK;
00130
00131
00132
00133 if (m_pInput == NULL) {
00134
00135 m_pInput = new CMMLDecodeInputPin(this, &locHR);
00136
00137
00138 if (m_pInput == NULL) {
00139 return NULL;
00140 }
00141
00142 mInputPin = (CMMLDecodeInputPin*)m_pInput;
00143 m_pOutput = new CTransformOutputPin(NAME("CMML Out"), this, &locHR, L"CMML Out");
00144
00145
00146 if (m_pOutput == NULL) {
00147 delete m_pInput;
00148 m_pInput = NULL;
00149 }
00150 }
00151
00152
00153
00154 if (inPinNo == 0) {
00155 return m_pInput;
00156 } else if (inPinNo == 1) {
00157 return m_pOutput;
00158 } else {
00159 return NULL;
00160 }
00161
00162 }
00163 HRESULT CMMLDecodeFilter::DecideBufferSize(IMemAllocator* inAllocator, ALLOCATOR_PROPERTIES* inPropertyRequest) {
00164
00165
00166 HRESULT locHR = S_OK;
00167
00168 ALLOCATOR_PROPERTIES locReqAlloc;
00169 ALLOCATOR_PROPERTIES locActualAlloc;
00170
00171 const unsigned long MIN_BUFFER_SIZE = 1024;
00172 const unsigned long DEFAULT_BUFFER_SIZE = 4096;
00173 const unsigned long MIN_NUM_BUFFERS = 10;
00174 const unsigned long DEFAULT_NUM_BUFFERS = 15;
00175
00176
00177
00178
00179 if (inPropertyRequest->cbAlign <= 0) {
00180 locReqAlloc.cbAlign = 1;
00181 } else {
00182 locReqAlloc.cbAlign = inPropertyRequest->cbAlign;
00183 }
00184
00185
00186 if (inPropertyRequest->cbBuffer < MIN_BUFFER_SIZE) {
00187 locReqAlloc.cbBuffer = DEFAULT_BUFFER_SIZE;
00188 } else {
00189 locReqAlloc.cbBuffer = inPropertyRequest->cbBuffer;
00190 }
00191
00192
00193 if (inPropertyRequest->cbPrefix < 0) {
00194 locReqAlloc.cbPrefix = 0;
00195 } else {
00196 locReqAlloc.cbPrefix = inPropertyRequest->cbPrefix;
00197 }
00198
00199
00200 if (inPropertyRequest->cBuffers < MIN_NUM_BUFFERS) {
00201 locReqAlloc.cBuffers = DEFAULT_NUM_BUFFERS;
00202 } else {
00203 locReqAlloc.cBuffers = inPropertyRequest->cBuffers;
00204 }
00205
00206
00207 locHR = inAllocator->SetProperties(&locReqAlloc, &locActualAlloc);
00208
00209 if (locHR != S_OK) {
00210 return locHR;
00211 }
00212
00213 locHR = inAllocator->Commit();
00214
00215 return locHR;
00216 }
00217 HRESULT CMMLDecodeFilter::GetMediaType(int inPosition, CMediaType* outMediaType) {
00218 if (inPosition < 0) {
00219 return E_INVALIDARG;
00220 } else if (inPosition == 0) {
00221 outMediaType->majortype = MEDIATYPE_Text;
00222 outMediaType->subtype = MEDIASUBTYPE_SubtitleVMR9;
00223 return S_OK;
00224 } else {
00225 return VFW_S_NO_MORE_ITEMS;
00226 }
00227 }
00228 HRESULT CMMLDecodeFilter::Transform(IMediaSample* inSample, IMediaSample* outSample) {
00229
00230
00231
00232
00233
00234
00235 unsigned long locSize = inSample->GetActualDataLength();
00236 char* locCMML = NULL;
00237 BYTE* locInBuff = NULL;
00238 BYTE* locOutBuff = NULL;
00239 HRESULT locHR = S_FALSE;
00240 wstring locWCMML;
00241 char* locText = NULL;
00242 string locTextStr;
00243 unsigned long locTextSize = 0;
00244
00245
00246 LONGLONG locStart, locEnd;
00247 inSample->GetTime(&locStart, &locEnd);
00248
00249 LONGLONG locSampleTime = locStart;
00250 inSample->GetMediaTime(&locStart, &locEnd);
00251
00252 locSampleTime -= locStart;
00253
00254
00255 if (locSize > 0) {
00256 locCMML = new char[locSize+1];
00257 locCMML[locSize] = '\0';
00258
00259 locHR = inSample->GetPointer(&locInBuff);
00260 memcpy((void*)locCMML, (const void*) locInBuff, locSize);
00261
00262
00263 string locNarrowCMML = locCMML;
00264 delete[] locCMML;
00265 locWCMML = toWStr(locNarrowCMML);
00266 if (mSeenHead == false) {
00267
00268
00269 mSeenHead = true;
00270 mHeadTag = new C_HeadTag;
00271 bool locParseOK = mCMMLParser->parseHeadTag(locWCMML, mHeadTag);
00272 if (locParseOK) {
00273
00274
00275
00276
00277
00278
00279
00280
00282
00283
00284
00285
00286 outSample->SetActualDataLength(0);
00287
00288
00289
00290 if (mCMMLCallbacks != NULL) {
00291 mCMMLCallbacks->headCallback(mHeadTag->clone());
00292 }
00293 } else {
00294
00295 }
00296
00297 } else {
00298
00299
00300 C_ClipTag locClipTag;
00301 bool locParseOK = mCMMLParser->parseClipTag(locWCMML, &locClipTag);
00302 if (locParseOK) {
00303
00304
00305
00306
00307
00308
00309
00310
00311
00313
00314
00317
00318
00319
00320
00321
00322
00323 outSample->SetActualDataLength(0);
00324
00325 if (mCMMLCallbacks != NULL) {
00326 mCMMLCallbacks->clipCallback(locClipTag.clone());
00327 }
00328
00329 } else {
00330
00331
00332 return S_FALSE;
00333 }
00334 }
00335
00336
00337
00338 return S_OK;
00339
00340 } else {
00341
00342
00343 outSample->SetActualDataLength(0);
00344
00345
00346 outSample->SetTime(&locSampleTime, &locSampleTime);
00347 outSample->SetMediaTime(NULL, NULL);
00348 outSample->SetSyncPoint(TRUE);
00349 outSample->SetDiscontinuity(FALSE);
00350 outSample->SetPreroll(FALSE);
00351 return S_OK;
00352 }
00353 }
00354
00355 wstring CMMLDecodeFilter::toWStr(string inString) {
00356 wstring retVal;
00357
00358
00359 for (std::string::const_iterator i = inString.begin(); i != inString.end(); i++) {
00360 retVal.append(1, *i);
00361 }
00362
00363
00364 return retVal;
00365 }
00366
00367
00368 STDMETHODIMP_(bool) CMMLDecodeFilter::setCallbacks(ICMMLCallbacks* inCallbacks) {
00369 mCMMLCallbacks = inCallbacks;
00370 return true;
00371 }
00372 STDMETHODIMP_(ICMMLCallbacks*) CMMLDecodeFilter::getCallbacks() {
00373 return mCMMLCallbacks;
00374 }
00375