Mercurial > mplayer.hg
annotate loader/dshow/DS_VideoDecoder.c @ 6371:622d57683187
Fix asf stream wich were giving invalid frame times because the frame time
was 0.
author | albeu |
---|---|
date | Mon, 10 Jun 2002 09:59:44 +0000 |
parents | c42ab0e5bbbc |
children | 1baa35e06053 |
rev | line source |
---|---|
1545 | 1 /******************************************************** |
2 | |
3 DirectShow Video decoder implementation | |
4 Copyright 2000 Eugene Kuznetsov (divx@euro.ru) | |
5 | |
6 *********************************************************/ | |
7 | |
8 #include "guids.h" | |
9 #include "interfaces.h" | |
10 | |
3946 | 11 #ifndef NOAVIFILE_HEADERS |
12 #include "videodecoder.h" | |
13 #else | |
14 #include "libwin32.h" | |
15 #endif | |
16 #include "DS_Filter.h" | |
17 | |
18 struct _DS_VideoDecoder | |
19 { | |
20 IVideoDecoder iv; | |
21 | |
22 DS_Filter* m_pDS_Filter; | |
23 AM_MEDIA_TYPE m_sOurType, m_sDestType; | |
24 VIDEOINFOHEADER* m_sVhdr; | |
25 VIDEOINFOHEADER* m_sVhdr2; | |
26 int m_Caps;//CAPS m_Caps; // capabilities of DirectShow decoder | |
27 int m_iLastQuality; // remember last quality as integer | |
28 int m_iMinBuffers; | |
29 int m_iMaxAuto; | |
30 int m_bIsDivX; // for speed | |
31 int m_bIsDivX4; // for speed | |
32 }; | |
33 | |
1545 | 34 #include "DS_VideoDecoder.h" |
3946 | 35 |
3059 | 36 #include "../wine/winerror.h" |
37 | |
38 #ifndef NOAVIFILE_HEADERS | |
39 #define VFW_E_NOT_RUNNING 0x80040226 | |
40 #include "fourcc.h" | |
41 #include "except.h" | |
42 #endif | |
1545 | 43 |
44 #include <unistd.h> | |
45 #include <fcntl.h> | |
46 #include <errno.h> | |
47 #include <sys/types.h> | |
48 #include <sys/mman.h> | |
3059 | 49 #include <stdio.h> |
50 #include <stdlib.h> // labs | |
2072 | 51 |
3059 | 52 // strcmp((const char*)info.dll,...) is used instead of (... == ...) |
53 // so Arpi could use char* pointer in his simplified DS_VideoDecoder class | |
1545 | 54 |
55 #define __MODULE__ "DirectShow_VideoDecoder" | |
56 | |
3059 | 57 #define false 0 |
58 #define true 1 | |
59 | |
60 int DS_VideoDecoder_GetCapabilities(DS_VideoDecoder *this) | |
61 {return this->m_Caps;} | |
62 | |
63 typedef struct _ct ct; | |
1545 | 64 |
3059 | 65 struct _ct { |
66 unsigned int bits; | |
67 fourcc_t fcc; | |
68 GUID *subtype; | |
69 int cap; | |
70 }; | |
71 | |
72 static ct check[] = { | |
73 {16, fccYUY2, &MEDIASUBTYPE_YUY2, CAP_YUY2}, | |
74 {12, fccIYUV, &MEDIASUBTYPE_IYUV, CAP_IYUV}, | |
75 {16, fccUYVY, &MEDIASUBTYPE_UYVY, CAP_UYVY}, | |
76 {12, fccYV12, &MEDIASUBTYPE_YV12, CAP_YV12}, | |
77 {16, fccYV12, &MEDIASUBTYPE_YV12, CAP_YV12}, | |
78 {16, fccYVYU, &MEDIASUBTYPE_YVYU, CAP_YVYU}, | |
79 //{12, fccI420, &MEDIASUBTYPE_I420, CAP_I420}, | |
80 {0}, | |
81 }; | |
82 | |
83 | |
3444 | 84 DS_VideoDecoder * DS_VideoDecoder_Open(char* dllname, GUID* guid, BITMAPINFOHEADER * format, int flip, int maxauto) |
1545 | 85 { |
3059 | 86 DS_VideoDecoder *this; |
87 HRESULT result; | |
88 ct* c; | |
89 | |
90 this = malloc(sizeof(DS_VideoDecoder)); | |
91 memset( this, 0, sizeof(DS_VideoDecoder)); | |
92 | |
93 this->m_sVhdr2 = 0; | |
94 this->m_iLastQuality = -1; | |
95 this->m_iMaxAuto = maxauto; | |
96 | |
3063 | 97 Setup_LDT_Keeper(); |
98 | |
1545 | 99 //memset(&m_obh, 0, sizeof(m_obh)); |
100 //m_obh.biSize = sizeof(m_obh); | |
3059 | 101 /*try*/ |
1545 | 102 { |
3059 | 103 unsigned int bihs; |
104 | |
105 bihs = (format->biSize < (int) sizeof(BITMAPINFOHEADER)) ? | |
106 sizeof(BITMAPINFOHEADER) : format->biSize; | |
107 | |
108 this->iv.m_bh = (BITMAPINFOHEADER*)malloc(bihs); | |
109 memcpy(this->iv.m_bh, format, bihs); | |
4205
c42ab0e5bbbc
possible sig11 fixed - noticed by Fredrik Kuivinen <freku045@student.liu.se>
arpi
parents:
3978
diff
changeset
|
110 |
3059 | 111 this->iv.m_State = STOP; |
112 //this->iv.m_pFrame = 0; | |
113 this->iv.m_Mode = DIRECT; | |
114 this->iv.m_iDecpos = 0; | |
115 this->iv.m_iPlaypos = -1; | |
116 this->iv.m_fQuality = 0.0f; | |
117 this->iv.m_bCapable16b = true; | |
118 | |
4205
c42ab0e5bbbc
possible sig11 fixed - noticed by Fredrik Kuivinen <freku045@student.liu.se>
arpi
parents:
3978
diff
changeset
|
119 bihs += sizeof(VIDEOINFOHEADER) - sizeof(BITMAPINFOHEADER); |
3059 | 120 this->m_sVhdr = (VIDEOINFOHEADER*)malloc(bihs); |
121 memset(this->m_sVhdr, 0, bihs); | |
122 memcpy(&this->m_sVhdr->bmiHeader, this->iv.m_bh, this->iv.m_bh->biSize); | |
123 this->m_sVhdr->rcSource.left = this->m_sVhdr->rcSource.top = 0; | |
124 this->m_sVhdr->rcSource.right = this->m_sVhdr->bmiHeader.biWidth; | |
125 this->m_sVhdr->rcSource.bottom = this->m_sVhdr->bmiHeader.biHeight; | |
126 //this->m_sVhdr->rcSource.right = 0; | |
127 //this->m_sVhdr->rcSource.bottom = 0; | |
128 this->m_sVhdr->rcTarget = this->m_sVhdr->rcSource; | |
1545 | 129 |
3059 | 130 this->m_sOurType.majortype = MEDIATYPE_Video; |
131 this->m_sOurType.subtype = MEDIATYPE_Video; | |
132 this->m_sOurType.subtype.f1 = this->m_sVhdr->bmiHeader.biCompression; | |
133 this->m_sOurType.formattype = FORMAT_VideoInfo; | |
134 this->m_sOurType.bFixedSizeSamples = false; | |
135 this->m_sOurType.bTemporalCompression = true; | |
136 this->m_sOurType.pUnk = 0; | |
137 this->m_sOurType.cbFormat = bihs; | |
138 this->m_sOurType.pbFormat = (char*)this->m_sVhdr; | |
139 | |
140 this->m_sVhdr2 = (VIDEOINFOHEADER*)(malloc(sizeof(VIDEOINFOHEADER)+12)); | |
141 memcpy(this->m_sVhdr2, this->m_sVhdr, sizeof(VIDEOINFOHEADER)); | |
142 memset((char*)this->m_sVhdr2 + sizeof(VIDEOINFOHEADER), 0, 12); | |
143 this->m_sVhdr2->bmiHeader.biCompression = 0; | |
144 this->m_sVhdr2->bmiHeader.biBitCount = 24; | |
1545 | 145 |
3059 | 146 memset(&this->m_sDestType, 0, sizeof(this->m_sDestType)); |
147 this->m_sDestType.majortype = MEDIATYPE_Video; | |
148 this->m_sDestType.subtype = MEDIASUBTYPE_RGB24; | |
149 this->m_sDestType.formattype = FORMAT_VideoInfo; | |
150 this->m_sDestType.bFixedSizeSamples = true; | |
151 this->m_sDestType.bTemporalCompression = false; | |
152 this->m_sDestType.lSampleSize = labs(this->m_sVhdr2->bmiHeader.biWidth*this->m_sVhdr2->bmiHeader.biHeight | |
153 * ((this->m_sVhdr2->bmiHeader.biBitCount + 7) / 8)); | |
154 this->m_sVhdr2->bmiHeader.biSizeImage = this->m_sDestType.lSampleSize; | |
155 this->m_sDestType.pUnk = 0; | |
156 this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER); | |
157 this->m_sDestType.pbFormat = (char*)this->m_sVhdr2; | |
158 | |
159 memset(&this->iv.m_obh, 0, sizeof(this->iv.m_obh)); | |
160 memcpy(&this->iv.m_obh, this->iv.m_bh, sizeof(this->iv.m_obh) < (unsigned) this->iv.m_bh->biSize | |
161 ? sizeof(this->iv.m_obh) : (unsigned) this->iv.m_bh->biSize); | |
162 this->iv.m_obh.biBitCount=24; | |
163 this->iv.m_obh.biSize = sizeof(BITMAPINFOHEADER); | |
164 this->iv.m_obh.biCompression = 0; //BI_RGB | |
165 //this->iv.m_obh.biHeight = labs(this->iv.m_obh.biHeight); | |
166 this->iv.m_obh.biSizeImage = labs(this->iv.m_obh.biWidth * this->iv.m_obh.biHeight) | |
167 * ((this->iv.m_obh.biBitCount + 7) / 8); | |
1545 | 168 |
169 | |
3444 | 170 this->m_pDS_Filter = DS_FilterCreate(dllname, guid, &this->m_sOurType, &this->m_sDestType); |
3456 | 171 |
172 if (!this->m_pDS_Filter) | |
173 { | |
174 printf("Failed to create DirectShow filter\n"); | |
175 return 0; | |
176 } | |
1545 | 177 |
178 if (!flip) | |
179 { | |
3059 | 180 this->iv.m_obh.biHeight *= -1; |
3466 | 181 this->m_sVhdr2->bmiHeader.biHeight = this->iv.m_obh.biHeight; |
3059 | 182 result = this->m_pDS_Filter->m_pOutputPin->vt->QueryAccept(this->m_pDS_Filter->m_pOutputPin, &this->m_sDestType); |
1545 | 183 if (result) |
184 { | |
3466 | 185 printf("Decoder does not support upside-down RGB frames\n"); |
3059 | 186 this->iv.m_obh.biHeight *= -1; |
3466 | 187 this->m_sVhdr2->bmiHeader.biHeight = this->iv.m_obh.biHeight; |
1545 | 188 } |
189 } | |
190 | |
3059 | 191 memcpy( &this->iv.m_decoder, &this->iv.m_obh, sizeof(this->iv.m_obh) ); |
1545 | 192 |
3059 | 193 switch (this->iv.m_bh->biCompression) |
1545 | 194 { |
195 case fccDIV3: | |
196 case fccDIV4: | |
197 case fccDIV5: | |
3059 | 198 case fccDIV6: |
1545 | 199 case fccMP42: |
200 case fccWMV2: | |
201 //YV12 seems to be broken for DivX :-) codec | |
3060 | 202 // case fccIV50: |
1545 | 203 //produces incorrect picture |
204 //m_Caps = (CAPS) (m_Caps & ~CAP_YV12); | |
3059 | 205 //m_Caps = CAP_UYVY;//CAP_YUY2; // | CAP_I420; |
206 //m_Caps = CAP_I420; | |
207 this->m_Caps = (CAP_YUY2 | CAP_UYVY); | |
1545 | 208 break; |
209 default: | |
3059 | 210 |
211 this->m_Caps = CAP_NONE; | |
1545 | 212 |
3059 | 213 for (c = check; c->bits; c++) |
1545 | 214 { |
3059 | 215 this->m_sVhdr2->bmiHeader.biBitCount = c->bits; |
216 this->m_sVhdr2->bmiHeader.biCompression = c->fcc; | |
217 this->m_sDestType.subtype = *c->subtype; | |
218 result = this->m_pDS_Filter->m_pOutputPin->vt->QueryAccept(this->m_pDS_Filter->m_pOutputPin, &this->m_sDestType); | |
1545 | 219 if (!result) |
3059 | 220 this->m_Caps = (this->m_Caps | c->cap); |
1545 | 221 } |
222 } | |
223 | |
3059 | 224 if (this->m_Caps != CAP_NONE) |
225 printf("Decoder is capable of YUV output ( flags 0x%x)\n", (int)this->m_Caps); | |
1545 | 226 |
3059 | 227 this->m_sVhdr2->bmiHeader.biBitCount = 24; |
228 this->m_sVhdr2->bmiHeader.biCompression = 0; | |
229 this->m_sDestType.subtype = MEDIASUBTYPE_RGB24; | |
1545 | 230 |
3059 | 231 this->m_iMinBuffers = this->iv.VBUFSIZE; |
3444 | 232 this->m_bIsDivX = (strcmp(dllname, "divxcvki.ax") == 0 |
233 || strcmp(dllname, "divx_c32.ax") == 0 | |
234 || strcmp(dllname, "wmvds32.ax") == 0 | |
235 || strcmp(dllname, "wmv8ds32.ax") == 0); | |
236 this->m_bIsDivX4 = (strcmp(dllname, "divxdec.ax") == 0); | |
3059 | 237 if (this->m_bIsDivX) |
238 this->iv.VBUFSIZE += 7; | |
239 else if (this->m_bIsDivX4) | |
240 this->iv.VBUFSIZE += 9; | |
1545 | 241 } |
3059 | 242 /*catch (FatalError& error) |
1545 | 243 { |
3059 | 244 delete[] m_sVhdr; |
1545 | 245 delete[] m_sVhdr2; |
246 delete m_pDS_Filter; | |
247 throw; | |
3059 | 248 }*/ |
249 return this; | |
1545 | 250 } |
251 | |
3059 | 252 void DS_VideoDecoder_Destroy(DS_VideoDecoder *this) |
1545 | 253 { |
3059 | 254 DS_VideoDecoder_StopInternal(this); |
255 this->iv.m_State = STOP; | |
256 free(this->m_sVhdr); | |
257 free(this->m_sVhdr2); | |
258 DS_Filter_Destroy(this->m_pDS_Filter); | |
1545 | 259 } |
260 | |
3059 | 261 void DS_VideoDecoder_StartInternal(DS_VideoDecoder *this) |
1545 | 262 { |
3059 | 263 ALLOCATOR_PROPERTIES props, props1; |
264 Debug printf("DS_VideoDecoder_StartInternal\n"); | |
1545 | 265 //cout << "DSSTART" << endl; |
3063 | 266 this->m_pDS_Filter->Start(this->m_pDS_Filter); |
3059 | 267 |
1545 | 268 props.cBuffers = 1; |
3059 | 269 props.cbBuffer = this->m_sDestType.lSampleSize; |
270 | |
1545 | 271 //don't know how to do this correctly |
272 props.cbAlign = props.cbPrefix = 0; | |
3059 | 273 this->m_pDS_Filter->m_pAll->vt->SetProperties(this->m_pDS_Filter->m_pAll, &props, &props1); |
274 this->m_pDS_Filter->m_pAll->vt->Commit(this->m_pDS_Filter->m_pAll); | |
275 | |
3957
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
276 this->iv.m_State = START; |
1545 | 277 } |
278 | |
3059 | 279 void DS_VideoDecoder_StopInternal(DS_VideoDecoder *this) |
1545 | 280 { |
3063 | 281 this->m_pDS_Filter->Stop(this->m_pDS_Filter); |
1545 | 282 //??? why was this here ??? m_pOurOutput->SetFramePointer(0); |
283 } | |
284 | |
3063 | 285 int DS_VideoDecoder_DecodeInternal(DS_VideoDecoder *this, const void* src, int size, int is_keyframe, char* pImage) |
1545 | 286 { |
287 IMediaSample* sample = 0; | |
3059 | 288 char* ptr; |
289 int result; | |
290 | |
3063 | 291 Debug printf("DS_VideoDecoder_DecodeInternal(%p,%p,%d,%d,%p)\n",this,src,size,is_keyframe,pImage); |
3059 | 292 |
293 this->m_pDS_Filter->m_pAll->vt->GetBuffer(this->m_pDS_Filter->m_pAll, &sample, 0, 0, 0); | |
294 | |
1545 | 295 if (!sample) |
296 { | |
3059 | 297 Debug printf("ERROR: null sample\n"); |
1545 | 298 return -1; |
299 } | |
3059 | 300 |
1545 | 301 //cout << "DECODE " << (void*) pImage << " d: " << (void*) pImage->Data() << endl; |
302 if (pImage) | |
303 { | |
3063 | 304 this->m_pDS_Filter->m_pOurOutput->SetPointer2(this->m_pDS_Filter->m_pOurOutput,pImage); |
1545 | 305 } |
306 | |
3059 | 307 |
3466 | 308 sample->vt->SetActualDataLength(sample, size); |
1545 | 309 sample->vt->GetPointer(sample, (BYTE **)&ptr); |
310 memcpy(ptr, src, size); | |
311 sample->vt->SetSyncPoint(sample, is_keyframe); | |
312 sample->vt->SetPreroll(sample, pImage ? 0 : 1); | |
313 // sample->vt->SetMediaType(sample, &m_sOurType); | |
314 | |
315 // FIXME: - crashing with YV12 at this place decoder will crash | |
316 // while doing this call | |
317 // %FS register was not setup for calling into win32 dll. Are all | |
318 // crashes inside ...->Receive() fixed now? | |
319 // | |
320 // nope - but this is surely helpfull - I'll try some more experiments | |
3060 | 321 Setup_FS_Segment(); |
1545 | 322 #if 0 |
3059 | 323 if (!this->m_pDS_Filter || !this->m_pDS_Filter->m_pImp |
324 || !this->m_pDS_Filter->m_pImp->vt | |
325 || !this->m_pDS_Filter->m_pImp->vt->Receive) | |
1545 | 326 printf("DecodeInternal ERROR???\n"); |
327 #endif | |
3059 | 328 result = this->m_pDS_Filter->m_pImp->vt->Receive(this->m_pDS_Filter->m_pImp, sample); |
1545 | 329 if (result) |
330 { | |
331 Debug printf("DS_VideoDecoder::DecodeInternal() error putting data into input pin %x\n", result); | |
332 } | |
333 | |
334 sample->vt->Release((IUnknown*)sample); | |
335 | |
3059 | 336 #if 0 |
337 if (this->m_bIsDivX) | |
1545 | 338 { |
339 int q; | |
3059 | 340 IHidden* hidden=(IHidden*)((int)this->m_pDS_Filter->m_pFilter + 0xb8); |
1545 | 341 // always check for actual value |
342 // this seems to be the only way to know the actual value | |
3059 | 343 hidden->vt->GetSmth2(hidden, &this->m_iLastQuality); |
344 if (this->m_iLastQuality > 9) | |
345 this->m_iLastQuality -= 10; | |
346 | |
347 if (this->m_iLastQuality < 0) | |
348 this->m_iLastQuality = 0; | |
349 else if (this->m_iLastQuality > this->m_iMaxAuto) | |
350 this->m_iLastQuality = this->m_iMaxAuto; | |
1545 | 351 |
3059 | 352 //cout << " Qual: " << this->m_iLastQuality << endl; |
353 this->iv.m_fQuality = this->m_iLastQuality / 4.0; | |
354 } | |
355 else if (this->m_bIsDivX4) | |
356 { | |
357 | |
358 // maybe access methods directly to safe some cpu cycles... | |
359 DS_VideoDecoder_GetValue(this, "Postprocessing", this->m_iLastQuality); | |
360 if (this->m_iLastQuality < 0) | |
361 this->m_iLastQuality = 0; | |
362 else if (this->m_iLastQuality > this->m_iMaxAuto) | |
363 this->m_iLastQuality = this->m_iMaxAuto; | |
1545 | 364 |
365 //cout << " Qual: " << m_iLastQuality << endl; | |
3059 | 366 this->iv.m_fQuality = this->m_iLastQuality / 6.0; |
1545 | 367 } |
368 | |
3059 | 369 if (this->iv.m_Mode == -1 ) // ???BUFFERED_QUALITY_AUTO) |
1545 | 370 { |
371 // adjust Quality - depends on how many cached frames we have | |
3059 | 372 int buffered = this->iv.m_iDecpos - this->iv.m_iPlaypos; |
1545 | 373 |
3059 | 374 if (this->m_bIsDivX || this->m_bIsDivX4) |
375 { | |
376 int to = buffered - this->m_iMinBuffers; | |
377 if (to < 0) | |
378 to = 0; | |
379 if (to != this->m_iLastQuality) | |
380 { | |
381 if (to > this->m_iMaxAuto) | |
382 to = this->m_iMaxAuto; | |
383 if (this->m_iLastQuality != to) | |
1545 | 384 { |
3059 | 385 if (this->m_bIsDivX) |
386 { | |
387 IHidden* hidden=(IHidden*)((int)this->m_pDS_Filter->m_pFilter + 0xb8); | |
388 hidden->vt->SetSmth(hidden, to, 0); | |
389 } | |
390 else | |
391 DS_VideoDecoder_SetValue(this, "Postprocessing", to); | |
1545 | 392 #ifndef QUIET |
3059 | 393 //printf("Switching quality %d -> %d b:%d\n",m_iLastQuality, to, buffered); |
1545 | 394 #endif |
395 } | |
396 } | |
397 } | |
398 } | |
3059 | 399 #endif |
1545 | 400 |
401 return 0; | |
402 } | |
403 | |
404 /* | |
405 * bits == 0 - leave unchanged | |
406 */ | |
3059 | 407 //int SetDestFmt(DS_VideoDecoder * this, int bits = 24, fourcc_t csp = 0); |
3946 | 408 int DS_VideoDecoder_SetDestFmt(DS_VideoDecoder *this, int bits, unsigned int csp) |
1545 | 409 { |
3059 | 410 HRESULT result; |
411 int should_test=1; | |
412 int stoped = 0; | |
413 | |
414 Debug printf("DS_VideoDecoder_SetDestFmt (%p, %d, %d)\n",this,bits,(int)csp); | |
415 | |
416 /* if (!CImage::Supported(csp, bits)) | |
1545 | 417 return -1; |
3059 | 418 */ |
1545 | 419 // BitmapInfo temp = m_obh; |
3059 | 420 |
3063 | 421 if (!csp) // RGB |
1545 | 422 { |
3059 | 423 int ok = true; |
1545 | 424 |
425 switch (bits) | |
426 { | |
427 case 15: | |
3059 | 428 this->m_sDestType.subtype = MEDIASUBTYPE_RGB555; |
1545 | 429 break; |
430 case 16: | |
3059 | 431 this->m_sDestType.subtype = MEDIASUBTYPE_RGB565; |
1545 | 432 break; |
433 case 24: | |
3059 | 434 this->m_sDestType.subtype = MEDIASUBTYPE_RGB24; |
1545 | 435 break; |
436 case 32: | |
3059 | 437 this->m_sDestType.subtype = MEDIASUBTYPE_RGB32; |
1545 | 438 break; |
439 default: | |
440 ok = false; | |
441 break; | |
442 } | |
443 | |
3059 | 444 if (ok) { |
445 this->iv.m_obh.biBitCount=bits; | |
446 if( bits == 15 || bits == 16 ) { | |
447 this->iv.m_obh.biSize=sizeof(BITMAPINFOHEADER)+12; | |
448 this->iv.m_obh.biCompression=3;//BI_BITFIELDS | |
449 this->iv.m_obh.biSizeImage=abs((int)(2*this->iv.m_obh.biWidth*this->iv.m_obh.biHeight)); | |
450 } | |
451 | |
452 if( bits == 16 ) { | |
453 this->iv.m_obh.colors[0]=0xF800; | |
454 this->iv.m_obh.colors[1]=0x07E0; | |
455 this->iv.m_obh.colors[2]=0x001F; | |
456 } else if ( bits == 15 ) { | |
457 this->iv.m_obh.colors[0]=0x7C00; | |
458 this->iv.m_obh.colors[1]=0x03E0; | |
459 this->iv.m_obh.colors[2]=0x001F; | |
460 } else { | |
461 this->iv.m_obh.biSize = sizeof(BITMAPINFOHEADER); | |
462 this->iv.m_obh.biCompression = 0; //BI_RGB | |
463 //this->iv.m_obh.biHeight = labs(this->iv.m_obh.biHeight); | |
464 this->iv.m_obh.biSizeImage = labs(this->iv.m_obh.biWidth * this->iv.m_obh.biHeight) | |
465 * ((this->iv.m_obh.biBitCount + 7) / 8); | |
466 } | |
467 } | |
1545 | 468 //.biSizeImage=abs(temp.biWidth*temp.biHeight*((temp.biBitCount+7)/8)); |
3063 | 469 } else |
470 { // YUV | |
3059 | 471 int ok = true; |
1545 | 472 switch (csp) |
473 { | |
474 case fccYUY2: | |
3059 | 475 this->m_sDestType.subtype = MEDIASUBTYPE_YUY2; |
1545 | 476 break; |
477 case fccYV12: | |
3059 | 478 this->m_sDestType.subtype = MEDIASUBTYPE_YV12; |
1545 | 479 break; |
480 case fccIYUV: | |
3059 | 481 this->m_sDestType.subtype = MEDIASUBTYPE_IYUV; |
1545 | 482 break; |
483 case fccUYVY: | |
3059 | 484 this->m_sDestType.subtype = MEDIASUBTYPE_UYVY; |
1545 | 485 break; |
486 case fccYVYU: | |
3059 | 487 this->m_sDestType.subtype = MEDIASUBTYPE_YVYU; |
1545 | 488 break; |
489 default: | |
490 ok = false; | |
491 break; | |
492 } | |
493 | |
3059 | 494 if (ok) { |
495 if (csp != 0 && csp != 3 && this->iv.m_obh.biHeight > 0) | |
496 this->iv.m_obh.biHeight *= -1; // YUV formats uses should have height < 0 | |
497 this->iv.m_obh.biSize = sizeof(BITMAPINFOHEADER); | |
498 this->iv.m_obh.biCompression=csp; | |
499 this->iv.m_obh.biBitCount=bits; | |
500 this->iv.m_obh.biSizeImage=labs(this->iv.m_obh.biBitCount* | |
501 this->iv.m_obh.biWidth*this->iv.m_obh.biHeight)>>3; | |
502 } | |
1545 | 503 } |
3059 | 504 this->m_sDestType.lSampleSize = this->iv.m_obh.biSizeImage; |
505 memcpy(&(this->m_sVhdr2->bmiHeader), &this->iv.m_obh, sizeof(this->iv.m_obh)); | |
506 this->m_sVhdr2->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); | |
507 if (this->m_sVhdr2->bmiHeader.biCompression == 3) | |
508 this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER) + 12; | |
1545 | 509 else |
3059 | 510 this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER); |
1545 | 511 |
3059 | 512 |
1545 | 513 switch(csp) |
514 { | |
515 case fccYUY2: | |
3059 | 516 if(!(this->m_Caps & CAP_YUY2)) |
1545 | 517 should_test=false; |
518 break; | |
519 case fccYV12: | |
3059 | 520 if(!(this->m_Caps & CAP_YV12)) |
1545 | 521 should_test=false; |
522 break; | |
523 case fccIYUV: | |
3059 | 524 if(!(this->m_Caps & CAP_IYUV)) |
1545 | 525 should_test=false; |
526 break; | |
527 case fccUYVY: | |
3059 | 528 if(!(this->m_Caps & CAP_UYVY)) |
1545 | 529 should_test=false; |
530 break; | |
531 case fccYVYU: | |
3059 | 532 if(!(this->m_Caps & CAP_YVYU)) |
1545 | 533 should_test=false; |
534 break; | |
535 } | |
536 if(should_test) | |
3059 | 537 result = this->m_pDS_Filter->m_pOutputPin->vt->QueryAccept(this->m_pDS_Filter->m_pOutputPin, &this->m_sDestType); |
1545 | 538 else |
539 result = -1; | |
540 | |
541 if (result != 0) | |
542 { | |
543 if (csp) | |
3059 | 544 printf("Warning: unsupported color space\n"); |
1545 | 545 else |
3059 | 546 printf("Warning: unsupported bit depth\n"); |
1545 | 547 |
3059 | 548 this->m_sDestType.lSampleSize = this->iv.m_decoder.biSizeImage; |
549 memcpy(&(this->m_sVhdr2->bmiHeader), &this->iv.m_decoder, sizeof(this->iv.m_decoder)); | |
550 this->m_sVhdr2->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); | |
551 if (this->m_sVhdr2->bmiHeader.biCompression == 3) | |
552 this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER) + 12; | |
1545 | 553 else |
3059 | 554 this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER); |
1545 | 555 |
3059 | 556 return -1; |
1545 | 557 } |
558 | |
3059 | 559 memcpy( &this->iv.m_decoder, &this->iv.m_obh, sizeof(this->iv.m_obh)); |
1545 | 560 |
561 // m_obh=temp; | |
562 // if(csp) | |
563 // m_obh.biBitCount=BitmapInfo::BitCount(csp); | |
3059 | 564 this->iv.m_bh->biBitCount = bits; |
565 | |
566 //DS_VideoDecoder_Restart(this); | |
1545 | 567 |
3059 | 568 if (this->iv.m_State == START) |
1545 | 569 { |
3059 | 570 DS_VideoDecoder_StopInternal(this); |
571 this->iv.m_State = STOP; | |
1545 | 572 stoped = true; |
573 } | |
574 | |
3059 | 575 this->m_pDS_Filter->m_pInputPin->vt->Disconnect(this->m_pDS_Filter->m_pInputPin); |
576 this->m_pDS_Filter->m_pOutputPin->vt->Disconnect(this->m_pDS_Filter->m_pOutputPin); | |
3063 | 577 this->m_pDS_Filter->m_pOurOutput->SetNewFormat(this->m_pDS_Filter->m_pOurOutput,&this->m_sDestType); |
3059 | 578 result = this->m_pDS_Filter->m_pInputPin->vt->ReceiveConnection(this->m_pDS_Filter->m_pInputPin, |
579 this->m_pDS_Filter->m_pOurInput, | |
580 &this->m_sOurType); | |
1545 | 581 if (result) |
582 { | |
3059 | 583 printf("Error reconnecting input pin 0x%x\n", (int)result); |
1545 | 584 return -1; |
585 } | |
3059 | 586 result = this->m_pDS_Filter->m_pOutputPin->vt->ReceiveConnection(this->m_pDS_Filter->m_pOutputPin, |
587 (IPin *)this->m_pDS_Filter->m_pOurOutput, | |
588 &this->m_sDestType); | |
1545 | 589 if (result) |
590 { | |
3059 | 591 printf("Error reconnecting output pin 0x%x\n", (int)result); |
1545 | 592 return -1; |
593 } | |
594 | |
595 if (stoped) | |
3059 | 596 { |
597 DS_VideoDecoder_StartInternal(this); | |
598 this->iv.m_State = START; | |
599 } | |
1545 | 600 |
601 return 0; | |
602 } | |
603 | |
3059 | 604 |
605 int DS_VideoDecoder_SetDirection(DS_VideoDecoder *this, int d) | |
606 { | |
607 this->iv.m_obh.biHeight = (d) ? this->iv.m_bh->biHeight : -this->iv.m_bh->biHeight; | |
608 this->m_sVhdr2->bmiHeader.biHeight = this->iv.m_obh.biHeight; | |
609 return 0; | |
610 } | |
611 | |
3946 | 612 int DS_VideoDecoder_GetValue(DS_VideoDecoder *this, const char* name, int* value) |
1545 | 613 { |
3059 | 614 /* |
615 if (m_bIsDivX4) | |
616 { | |
617 IDivxFilterInterface* pIDivx; | |
618 if (m_pDS_Filter->m_pFilter->vt->QueryInterface((IUnknown*)m_pDS_Filter->m_pFilter, &IID_IDivxFilterInterface, (void**)&pIDivx)) | |
619 { | |
620 Debug printf("No such interface\n"); | |
621 return -1; | |
622 } | |
623 if (strcmp(name, "Postprocessing") == 0) | |
624 { | |
625 pIDivx->vt->get_PPLevel(pIDivx, &value); | |
626 value /= 10; | |
627 } | |
628 else if (strcmp(name, "Brightness") == 0) | |
629 pIDivx->vt->get_Brightness(pIDivx, &value); | |
630 else if (strcmp(name, "Contrast") == 0) | |
631 pIDivx->vt->get_Contrast(pIDivx, &value); | |
632 else if (strcmp(name, "Saturation") == 0) | |
633 pIDivx->vt->get_Saturation(pIDivx, &value); | |
634 else if (strcmp(name, "MaxAuto") == 0) | |
635 value = m_iMaxAuto; | |
636 pIDivx->vt->Release((IUnknown*)pIDivx); | |
637 return 0; | |
638 } | |
639 else if (m_bIsDivX) | |
1545 | 640 { |
641 if (m_State != START) | |
642 return VFW_E_NOT_RUNNING; | |
643 // brightness 87 | |
644 // contrast 74 | |
645 // hue 23 | |
646 // saturation 20 | |
647 // post process mode 0 | |
648 // get1 0x01 | |
649 // get2 10 | |
650 // get3=set2 86 | |
651 // get4=set3 73 | |
652 // get5=set4 19 | |
653 // get6=set5 23 | |
654 IHidden* hidden=(IHidden*)((int)m_pDS_Filter->m_pFilter+0xb8); | |
3059 | 655 if (strcmp(name, "Quality") == 0) |
656 { | |
657 #warning NOT SURE | |
658 int r = hidden->vt->GetSmth2(hidden, &value); | |
659 if (value >= 10) | |
660 value -= 10; | |
661 return 0; | |
662 } | |
1545 | 663 if (strcmp(name, "Brightness") == 0) |
664 return hidden->vt->GetSmth3(hidden, &value); | |
665 if (strcmp(name, "Contrast") == 0) | |
666 return hidden->vt->GetSmth4(hidden, &value); | |
667 if (strcmp(name, "Hue") == 0) | |
668 return hidden->vt->GetSmth6(hidden, &value); | |
669 if (strcmp(name, "Saturation") == 0) | |
670 return hidden->vt->GetSmth5(hidden, &value); | |
3059 | 671 if (strcmp(name, "MaxAuto") == 0) |
1545 | 672 { |
3059 | 673 value = m_iMaxAuto; |
674 return 0; | |
1545 | 675 } |
676 } | |
3059 | 677 else if (strcmp((const char*)record.dll, "ir50_32.dll") == 0) |
1545 | 678 { |
679 IHidden2* hidden = 0; | |
680 if (m_pDS_Filter->m_pFilter->vt->QueryInterface((IUnknown*)m_pDS_Filter->m_pFilter, &IID_Iv50Hidden, (void**)&hidden)) | |
681 { | |
3059 | 682 Debug printf("No such interface\n"); |
1545 | 683 return -1; |
684 } | |
685 #warning FIXME | |
686 int recordpar[30]; | |
687 recordpar[0]=0x7c; | |
688 recordpar[1]=fccIV50; | |
689 recordpar[2]=0x10005; | |
690 recordpar[3]=2; | |
691 recordpar[4]=1; | |
692 recordpar[5]=0x80000000; | |
693 | |
694 if (strcmp(name, "Brightness") == 0) | |
695 recordpar[5]|=0x20; | |
696 else if (strcmp(name, "Saturation") == 0) | |
697 recordpar[5]|=0x40; | |
698 else if (strcmp(name, "Contrast") == 0) | |
699 recordpar[5]|=0x80; | |
700 if (!recordpar[5]) | |
701 { | |
702 hidden->vt->Release((IUnknown*)hidden); | |
703 return -1; | |
704 } | |
705 if (hidden->vt->DecodeSet(hidden, recordpar)) | |
706 return -1; | |
707 | |
708 if (strcmp(name, "Brightness") == 0) | |
709 value = recordpar[18]; | |
710 else if (strcmp(name, "Saturation") == 0) | |
711 value = recordpar[19]; | |
712 else if (strcmp(name, "Contrast") == 0) | |
713 value = recordpar[20]; | |
714 | |
715 hidden->vt->Release((IUnknown*)hidden); | |
716 } | |
3059 | 717 */ |
1545 | 718 return 0; |
719 } | |
720 | |
3946 | 721 int DS_VideoDecoder_SetValue(DS_VideoDecoder *this, const char* name, int value) |
1545 | 722 { |
3957
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
723 if (this->m_bIsDivX4) { |
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
724 IDivxFilterInterface* pIDivx=NULL; |
3978 | 725 // printf("DS_SetValue for DIVX4, name=%s value=%d\n",name,value); |
3957
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
726 if (this->m_pDS_Filter->m_pFilter->vt->QueryInterface((IUnknown*)this->m_pDS_Filter->m_pFilter, &IID_IDivxFilterInterface, (void**)&pIDivx)) |
3059 | 727 { |
3957
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
728 printf("No such interface\n"); |
3059 | 729 return -1; |
730 } | |
731 if (strcmp(name, "Postprocessing") == 0) | |
732 pIDivx->vt->put_PPLevel(pIDivx, value * 10); | |
733 else if (strcmp(name, "Brightness") == 0) | |
734 pIDivx->vt->put_Brightness(pIDivx, value); | |
735 else if (strcmp(name, "Contrast") == 0) | |
736 pIDivx->vt->put_Contrast(pIDivx, value); | |
737 else if (strcmp(name, "Saturation") == 0) | |
738 pIDivx->vt->put_Saturation(pIDivx, value); | |
739 else if (strcmp(name, "MaxAuto") == 0) | |
3957
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
740 this->m_iMaxAuto = value; |
3059 | 741 pIDivx->vt->Release((IUnknown*)pIDivx); |
742 //printf("Set %s %d\n", name, value); | |
743 return 0; | |
744 } | |
3957
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
745 |
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
746 if (this->m_bIsDivX) { |
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
747 IHidden* hidden; |
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
748 if (this->iv.m_State != START) |
1545 | 749 return VFW_E_NOT_RUNNING; |
750 | |
751 //cout << "set value " << name << " " << value << endl; | |
752 // brightness 87 | |
753 // contrast 74 | |
754 // hue 23 | |
755 // saturation 20 | |
756 // post process mode 0 | |
757 // get1 0x01 | |
758 // get2 10 | |
759 // get3=set2 86 | |
760 // get4=set3 73 | |
761 // get5=set4 19 | |
3059 | 762 // get6=set5 23 |
3957
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
763 hidden = (IHidden*)((int)this->m_pDS_Filter->m_pFilter + 0xb8); |
3978 | 764 // printf("DS_SetValue for DIVX, name=%s value=%d\n",name,value); |
1545 | 765 if (strcmp(name, "Quality") == 0) |
766 { | |
3957
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
767 this->m_iLastQuality = value; |
1545 | 768 return hidden->vt->SetSmth(hidden, value, 0); |
769 } | |
770 if (strcmp(name, "Brightness") == 0) | |
771 return hidden->vt->SetSmth2(hidden, value, 0); | |
772 if (strcmp(name, "Contrast") == 0) | |
773 return hidden->vt->SetSmth3(hidden, value, 0); | |
774 if (strcmp(name, "Saturation") == 0) | |
775 return hidden->vt->SetSmth4(hidden, value, 0); | |
776 if (strcmp(name, "Hue") == 0) | |
777 return hidden->vt->SetSmth5(hidden, value, 0); | |
3059 | 778 if (strcmp(name, "MaxAuto") == 0) |
779 { | |
3957
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
780 this->m_iMaxAuto = value; |
3059 | 781 } |
3957
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
782 return 0; |
1545 | 783 } |
3957
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
784 #if 0 |
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
785 if (strcmp((const char*)record.dll, "ir50_32.dll") == 0) |
1545 | 786 { |
787 IHidden2* hidden = 0; | |
788 if (m_pDS_Filter->m_pFilter->vt->QueryInterface((IUnknown*)m_pDS_Filter->m_pFilter, &IID_Iv50Hidden, (void**)&hidden)) | |
789 { | |
3059 | 790 Debug printf("No such interface\n"); |
1545 | 791 return -1; |
792 } | |
793 int recordpar[30]; | |
794 recordpar[0]=0x7c; | |
795 recordpar[1]=fccIV50; | |
796 recordpar[2]=0x10005; | |
797 recordpar[3]=2; | |
798 recordpar[4]=1; | |
799 recordpar[5]=0x80000000; | |
800 if (strcmp(name, "Brightness") == 0) | |
801 { | |
802 recordpar[5]|=0x20; | |
803 recordpar[18]=value; | |
804 } | |
805 else if (strcmp(name, "Saturation") == 0) | |
806 { | |
807 recordpar[5]|=0x40; | |
808 recordpar[19]=value; | |
809 } | |
810 else if (strcmp(name, "Contrast") == 0) | |
811 { | |
812 recordpar[5]|=0x80; | |
813 recordpar[20]=value; | |
814 } | |
815 if(!recordpar[5]) | |
816 { | |
817 hidden->vt->Release((IUnknown*)hidden); | |
818 return -1; | |
819 } | |
820 HRESULT result = hidden->vt->DecodeSet(hidden, recordpar); | |
821 hidden->vt->Release((IUnknown*)hidden); | |
822 | |
823 return result; | |
824 } | |
3957
49290522ab06
SetValue fixed, iv_State=START enabled (silly xine developers disabled for unknown reason)
arpi
parents:
3946
diff
changeset
|
825 #endif |
3978 | 826 // printf("DS_SetValue for ????, name=%s value=%d\n",name,value); |
1545 | 827 return 0; |
828 } | |
829 /* | |
3063 | 830 vim: vi* sux. |
1545 | 831 */ |
3063 | 832 |
833 int DS_SetAttr_DivX(char* attribute, int value){ | |
834 int result, status, newkey, count; | |
835 if(strcmp(attribute, "Quality")==0){ | |
836 char* keyname="SOFTWARE\\Microsoft\\Scrunch"; | |
837 result=RegCreateKeyExA(HKEY_CURRENT_USER, keyname, 0, 0, 0, 0, 0, &newkey, &status); | |
838 if(result!=0) | |
839 { | |
840 printf("VideoDecoder::SetExtAttr: registry failure\n"); | |
841 return -1; | |
842 } | |
843 result=RegSetValueExA(newkey, "Current Post Process Mode", 0, REG_DWORD, &value, 4); | |
844 if(result!=0) | |
845 { | |
846 printf("VideoDecoder::SetExtAttr: error writing value\n"); | |
847 return -1; | |
848 } | |
849 value=-1; | |
850 result=RegSetValueExA(newkey, "Force Post Process Mode", 0, REG_DWORD, &value, 4); | |
851 if(result!=0) | |
852 { | |
853 printf("VideoDecoder::SetExtAttr: error writing value\n"); | |
854 return -1; | |
855 } | |
856 RegCloseKey(newkey); | |
857 return 0; | |
858 } | |
859 | |
860 if( | |
861 (strcmp(attribute, "Saturation")==0) || | |
862 (strcmp(attribute, "Hue")==0) || | |
863 (strcmp(attribute, "Contrast")==0) || | |
864 (strcmp(attribute, "Brightness")==0) | |
865 ) | |
866 { | |
867 char* keyname="SOFTWARE\\Microsoft\\Scrunch\\Video"; | |
868 result=RegCreateKeyExA(HKEY_CURRENT_USER, keyname, 0, 0, 0, 0, 0, &newkey, &status); | |
869 if(result!=0) | |
870 { | |
871 printf("VideoDecoder::SetExtAttr: registry failure\n"); | |
872 return -1; | |
873 } | |
874 result=RegSetValueExA(newkey, attribute, 0, REG_DWORD, &value, 4); | |
875 if(result!=0) | |
876 { | |
877 printf("VideoDecoder::SetExtAttr: error writing value\n"); | |
878 return -1; | |
879 } | |
880 RegCloseKey(newkey); | |
881 return 0; | |
882 } | |
883 | |
884 printf("Unknown attribute!\n"); | |
885 return -200; | |
886 } | |
887 | |
888 | |
889 | |
890 |