Mercurial > mplayer.hg
annotate loader/dshow/DS_VideoDec.c @ 1525:9525bff8bea8
fixed BITMAPINFO struct length truncation (WMV8)
author | arpi |
---|---|
date | Wed, 15 Aug 2001 00:38:01 +0000 |
parents | bd6ea9bd3f80 |
children | da26060c81ef |
rev | line source |
---|---|
169 | 1 /******************************************************** |
2 | |
3 DirectShow Video decoder implementation | |
4 Copyright 2000 Eugene Kuznetsov (divx@euro.ru) | |
5 Converted C++ --> C :) by A'rpi/ESP-team | |
6 | |
7 *********************************************************/ | |
8 | |
9 //#include <config.h> | |
10 | |
11 //#include "DS_VideoDecoder.h" | |
1073
1485ab9af8a1
ehh. removed duplicated namspace 'std'... and removed include string.h, unneeded for c++
arpi_esp
parents:
1063
diff
changeset
|
12 //#include <string.h> |
1082 | 13 using namespace std; |
169 | 14 #include <stdlib.h> |
15 #include <except.h> | |
16 #define __MODULE__ "DirectShow_VideoDecoder" | |
17 | |
1063 | 18 |
169 | 19 #include <errno.h> |
20 #ifdef HAVE_MALLOC_H | |
21 #include <malloc.h> | |
22 #endif | |
23 //#include <loader.h> | |
24 //#include <wine/winbase.h> | |
25 #include <stdio.h> | |
26 #include <unistd.h> | |
27 #include <fcntl.h> | |
28 #include <strstream> | |
29 #include <dlfcn.h> | |
30 #include <sys/types.h> | |
31 #include <sys/mman.h> | |
32 | |
173 | 33 #include <registry.h> |
34 #include <wine/winreg.h> | |
35 | |
169 | 36 #include "guids.h" |
37 #include "interfaces.h" | |
38 #include "DS_Filter.h" | |
39 | |
40 #include "BitmapInfo.h" | |
41 | |
42 #include <string> | |
43 #include <default.h> | |
44 | |
45 #include "DS_VideoDec.h" | |
46 | |
173 | 47 |
169 | 48 extern "C" char* def_path; |
49 | |
50 static char** m_destptr=0; | |
51 | |
52 static DS_Filter* dsf=0; | |
53 | |
54 static AM_MEDIA_TYPE m_sOurType, m_sDestType; | |
1525 | 55 static VIDEOINFOHEADER *m_sVhdr; |
169 | 56 static VIDEOINFOHEADER *m_sVhdr2; |
57 static void* m_pCust; | |
58 | |
1525 | 59 static BITMAPINFOHEADER *m_bh;//format of input data |
169 | 60 static BitmapInfo m_decoder;//format of decoder output |
61 static BitmapInfo m_obh; //format of returned frames | |
62 // CImage* m_outFrame; | |
63 | |
64 // int m_iState=0; | |
65 | |
66 extern "C" int DS_VideoDecoder_Open(char* dllname, GUID* guid, BITMAPINFOHEADER* format, int flip,char** d_ptr) | |
67 // :IVideoDecoder(info), m_sVhdr2(0) | |
68 { | |
69 | |
70 m_destptr=d_ptr; | |
71 | |
72 //m_outFrame=0; | |
73 //decpos = 0; | |
74 //playpos = 0; | |
75 //realtime = 0; | |
76 | |
77 try | |
78 { | |
1525 | 79 m_bh=format; |
169 | 80 memset(&m_obh, 0, sizeof(m_obh)); |
81 m_obh.biSize=sizeof(m_obh); | |
82 | |
1525 | 83 #if 0 |
713 | 84 memset(&m_sVhdr, 0, sizeof(m_sVhdr)); |
169 | 85 m_sVhdr.bmiHeader=m_bh; |
86 m_sVhdr.rcSource.left=m_sVhdr.rcSource.top=0; | |
87 m_sVhdr.rcSource.right=m_sVhdr.bmiHeader.biWidth; | |
88 m_sVhdr.rcSource.bottom=m_sVhdr.bmiHeader.biHeight; | |
89 m_sVhdr.rcTarget=m_sVhdr.rcSource; | |
1525 | 90 #else |
91 unsigned bihs = (format->biSize < (int) sizeof(BITMAPINFOHEADER)) ? | |
92 sizeof(BITMAPINFOHEADER) : format->biSize; | |
93 bihs = sizeof(VIDEOINFOHEADER) - sizeof(BITMAPINFOHEADER) + bihs; | |
169 | 94 |
1525 | 95 m_sVhdr = (VIDEOINFOHEADER*) new char[bihs]; |
96 memset(m_sVhdr, 0, bihs); | |
97 memcpy(&m_sVhdr->bmiHeader, m_bh, m_bh->biSize); | |
98 | |
99 m_sVhdr->rcSource.left = m_sVhdr->rcSource.top = 0; | |
100 m_sVhdr->rcSource.right = m_sVhdr->bmiHeader.biWidth; | |
101 m_sVhdr->rcSource.bottom = m_sVhdr->bmiHeader.biHeight; | |
102 m_sVhdr->rcTarget = m_sVhdr->rcSource; | |
103 #endif | |
104 m_sOurType.majortype=MEDIATYPE_Video; | |
169 | 105 m_sOurType.subtype=MEDIATYPE_Video; |
1525 | 106 m_sOurType.subtype.f1=m_sVhdr->bmiHeader.biCompression; |
169 | 107 m_sOurType.formattype=FORMAT_VideoInfo; |
108 m_sOurType.bFixedSizeSamples=false; | |
109 m_sOurType.bTemporalCompression=true; | |
110 m_sOurType.pUnk=0; | |
1525 | 111 // m_sOurType.cbFormat=sizeof(m_sVhdr); |
112 // m_sOurType.pbFormat=(char*)&m_sVhdr; | |
113 m_sOurType.cbFormat = bihs; | |
114 m_sOurType.pbFormat = (char*)m_sVhdr; | |
169 | 115 |
116 m_sVhdr2=(VIDEOINFOHEADER*)(new char[sizeof(VIDEOINFOHEADER)+12]); | |
1525 | 117 // *m_sVhdr2=m_sVhdr; |
118 memcpy(m_sVhdr2, m_sVhdr, sizeof(VIDEOINFOHEADER)+12); | |
169 | 119 m_sVhdr2->bmiHeader.biCompression=0; |
120 m_sVhdr2->bmiHeader.biBitCount=24; | |
121 | |
713 | 122 memset(&m_sDestType, 0, sizeof(m_sDestType)); |
169 | 123 m_sDestType.majortype=MEDIATYPE_Video; |
124 m_sDestType.subtype=MEDIASUBTYPE_RGB24; | |
125 m_sDestType.formattype=FORMAT_VideoInfo; | |
126 m_sDestType.bFixedSizeSamples=true; | |
127 m_sDestType.bTemporalCompression=false; | |
128 m_sDestType.lSampleSize=abs(m_sVhdr2->bmiHeader.biWidth*m_sVhdr2->bmiHeader.biHeight* | |
129 ((m_sVhdr2->bmiHeader.biBitCount+7)/8)); | |
130 m_sVhdr2->bmiHeader.biSizeImage=m_sDestType.lSampleSize; | |
131 m_sDestType.pUnk=0; | |
132 m_sDestType.cbFormat=sizeof(VIDEOINFOHEADER); | |
133 m_sDestType.pbFormat=(char*)m_sVhdr2; | |
1525 | 134 m_obh = *m_bh; |
169 | 135 m_obh.setBits(24); |
136 | |
137 HRESULT result; | |
138 | |
713 | 139 dsf=new DS_Filter(); |
140 dsf->Create(dllname, guid, &m_sOurType, &m_sDestType); | |
141 | |
169 | 142 if(!flip) |
143 { | |
144 m_sVhdr2->bmiHeader.biHeight*=-1; | |
145 m_obh.biHeight*=-1; | |
713 | 146 result=dsf->m_pOutputPin->vt->QueryAccept(dsf->m_pOutputPin, &m_sDestType); |
147 if(result){ | |
148 printf("DShow: Decoder does not support upside-down frames"); | |
149 m_obh.biHeight*=-1; | |
150 } | |
169 | 151 } |
152 | |
468 | 153 #if 0 |
169 | 154 m_sVhdr2->bmiHeader.biBitCount=16; |
155 m_sVhdr2->bmiHeader.biCompression=fccYUY2; | |
156 m_sDestType.subtype=MEDIASUBTYPE_YUY2; | |
157 result=dsf->m_pOutputPin->vt->QueryAccept(dsf->m_pOutputPin, &m_sDestType); | |
158 // if(!result) caps=(CAPS)(caps | CAP_YUY2); | |
468 | 159 #endif |
169 | 160 |
161 m_sVhdr2->bmiHeader.biBitCount=24; | |
162 m_sVhdr2->bmiHeader.biCompression=0; | |
163 m_sDestType.subtype=MEDIASUBTYPE_RGB24; | |
164 m_decoder=m_obh; | |
165 //qual = 0-1; | |
166 } | |
167 catch(FatalError& error) | |
168 { | |
169 delete[] m_sVhdr2; | |
170 return 1; | |
171 } | |
172 return 0; | |
173 } | |
174 | |
175 extern "C" void DS_VideoDecoder_Start(){ | |
176 if(dsf->m_iState!=1) return; | |
177 dsf->Start(); | |
178 | |
179 ALLOCATOR_PROPERTIES props, props1; | |
180 props.cBuffers=1; | |
181 props.cbBuffer=1024*1024; //m_sDestType.lSampleSize;//don't know how to do this correctly | |
182 props.cbAlign=props.cbPrefix=0; | |
183 dsf->m_pAll->vt->SetProperties(dsf->m_pAll, &props, &props1); | |
184 dsf->m_pAll->vt->Commit(dsf->m_pAll); | |
185 | |
186 // m_outFrame=new CImage(&m_decoder,(unsigned char *)malloc(m_sDestType.lSampleSize),false); | |
187 //m_outFrame=new CImage(&m_decoder, 0, false); | |
188 // printf("Datap %x\n",m_outFrame->getaddr()); | |
189 | |
190 | |
191 // dsf->m_pOurOutput->SetFramePointer((char **)m_outFrame->getaddr()); //!FIXME! | |
192 dsf->m_pOurOutput->SetFramePointer(m_destptr); //!FIXME! | |
193 | |
194 // filling = realtime; | |
195 | |
196 dsf->m_iState=2; | |
197 return; | |
198 } | |
199 | |
200 extern "C" void DS_VideoDecoder_Stop(){ | |
201 if(dsf->m_iState!=2) return; | |
202 dsf->Stop(); | |
713 | 203 // dsf->m_pOurOutput->SetFramePointer(0); |
169 | 204 // free(m_outFrame->data()); |
205 //m_outFrame->release();//just in case | |
206 //m_outFrame=0; | |
207 // FlushCache(); | |
208 dsf->m_iState=1; | |
209 return; | |
210 } | |
211 | |
212 extern "C" void DS_VideoDecoder_Restart(){ | |
213 if(dsf->m_iState!=2) return; | |
214 | |
215 dsf->Stop(); | |
216 dsf->Start(); | |
217 | |
218 ALLOCATOR_PROPERTIES props, props1; | |
219 props.cBuffers=1; | |
220 props.cbBuffer=m_sDestType.lSampleSize;//don't know how to do this correctly | |
221 props.cbAlign=props.cbPrefix=0; | |
222 dsf->m_pAll->vt->SetProperties(dsf->m_pAll, &props, &props1); | |
223 dsf->m_pAll->vt->Commit(dsf->m_pAll); | |
224 } | |
225 | |
226 extern "C" void DS_VideoDecoder_Close(){ | |
227 if(dsf->m_iState==0) return; | |
228 if(dsf->m_iState==2) DS_VideoDecoder_Stop(); | |
229 delete[] m_sVhdr2; | |
230 // delete m_outFrame; | |
231 } | |
232 | |
233 extern "C" int DS_VideoDecoder_DecodeFrame(char* src, int size, int is_keyframe, int render){ | |
234 | |
235 if(!size)return 0; | |
236 | |
1525 | 237 m_bh->biSizeImage=size; |
169 | 238 |
239 IMediaSample* sample=0; | |
173 | 240 //printf("GetBuffer... (m_pAll=%X) ",dsf->m_pAll);fflush(stdout); |
169 | 241 dsf->m_pAll->vt->GetBuffer(dsf->m_pAll, &sample, 0, 0, 0); |
173 | 242 //printf("OK!\n"); |
169 | 243 if(!sample) |
244 { | |
245 Debug cerr<<"ERROR: null sample"<<endl; | |
246 return -1; | |
247 } | |
248 char* ptr; | |
173 | 249 //printf("GetPtr...");fflush(stdout); |
169 | 250 sample->vt->GetPointer(sample, (BYTE **)&ptr); |
173 | 251 //printf("OK!\n"); |
169 | 252 memcpy(ptr, src, size); |
173 | 253 //printf("memcpy OK!\n"); |
169 | 254 sample->vt->SetActualDataLength(sample, size); |
173 | 255 //printf("SetActualDataLength OK!\n"); |
169 | 256 sample->vt->SetSyncPoint(sample, is_keyframe); |
173 | 257 //printf("SetSyncPoint OK!\n"); |
169 | 258 sample->vt->SetPreroll(sample, !render); |
259 // sample->vt->SetMediaType(sample, &m_sOurType); | |
260 int result=dsf->m_pImp->vt->Receive(dsf->m_pImp, sample); | |
261 if(result) | |
173 | 262 printf("Error putting data into input pin %x\n", result); |
169 | 263 |
264 sample->vt->Release((IUnknown*)sample); | |
265 | |
266 return 0; | |
267 } | |
268 | |
269 extern "C" int DS_VideoDecoder_SetDestFmt(int bits, int csp){ | |
270 if(dsf->m_iState==0) return -1; | |
271 // if(!CImage::supported(csp, bits)) return -1; | |
272 HRESULT result; | |
273 // BitmapInfo temp=m_obh; | |
274 if(csp==0) | |
275 { | |
276 switch(bits) | |
277 { | |
278 case 15: | |
279 m_sDestType.subtype=MEDIASUBTYPE_RGB555; | |
280 break; | |
281 case 16: | |
282 m_sDestType.subtype=MEDIASUBTYPE_RGB565; | |
283 break; | |
284 case 24: | |
285 m_sDestType.subtype=MEDIASUBTYPE_RGB24; | |
286 break; | |
287 case 32: | |
288 m_sDestType.subtype=MEDIASUBTYPE_RGB32; | |
289 break; | |
290 default: | |
291 break; | |
292 } | |
293 m_obh.setBits(bits); | |
294 // .biSizeImage=abs(temp.biWidth*temp.biHeight*((temp.biBitCount+7)/8)); | |
295 } | |
296 else | |
297 { | |
468 | 298 m_obh.setSpace(csp,bits); |
169 | 299 switch(csp) |
300 { | |
301 case fccYUY2: | |
302 m_sDestType.subtype=MEDIASUBTYPE_YUY2; | |
468 | 303 printf("DShow: using YUY2 colorspace\n"); |
169 | 304 break; |
305 case fccYV12: | |
306 m_sDestType.subtype=MEDIASUBTYPE_YV12; | |
468 | 307 printf("DShow: using YV12 colorspace\n"); |
169 | 308 break; |
309 case fccIYUV: | |
310 m_sDestType.subtype=MEDIASUBTYPE_IYUV; | |
468 | 311 printf("DShow: using IYUV colorspace\n"); |
169 | 312 break; |
313 case fccUYVY: | |
314 m_sDestType.subtype=MEDIASUBTYPE_UYVY; | |
468 | 315 printf("DShow: using UYVY colorspace\n"); |
169 | 316 break; |
317 case fccYVYU: | |
318 m_sDestType.subtype=MEDIASUBTYPE_YVYU; | |
468 | 319 printf("DShow: using YVYU colorspace\n"); |
169 | 320 break; |
321 } | |
322 } | |
323 | |
324 m_sDestType.lSampleSize=m_obh.biSizeImage; | |
325 memcpy(&(m_sVhdr2->bmiHeader), &m_obh, sizeof(m_obh)); | |
326 m_sVhdr2->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); | |
327 if(m_sVhdr2->bmiHeader.biCompression==3) | |
328 m_sDestType.cbFormat=sizeof(VIDEOINFOHEADER)+12; | |
329 else | |
330 m_sDestType.cbFormat=sizeof(VIDEOINFOHEADER); | |
331 | |
332 result=dsf->m_pOutputPin->vt->QueryAccept(dsf->m_pOutputPin, &m_sDestType); | |
333 | |
334 if(result!=0) | |
335 { | |
336 if(csp) | |
337 cerr<<"Warning: unsupported color space"<<endl; | |
338 else | |
339 cerr<<"Warning: unsupported bit depth"<<endl; | |
340 | |
341 m_sDestType.lSampleSize=m_decoder.biSizeImage; | |
342 memcpy(&(m_sVhdr2->bmiHeader), &m_decoder, sizeof(m_decoder)); | |
343 m_sVhdr2->bmiHeader.biSize=sizeof(BITMAPINFOHEADER); | |
344 if(m_sVhdr2->bmiHeader.biCompression==3) | |
345 m_sDestType.cbFormat=sizeof(VIDEOINFOHEADER)+12; | |
346 else | |
347 m_sDestType.cbFormat=sizeof(VIDEOINFOHEADER); | |
348 return 1; | |
349 } | |
350 | |
351 m_decoder=m_obh; | |
352 // m_obh=temp; | |
353 // if(csp) | |
354 // m_obh.biBitCount=BitmapInfo::BitCount(csp); | |
1525 | 355 m_bh->biBitCount=bits; |
169 | 356 if(dsf->m_iState>0) |
357 { | |
358 int old_state=dsf->m_iState; | |
359 if(dsf->m_iState==2) DS_VideoDecoder_Stop(); | |
360 dsf->m_pInputPin->vt->Disconnect(dsf->m_pInputPin); | |
361 dsf->m_pOutputPin->vt->Disconnect(dsf->m_pOutputPin); | |
362 dsf->m_pOurOutput->SetNewFormat(m_sDestType); | |
363 result=dsf->m_pInputPin->vt->ReceiveConnection(dsf->m_pInputPin, dsf->m_pOurInput, &m_sOurType); | |
364 if(result) | |
365 { | |
366 cerr<<"Error reconnecting input pin "<<hex<<result<<dec<<endl; | |
367 return -1; | |
368 } | |
369 result=dsf->m_pOutputPin->vt->ReceiveConnection(dsf->m_pOutputPin, | |
370 dsf->m_pOurOutput, &m_sDestType); | |
371 if(result) | |
372 { | |
373 cerr<<"Error reconnecting output pin "<<hex<<result<<dec<<endl; | |
374 return -1; | |
375 } | |
376 if(old_state==2) DS_VideoDecoder_Start(); | |
377 } | |
378 return 0; | |
379 } | |
380 | |
381 | |
382 extern "C" int DS_SetValue_DivX(char* name, int value){ | |
383 int temp; | |
384 if(dsf->m_iState!=2) return VFW_E_NOT_RUNNING; | |
385 // brightness 87 | |
386 // contrast 74 | |
387 // hue 23 | |
388 // saturation 20 | |
389 // post process mode 0 | |
390 // get1 0x01 | |
391 // get2 10 | |
392 // get3=set2 86 | |
393 // get4=set3 73 | |
394 // get5=set4 19 | |
395 // get6=set5 23 | |
1440 | 396 // printf("DivX setting: %s = %d\n",name,value); |
169 | 397 |
398 IHidden* hidden=(IHidden*)((int)dsf->m_pFilter+0xb8); | |
399 if(strcmp(name, "Brightness")==0) | |
400 return hidden->vt->SetSmth2(hidden, value, 0); | |
401 if(strcmp(name, "Contrast")==0) | |
402 return hidden->vt->SetSmth3(hidden, value, 0); | |
403 if(strcmp(name, "Hue")==0) | |
404 return hidden->vt->SetSmth5(hidden, value, 0); | |
405 if(strcmp(name, "Saturation")==0) | |
406 return hidden->vt->SetSmth4(hidden, value, 0); | |
407 if(strcmp(name, "Quality")==0) | |
408 return hidden->vt->SetSmth(hidden, value, 0); | |
409 | |
410 printf("Invalid setting!\n"); | |
411 return -200; | |
412 } | |
413 | |
173 | 414 extern "C" int DS_SetAttr_DivX(char* attribute, int value){ |
415 int result, status, newkey, count; | |
416 if(strcmp(attribute, "Quality")==0){ | |
417 char* keyname="SOFTWARE\\Microsoft\\Scrunch"; | |
418 result=RegCreateKeyExA(HKEY_CURRENT_USER, keyname, 0, 0, 0, 0, 0, &newkey, &status); | |
419 if(result!=0) | |
420 { | |
421 printf("VideoDecoder::SetExtAttr: registry failure\n"); | |
422 return -1; | |
423 } | |
424 result=RegSetValueExA(newkey, "Current Post Process Mode", 0, REG_DWORD, &value, 4); | |
425 if(result!=0) | |
426 { | |
427 printf("VideoDecoder::SetExtAttr: error writing value\n"); | |
428 return -1; | |
429 } | |
430 value=-1; | |
431 result=RegSetValueExA(newkey, "Force Post Process Mode", 0, REG_DWORD, &value, 4); | |
432 if(result!=0) | |
433 { | |
434 printf("VideoDecoder::SetExtAttr: error writing value\n"); | |
435 return -1; | |
436 } | |
437 RegCloseKey(newkey); | |
438 return 0; | |
439 } | |
169 | 440 |
173 | 441 if( |
442 (strcmp(attribute, "Saturation")==0) || | |
443 (strcmp(attribute, "Hue")==0) || | |
444 (strcmp(attribute, "Contrast")==0) || | |
445 (strcmp(attribute, "Brightness")==0) | |
446 ) | |
447 { | |
448 char* keyname="SOFTWARE\\Microsoft\\Scrunch\\Video"; | |
449 result=RegCreateKeyExA(HKEY_CURRENT_USER, keyname, 0, 0, 0, 0, 0, &newkey, &status); | |
450 if(result!=0) | |
451 { | |
452 printf("VideoDecoder::SetExtAttr: registry failure\n"); | |
453 return -1; | |
454 } | |
455 result=RegSetValueExA(newkey, attribute, 0, REG_DWORD, &value, 4); | |
456 if(result!=0) | |
457 { | |
458 printf("VideoDecoder::SetExtAttr: error writing value\n"); | |
459 return -1; | |
460 } | |
461 RegCloseKey(newkey); | |
462 return 0; | |
463 } | |
464 | |
465 printf("Unknown attribute!\n"); | |
466 return -200; | |
467 } | |
468 |