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 {
00064
00065 mCMMLParser = new CMMLParser;
00066
00067
00068 }
00069
00070 CMMLDecodeFilter::~CMMLDecodeFilter(void)
00071 {
00072
00073
00074 delete mCMMLParser;
00075 }
00076
00077 CUnknown* WINAPI CMMLDecodeFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr)
00078 {
00079
00080 CMMLDecodeFilter *pNewObject = new CMMLDecodeFilter();
00081 if (pNewObject == NULL) {
00082 *pHr = E_OUTOFMEMORY;
00083 }
00084 return pNewObject;
00085 }
00086
00087 STDMETHODIMP CMMLDecodeFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv) {
00088 if (riid == IID_ICMMLAppControl) {
00089 *ppv = (ICMMLAppControl*)this;
00090 ((IUnknown*)*ppv)->AddRef();
00091 return NOERROR;
00092 }
00093
00094 return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
00095 }
00096
00097 HRESULT CMMLDecodeFilter::CheckInputType(const CMediaType* inInputMediaType) {
00098 if ( (inInputMediaType->majortype == MEDIATYPE_Text) &&
00099 (inInputMediaType->subtype == MEDIASUBTYPE_CMML) &&
00100 (inInputMediaType->formattype == FORMAT_CMML) ){
00101
00102
00103 return S_OK;
00104 } else {
00105 return VFW_E_TYPE_NOT_ACCEPTED;
00106 }
00107 }
00108 HRESULT CMMLDecodeFilter::CheckTransform(const CMediaType* inInputMediaType, const CMediaType* inOutputMediaType) {
00109 if ( (inInputMediaType->majortype == MEDIATYPE_Text) &&
00110 (inInputMediaType->subtype == MEDIASUBTYPE_CMML) &&
00111 (inInputMediaType->formattype == FORMAT_CMML) &&
00112 (inOutputMediaType->majortype == MEDIATYPE_Text) &&
00113 (inOutputMediaType->subtype == MEDIASUBTYPE_SubtitleVMR9) ){
00114
00115
00116 return S_OK;
00117 } else {
00118 return VFW_E_TYPE_NOT_ACCEPTED;
00119 }
00120
00121 }
00122 HRESULT CMMLDecodeFilter::DecideBufferSize(IMemAllocator* inAllocator, ALLOCATOR_PROPERTIES* inPropertyRequest) {
00123
00124
00125 HRESULT locHR = S_OK;
00126
00127 ALLOCATOR_PROPERTIES locReqAlloc;
00128 ALLOCATOR_PROPERTIES locActualAlloc;
00129
00130 const unsigned long MIN_BUFFER_SIZE = 1024;
00131 const unsigned long DEFAULT_BUFFER_SIZE = 4096;
00132 const unsigned long MIN_NUM_BUFFERS = 10;
00133 const unsigned long DEFAULT_NUM_BUFFERS = 15;
00134
00135
00136
00137
00138 if (inPropertyRequest->cbAlign <= 0) {
00139 locReqAlloc.cbAlign = 1;
00140 } else {
00141 locReqAlloc.cbAlign = inPropertyRequest->cbAlign;
00142 }
00143
00144
00145 if (inPropertyRequest->cbBuffer < MIN_BUFFER_SIZE) {
00146 locReqAlloc.cbBuffer = DEFAULT_BUFFER_SIZE;
00147 } else {
00148 locReqAlloc.cbBuffer = inPropertyRequest->cbBuffer;
00149 }
00150
00151
00152 if (inPropertyRequest->cbPrefix < 0) {
00153 locReqAlloc.cbPrefix = 0;
00154 } else {
00155 locReqAlloc.cbPrefix = inPropertyRequest->cbPrefix;
00156 }
00157
00158
00159 if (inPropertyRequest->cBuffers < MIN_NUM_BUFFERS) {
00160 locReqAlloc.cBuffers = DEFAULT_NUM_BUFFERS;
00161 } else {
00162 locReqAlloc.cBuffers = inPropertyRequest->cBuffers;
00163 }
00164
00165
00166 locHR = inAllocator->SetProperties(&locReqAlloc, &locActualAlloc);
00167
00168 if (locHR != S_OK) {
00169 return locHR;
00170 }
00171
00172 locHR = inAllocator->Commit();
00173
00174 return locHR;
00175 }
00176 HRESULT CMMLDecodeFilter::GetMediaType(int inPosition, CMediaType* outMediaType) {
00177 if (inPosition < 0) {
00178 return E_INVALIDARG;
00179 } else if (inPosition == 0) {
00180 outMediaType->majortype = MEDIATYPE_Text;
00181 outMediaType->subtype = MEDIASUBTYPE_SubtitleVMR9;
00182 return S_OK;
00183 } else {
00184 return VFW_S_NO_MORE_ITEMS;
00185 }
00186 }
00187 HRESULT CMMLDecodeFilter::Transform(IMediaSample* inSample, IMediaSample* outSample) {
00188
00189
00190
00191
00192
00193
00194 unsigned long locSize = inSample->GetActualDataLength();
00195 char* locCMML = NULL;
00196 BYTE* locInBuff = NULL;
00197 BYTE* locOutBuff = NULL;
00198 HRESULT locHR = S_FALSE;
00199 wstring locWCMML;
00200 char* locText = NULL;
00201 string locTextStr;
00202 unsigned long locTextSize = 0;
00203
00204
00205 LONGLONG locStart, locEnd;
00206 inSample->GetTime(&locStart, &locEnd);
00207
00208 LONGLONG locSampleTime = locStart;
00209 inSample->GetMediaTime(&locStart, &locEnd);
00210
00211 locSampleTime -= locStart;
00212
00213
00214 if (locSize > 0) {
00215 locCMML = new char[locSize+1];
00216 locCMML[locSize] = '\0';
00217
00218 locHR = inSample->GetPointer(&locInBuff);
00219 memcpy((void*)locCMML, (const void*) locInBuff, locSize);
00220
00221 locWCMML = toWStr(locCMML);
00222 if (mSeenHead == false) {
00223
00224
00225 mSeenHead = true;
00226 mHeadTag = new C_HeadTag;
00227 bool locParseOK = mCMMLParser->parseHeadTag(locWCMML, mHeadTag);
00228 if (locParseOK) {
00229
00230
00231
00232
00233
00234
00235
00236
00238
00239
00240
00241
00242 outSample->SetActualDataLength(0);
00243
00244
00245
00246 if (mCMMLCallbacks != NULL) {
00247 mCMMLCallbacks->headCallback(mHeadTag->clone());
00248 }
00249 } else {
00250
00251 }
00252
00253 } else {
00254
00255
00256 C_ClipTag locClipTag;
00257 bool locParseOK = mCMMLParser->parseClipTag(locWCMML, &locClipTag);
00258 if (locParseOK) {
00259
00260
00261
00262
00263
00264
00265
00266
00267
00269
00270
00273
00274
00275
00276
00277
00278
00279 outSample->SetActualDataLength(0);
00280
00281 if (mCMMLCallbacks != NULL) {
00282 mCMMLCallbacks->clipCallback(locClipTag.clone());
00283 }
00284
00285 } else {
00286
00287 delete[] locCMML;
00288 return S_FALSE;
00289 }
00290 }
00291
00292
00293 delete[] locCMML;
00294 return S_OK;
00295
00296 } else {
00297
00298
00299 outSample->SetActualDataLength(0);
00300
00301
00302 outSample->SetTime(&locSampleTime, &locSampleTime);
00303 outSample->SetMediaTime(NULL, NULL);
00304 outSample->SetSyncPoint(TRUE);
00305 outSample->SetDiscontinuity(FALSE);
00306 outSample->SetPreroll(FALSE);
00307 return S_OK;
00308 }
00309 }
00310
00311 wstring CMMLDecodeFilter::toWStr(string inString) {
00312 wstring retVal;
00313
00314
00315 for (std::string::const_iterator i = inString.begin(); i != inString.end(); i++) {
00316 retVal.append(1, *i);
00317 }
00318
00319
00320 return retVal;
00321 }
00322
00323
00324 STDMETHODIMP_(bool) CMMLDecodeFilter::setCallbacks(ICMMLCallbacks* inCallbacks) {
00325 mCMMLCallbacks = inCallbacks;
00326 return true;
00327 }
00328 STDMETHODIMP_(ICMMLCallbacks*) CMMLDecodeFilter::getCallbacks() {
00329 return mCMMLCallbacks;
00330 }
00331