[svn] / branches / dshow / dshow / src / CXvidDecoder.cpp Repository:
ViewVC logotype

Annotation of /branches/dshow/dshow/src/CXvidDecoder.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (view) (download)

1 : Isibaar 6 /*
2 :     this requires the directx sdk
3 :     place these paths at the top of the Tools|Options|Directories list
4 :    
5 :     headers:
6 :     C:\DXVCSDK\include
7 :     C:\DXVCSDK\samples\Multimedia\DirectShow\BaseClasses
8 :    
9 :     libraries (optional):
10 :     C:\DXVCSDK\samples\Multimedia\DirectShow\BaseClasses\Release
11 :     */
12 :    
13 :     #include <windows.h>
14 :    
15 :     #include <streams.h>
16 :     #include <initguid.h>
17 :     #include <olectl.h>
18 :     #if (1100 > _MSC_VER)
19 :     #include <olectlid.h>
20 :     #endif
21 :     #include <dvdmedia.h> // VIDEOINFOHEADER2
22 :    
23 :     #include "xvid.h"
24 :     #include "IXvidDecoder.h"
25 :     #include "CXvidDecoder.h"
26 :     #include "CAbout.h"
27 :    
28 :    
29 :    
30 :     const AMOVIESETUP_MEDIATYPE sudInputPinTypes[] =
31 :     {
32 :     { &MEDIATYPE_Video, &CLSID_XVID },
33 :     { &MEDIATYPE_Video, &CLSID_XVID_UC },
34 :     { &MEDIATYPE_Video, &CLSID_DIVX },
35 :     { &MEDIATYPE_Video, &CLSID_DIVX_UC }
36 :     };
37 :    
38 :     const AMOVIESETUP_MEDIATYPE sudOutputPinTypes[] =
39 :     {
40 :     { &MEDIATYPE_Video, &MEDIASUBTYPE_NULL }
41 :     };
42 :    
43 :    
44 :     const AMOVIESETUP_PIN psudPins[] =
45 :     {
46 :     {
47 :     L"Input", // String pin name
48 :     FALSE, // Is it rendered
49 :     FALSE, // Is it an output
50 :     FALSE, // Allowed none
51 :     FALSE, // Allowed many
52 :     &CLSID_NULL, // Connects to filter
53 :     L"Output", // Connects to pin
54 :     sizeof(sudInputPinTypes) / sizeof(AMOVIESETUP_MEDIATYPE), // Number of types
55 :     &sudInputPinTypes[0] // The pin details
56 :     },
57 :     {
58 :     L"Output", // String pin name
59 :     FALSE, // Is it rendered
60 :     TRUE, // Is it an output
61 :     FALSE, // Allowed none
62 :     FALSE, // Allowed many
63 :     &CLSID_NULL, // Connects to filter
64 :     L"Input", // Connects to pin
65 :     sizeof(sudOutputPinTypes) / sizeof(AMOVIESETUP_MEDIATYPE), // Number of types
66 :     sudOutputPinTypes // The pin details
67 :     }
68 :     };
69 :    
70 :    
71 :     const AMOVIESETUP_FILTER sudXvidDecoder =
72 :     {
73 :     &CLSID_XVID, // Filter CLSID
74 :     XVID_NAME_L, // Filter name
75 :     MERIT_PREFERRED, // Its merit
76 :     sizeof(psudPins) / sizeof(AMOVIESETUP_PIN), // Number of pins
77 :     psudPins // Pin details
78 :     };
79 :    
80 :    
81 :     // List of class IDs and creator functions for the class factory. This
82 :     // provides the link between the OLE entry point in the DLL and an object
83 :     // being created. The class factory will call the static CreateInstance
84 :    
85 :     CFactoryTemplate g_Templates[] =
86 :     {
87 :     {
88 :     XVID_NAME_L,
89 :     &CLSID_XVID,
90 :     CXvidDecoder::CreateInstance,
91 :     NULL,
92 :     &sudXvidDecoder
93 :     },
94 :     {
95 :     XVID_NAME_L L"About",
96 :     &CLSID_CABOUT,
97 :     CAbout::CreateInstance
98 :     }
99 :    
100 :     };
101 :    
102 :     int g_cTemplates = sizeof(g_Templates) / sizeof(CFactoryTemplate);
103 :    
104 :    
105 :    
106 :    
107 :     STDAPI DllRegisterServer()
108 :     {
109 :     return AMovieDllRegisterServer2( TRUE );
110 :     }
111 :    
112 :    
113 :     STDAPI DllUnregisterServer()
114 :     {
115 :     return AMovieDllRegisterServer2( FALSE );
116 :     }
117 :    
118 :    
119 :     /* create instance */
120 :    
121 :     CUnknown * WINAPI CXvidDecoder::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
122 :     {
123 :     CXvidDecoder * pNewObject = new CXvidDecoder(punk, phr);
124 :     if (pNewObject == NULL)
125 :     {
126 :     *phr = E_OUTOFMEMORY;
127 :     }
128 :     return pNewObject;
129 :     }
130 :    
131 :    
132 :     /* query interfaces */
133 :    
134 :     STDMETHODIMP CXvidDecoder::NonDelegatingQueryInterface(REFIID riid, void **ppv)
135 :     {
136 :     CheckPointer(ppv, E_POINTER);
137 :    
138 :     if (riid == IID_IXvidDecoder)
139 :     {
140 :     return GetInterface((IXvidDecoder *) this, ppv);
141 :     }
142 :    
143 :     if (riid == IID_ISpecifyPropertyPages)
144 :     {
145 :     return GetInterface((ISpecifyPropertyPages *) this, ppv);
146 :     }
147 :    
148 :     return CVideoTransformFilter::NonDelegatingQueryInterface(riid, ppv);
149 :     }
150 :    
151 :    
152 :    
153 :     /* dummy decore() */
154 :    
155 :     static int dummy_xvid_decore(void * handle, int opt, void * param1, void * param2)
156 :     {
157 :     return XVID_ERR_FAIL;
158 :     }
159 :    
160 :    
161 :    
162 :     /* constructor */
163 :    
164 :     #define XVID_DLL_NAME "xvid.dll"
165 :     #define XVID_INIT_NAME "xvid_init"
166 :     #define XVID_DECORE_NAME "xvid_decore"
167 :    
168 :     CXvidDecoder::CXvidDecoder(LPUNKNOWN punk, HRESULT *phr) :
169 :     CVideoTransformFilter(NAME("CXvidDecoder"), punk, CLSID_XVID)
170 :     {
171 :     DEBUG("Constructor");
172 :    
173 :     ASSERT(phr);
174 :    
175 :     m_xvid_decore = dummy_xvid_decore;
176 :    
177 :     m_hdll = LoadLibrary(XVID_DLL_NAME);
178 :     if (m_hdll == NULL) {
179 :     DEBUG("dll load failed");
180 :     MessageBox(0, XVID_DLL_NAME " not found","Error", 0);
181 :     return;
182 :     }
183 :    
184 :     m_xvid_init = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, XVID_INIT_NAME);
185 :     if (m_xvid_init == NULL) {
186 :     MessageBox(0, XVID_INIT_NAME "() not found", "Error", 0);
187 :     return;
188 :     }
189 :    
190 :     m_xvid_decore = (int (__cdecl *)(void *, int, void *, void *))GetProcAddress(m_hdll, XVID_DECORE_NAME);
191 :     if (m_xvid_decore == NULL) {
192 :     MessageBox(0, XVID_DECORE_NAME "() not found", "Error", 0);
193 :     return;
194 :     }
195 :    
196 :     XVID_INIT_PARAM init;
197 :    
198 :     init.cpu_flags = 0;
199 :     if (m_xvid_init(0, 0, &init, 0) != XVID_ERR_OK)
200 :     {
201 :     MessageBox(0, XVID_INIT_NAME "() failed", "Error", 0);
202 :     return;
203 :     }
204 :    
205 :     if (init.api_version < API_VERSION)
206 :     {
207 :     MessageBox(0, XVID_DLL_NAME " implements an older api version; update your " XVID_DLL_NAME, "Warning", 0);
208 :     }
209 :     else if (init.api_version > API_VERSION)
210 :     {
211 :     MessageBox(0, XVID_DLL_NAME " implements a newer api version; update your directshow filter", "Error", 0);
212 :     return;
213 :     }
214 :    
215 :     m_param.handle = NULL;
216 :     }
217 :    
218 :    
219 :    
220 :     /* destructor */
221 :    
222 :     CXvidDecoder::~CXvidDecoder()
223 :     {
224 :     DEBUG("Destructor");
225 :    
226 :     if (m_param.handle != NULL)
227 :     {
228 :     m_xvid_decore(m_param.handle, XVID_DEC_DESTROY, 0, 0);
229 :     m_param.handle = NULL;
230 :     }
231 :    
232 :     if (m_hdll != NULL)
233 :     {
234 :     FreeLibrary(m_hdll);
235 :     m_hdll = NULL;
236 :     }
237 :     }
238 :    
239 :    
240 :    
241 :     /* check input type */
242 :    
243 :     HRESULT CXvidDecoder::CheckInputType(const CMediaType * mtIn)
244 :     {
245 :     DEBUG("CheckInputType");
246 :     BITMAPINFOHEADER * hdr;
247 :    
248 :     if (*mtIn->Type() != MEDIATYPE_Video)
249 :     {
250 :     return VFW_E_TYPE_NOT_ACCEPTED;
251 :     }
252 :    
253 :     if (*mtIn->FormatType() == FORMAT_VideoInfo)
254 :     {
255 :     VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtIn->Format();
256 :     hdr = &vih->bmiHeader;
257 :     }
258 :     else if (*mtIn->FormatType() == FORMAT_VideoInfo2)
259 :     {
260 :     VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 *) mtIn->Format();
261 :     hdr = &vih2->bmiHeader;
262 :     }
263 :     else
264 :     {
265 :     return VFW_E_TYPE_NOT_ACCEPTED;
266 :     }
267 :    
268 :     if (hdr->biHeight < 0)
269 :     {
270 :     DEBUG("colorspace: inverted input format not supported");
271 :     }
272 :    
273 :     m_param.width = hdr->biWidth;
274 :     m_param.height = hdr->biHeight;
275 :    
276 :     switch(hdr->biCompression)
277 :     {
278 :     case FOURCC_XVID :
279 :     // case FOURCC_DIVX :
280 :     break;
281 :    
282 :     default :
283 :     return VFW_E_TYPE_NOT_ACCEPTED;
284 :     }
285 :    
286 :     return S_OK;
287 :     }
288 :    
289 :    
290 :     /* get list of supported output colorspaces */
291 :    
292 :     HRESULT CXvidDecoder::GetMediaType(int iPosition, CMediaType *mtOut)
293 :     {
294 :     DEBUG("GetMediaType");
295 :    
296 :     if (m_pInput->IsConnected() == FALSE)
297 :     {
298 :     return E_UNEXPECTED;
299 :     }
300 :    
301 :     VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) mtOut->ReallocFormatBuffer(sizeof(VIDEOINFOHEADER));
302 :     if (vih == NULL)
303 :     {
304 :     return E_OUTOFMEMORY;
305 :     }
306 :    
307 :     ZeroMemory(vih, sizeof (VIDEOINFOHEADER));
308 :     vih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
309 :     vih->bmiHeader.biWidth = m_param.width;
310 :     vih->bmiHeader.biHeight = m_param.height;
311 :     vih->bmiHeader.biPlanes = 1;
312 :    
313 :     if (iPosition < 0)
314 :     {
315 :     return E_INVALIDARG;
316 :     }
317 :    
318 :     switch(iPosition)
319 :     {
320 :     case 0 :
321 :     vih->bmiHeader.biCompression = MEDIASUBTYPE_YV12.Data1;
322 :     vih->bmiHeader.biBitCount = 12;
323 :     mtOut->SetSubtype(&MEDIASUBTYPE_YV12);
324 :     break;
325 :    
326 :     case 1:
327 :     vih->bmiHeader.biCompression = MEDIASUBTYPE_YUY2.Data1;
328 :     vih->bmiHeader.biBitCount = 16;
329 :     mtOut->SetSubtype(&MEDIASUBTYPE_YUY2);
330 :     break;
331 :    
332 :     case 2:
333 :     vih->bmiHeader.biCompression = MEDIASUBTYPE_YVYU.Data1;
334 :     vih->bmiHeader.biBitCount = 16;
335 :     mtOut->SetSubtype(&MEDIASUBTYPE_YVYU);
336 :     break;
337 :    
338 :     case 3:
339 :     vih->bmiHeader.biCompression = MEDIASUBTYPE_UYVY.Data1;
340 :     vih->bmiHeader.biBitCount = 16;
341 :     mtOut->SetSubtype(&MEDIASUBTYPE_UYVY);
342 :     break;
343 :    
344 :     case 4:
345 :     vih->bmiHeader.biCompression = BI_RGB;
346 :     vih->bmiHeader.biBitCount = 32;
347 :     mtOut->SetSubtype(&MEDIASUBTYPE_RGB32);
348 :     break;
349 :    
350 :     case 5:
351 :     vih->bmiHeader.biCompression = BI_RGB;
352 :     vih->bmiHeader.biBitCount = 24;
353 :     mtOut->SetSubtype(&MEDIASUBTYPE_RGB24);
354 :     break;
355 :    
356 :     case 6:
357 :     vih->bmiHeader.biCompression = BI_RGB;
358 :     vih->bmiHeader.biBitCount = 16;
359 :     mtOut->SetSubtype(&MEDIASUBTYPE_RGB555);
360 :     break;
361 :    
362 :     case 7:
363 :     vih->bmiHeader.biCompression = BI_RGB;
364 :     vih->bmiHeader.biBitCount = 16;
365 :     mtOut->SetSubtype(&MEDIASUBTYPE_RGB565);
366 :     break;
367 :    
368 :     default :
369 :     return VFW_S_NO_MORE_ITEMS;
370 :     }
371 :    
372 :     vih->bmiHeader.biSizeImage = GetBitmapSize(&vih->bmiHeader);
373 :    
374 :     mtOut->SetType(&MEDIATYPE_Video);
375 :     mtOut->SetFormatType(&FORMAT_VideoInfo);
376 :     mtOut->SetTemporalCompression(FALSE);
377 :     mtOut->SetSampleSize(vih->bmiHeader.biSizeImage);
378 :    
379 :     return S_OK;
380 :     }
381 :    
382 :    
383 :     /* (internal function) change colorspace */
384 :    
385 :     HRESULT CXvidDecoder::ChangeColorspace(GUID subtype, GUID formattype, void * format)
386 :     {
387 :     if (subtype == MEDIASUBTYPE_YV12)
388 :     {
389 :     DEBUG("YV12");
390 :     m_frame.colorspace = XVID_CSP_YV12;
391 :     }
392 :     else if (subtype == MEDIASUBTYPE_YUY2)
393 :     {
394 :     DEBUG("YUY2");
395 :     m_frame.colorspace = XVID_CSP_YUY2;
396 :     }
397 :     else if (subtype == MEDIASUBTYPE_YVYU)
398 :     {
399 :     DEBUG("YVYU");
400 :     m_frame.colorspace = XVID_CSP_YVYU;
401 :     }
402 :     else if (subtype == MEDIASUBTYPE_UYVY)
403 :     {
404 :     DEBUG("UYVY");
405 :     m_frame.colorspace = XVID_CSP_UYVY;
406 :     }
407 :     else if (subtype == MEDIASUBTYPE_RGB32)
408 :     {
409 :     DEBUG("RGB32");
410 :     m_frame.colorspace = XVID_CSP_VFLIP | XVID_CSP_RGB32;
411 :     }
412 :     else if (subtype == MEDIASUBTYPE_RGB24)
413 :     {
414 :     DEBUG("RGB24");
415 :     m_frame.colorspace = XVID_CSP_VFLIP | XVID_CSP_RGB24;
416 :     }
417 :     else if (subtype == MEDIASUBTYPE_RGB555)
418 :     {
419 :     DEBUG("RGB555");
420 :     m_frame.colorspace = XVID_CSP_VFLIP | XVID_CSP_RGB555;
421 :     }
422 :     else if (subtype == MEDIASUBTYPE_RGB565)
423 :     {
424 :     DEBUG("RGB565");
425 :     m_frame.colorspace = XVID_CSP_VFLIP | XVID_CSP_RGB565;
426 :     }
427 :     else if (subtype == GUID_NULL)
428 :     {
429 :     m_frame.colorspace = XVID_CSP_NULL;
430 :     }
431 :     else
432 :     {
433 :     return S_FALSE;
434 :     }
435 :    
436 :    
437 :     if (formattype == FORMAT_VideoInfo)
438 :     {
439 :     VIDEOINFOHEADER * vih = (VIDEOINFOHEADER * )format;
440 :     m_frame.stride = vih->bmiHeader.biWidth;
441 :     }
442 :     else if (formattype == FORMAT_VideoInfo2)
443 :     {
444 :     VIDEOINFOHEADER2 * vih2 = (VIDEOINFOHEADER2 * )format;
445 :     m_frame.stride = vih2->bmiHeader.biWidth;
446 :     }
447 :     else
448 :     {
449 :     return S_FALSE;
450 :     }
451 :    
452 :     return S_OK;
453 :    
454 :     }
455 :    
456 :    
457 :     /* set output colorspace */
458 :    
459 :     HRESULT CXvidDecoder::SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt)
460 :     {
461 :     DEBUG("SetMediaType");
462 :    
463 :     if (direction == PINDIR_OUTPUT)
464 :     {
465 :     return ChangeColorspace(*pmt->Subtype(), *pmt->FormatType(), pmt->Format());
466 :     }
467 :    
468 :     return S_OK;
469 :     }
470 :    
471 :    
472 :     /* check input<->output compatiblity */
473 :    
474 :     HRESULT CXvidDecoder::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
475 :     {
476 :     DEBUG("CheckTransform");
477 :     return S_OK;
478 :     }
479 :    
480 :    
481 :     /* alloc output buffer */
482 :    
483 :     HRESULT CXvidDecoder::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *ppropInputRequest)
484 :     {
485 :     DEBUG("DecideBufferSize");
486 :     HRESULT result;
487 :     ALLOCATOR_PROPERTIES ppropActual;
488 :    
489 :     if (m_pInput->IsConnected() == FALSE)
490 :     {
491 :     return E_UNEXPECTED;
492 :     }
493 :    
494 :     ppropInputRequest->cBuffers = 1;
495 :     ppropInputRequest->cbBuffer = m_param.width * m_param.height * 4;
496 :     // cbAlign causes problems with the resize filter */
497 :     // ppropInputRequest->cbAlign = 16;
498 :     ppropInputRequest->cbPrefix = 0;
499 :    
500 :     result = pAlloc->SetProperties(ppropInputRequest, &ppropActual);
501 :     if (result != S_OK)
502 :     {
503 :     return result;
504 :     }
505 :    
506 :     if (ppropActual.cbBuffer < ppropInputRequest->cbBuffer)
507 :     {
508 :     return E_FAIL;
509 :     }
510 :    
511 :     return S_OK;
512 :     }
513 :    
514 :    
515 :    
516 :     /* decode frame */
517 :    
518 :     HRESULT CXvidDecoder::Transform(IMediaSample *pIn, IMediaSample *pOut)
519 :     {
520 :     DEBUG("Transform");
521 :    
522 :     if (m_param.handle == NULL)
523 :     {
524 :     if (m_xvid_decore(0, XVID_DEC_CREATE, &m_param, 0) != XVID_ERR_OK)
525 :     {
526 :     return S_FALSE;
527 :     }
528 :     }
529 :    
530 :     AM_MEDIA_TYPE * mtOut;
531 :     pOut->GetMediaType(&mtOut);
532 :     if (mtOut != NULL)
533 :     {
534 :     HRESULT result;
535 :    
536 :     result = ChangeColorspace(mtOut->subtype, mtOut->formattype, mtOut->pbFormat);
537 :     DeleteMediaType(mtOut);
538 :    
539 :     if (result != S_OK)
540 :     {
541 :     return result;
542 :     }
543 :     }
544 :    
545 :     if (pIn->GetPointer((BYTE**)&m_frame.bitstream) != S_OK)
546 :     {
547 :     return S_FALSE;
548 :     }
549 :    
550 :     if (pOut->GetPointer((BYTE**)&m_frame.image) != S_OK)
551 :     {
552 :     return S_FALSE;
553 :     }
554 :    
555 :     m_frame.length = pIn->GetSize();
556 :    
557 :     if (pIn->IsPreroll() != S_OK)
558 :     {
559 :     if (m_xvid_decore(m_param.handle, XVID_DEC_DECODE, &m_frame, 0) != XVID_ERR_OK)
560 :     {
561 :     return S_FALSE;
562 :     }
563 :     }
564 :     else
565 :     {
566 :     int tmp = m_frame.colorspace;
567 :     m_frame.colorspace = XVID_CSP_NULL;
568 :    
569 :     if (m_xvid_decore(m_param.handle, XVID_DEC_DECODE, &m_frame, 0) != XVID_ERR_OK)
570 :     {
571 :     return S_FALSE;
572 :     }
573 :    
574 :     m_frame.colorspace = tmp;
575 :    
576 :     }
577 :    
578 :     return S_OK;
579 :     }
580 :    
581 :    
582 :     /* get property page list */
583 :    
584 :     STDMETHODIMP CXvidDecoder::GetPages(CAUUID * pPages)
585 :     {
586 :     DEBUG("GetPages");
587 :    
588 :     pPages->cElems = 1;
589 :     pPages->pElems = (GUID *)CoTaskMemAlloc(pPages->cElems * sizeof(GUID));
590 :     if (pPages->pElems == NULL)
591 :     {
592 :     return E_OUTOFMEMORY;
593 :     }
594 :     pPages->pElems[0] = CLSID_CABOUT;
595 :    
596 :     return S_OK;
597 :     }
598 :    
599 :    
600 :     /* cleanup pages */
601 :    
602 :     STDMETHODIMP CXvidDecoder::FreePages(CAUUID * pPages)
603 :     {
604 :     DEBUG("FreePages");
605 :     CoTaskMemFree(pPages->pElems);
606 :     return S_OK;
607 :     }

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4