2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "vd_internal.h"
27 #include "libmpdemux/aviprint.h"
28 #include "loader/wine/driver.h"
29 #include "loader/wine/vfw.h"
31 static const vd_info_t info
= {
33 "Win32/VfWex video codecs",
36 "Win32/VfW video codecs",
51 BITMAPINFOHEADER
*o_bih
;
53 unsigned char *palette
;
56 static int vfw_set_postproc(sh_video_t
* sh
, int quality
)
58 vd_vfw_ctx
*priv
= sh
->context
;
59 // Works only with opendivx/divx4 based DLL
60 return ICSendMessage(priv
->handle
, ICM_USER
+80, (long)(&quality
), 0);
63 static void set_csp(BITMAPINFOHEADER
*o_bih
,unsigned int outfmt
){
100 o_bih
->biBitCount
=24;
104 o_bih
->biBitCount
=32;
107 mp_msg(MSGT_WIN32
,MSGL_ERR
,"Unsupported image format: %s\n", vo_format_name(outfmt
));
111 o_bih
->biSizeImage
= abs(o_bih
->biWidth
* o_bih
->biHeight
* (o_bih
->biBitCount
/8));
113 // Note: we cannot rely on sh->outfmtidx here, it's undefined at this stage!!!
114 // if (yuv && !(sh->codec->outflags[sh->outfmtidx] & CODECS_FLAG_YUVHACK))
116 o_bih
->biCompression
= outfmt
;
118 o_bih
->biCompression
= 0;
121 // to set/get/query special features/parameters
122 static int control(sh_video_t
*sh
,int cmd
,void* arg
,...){
123 vd_vfw_ctx
*priv
= sh
->context
;
125 case VDCTRL_QUERY_MAX_PP_LEVEL
:
127 case VDCTRL_SET_PP_LEVEL
:
128 vfw_set_postproc(sh
,10*(*((int*)arg
)));
130 // FIXME: make this optional...
131 case VDCTRL_QUERY_FORMAT
:
134 if(!(sh
->codec
->outflags
[sh
->outfmtidx
]&CODECS_FLAG_QUERY
))
135 return CONTROL_UNKNOWN
; // do not query!
136 set_csp(priv
->o_bih
,*((int*)arg
));
138 ret
= ICDecompressQueryEx(priv
->handle
, sh
->bih
, priv
->o_bih
);
140 ret
= ICDecompressQuery(priv
->handle
, sh
->bih
, priv
->o_bih
);
144 mp_msg(MSGT_WIN32
, MSGL_DBG2
, "ICDecompressQuery failed:: Error %d\n", (int)ret
);
145 return CONTROL_FALSE
;
150 return CONTROL_UNKNOWN
;
154 static int init(sh_video_t
*sh
){
156 // unsigned int outfmt=sh->codec->outfmt[sh->outfmtidx];
160 /* Hack for VSSH codec: new dll can't decode old files
161 * In my samples old files have no extradata, so use that info
162 * to decide what dll should be used (here and in vd_dshow).
164 if (!strcmp(sh
->codec
->dll
, "vssh264.dll") && (sh
->bih
->biSize
> 40))
167 priv
= malloc(sizeof(vd_vfw_ctx
));
170 memset(priv
, 0, sizeof(vd_vfw_ctx
));
173 mp_msg(MSGT_WIN32
,MSGL_V
,"======= Win32 (VFW) VIDEO Codec init =======\n");
176 // win32_codec_name = sh->codec->dll;
177 // sh->hic = ICOpen( 0x63646976, sh->bih->biCompression, ICMODE_FASTDECOMPRESS);
178 // priv->handle = ICOpen( 0x63646976, sh->bih->biCompression, ICMODE_DECOMPRESS);
179 priv
->handle
= ICOpen( (long)(sh
->codec
->dll
), sh
->bih
->biCompression
, ICMODE_DECOMPRESS
);
181 mp_msg(MSGT_WIN32
,MSGL_ERR
,"ICOpen failed! unknown codec / wrong parameters?\n");
185 // sh->bih->biBitCount=32;
187 o_bih_len
= ICDecompressGetFormatSize(priv
->handle
, sh
->bih
);
189 if(o_bih_len
< sizeof(BITMAPINFOHEADER
)){
190 mp_msg(MSGT_WIN32
,MSGL_ERR
,"ICDecompressGetFormatSize returned a bogus value: %d\n", o_bih_len
);
194 priv
->o_bih
= malloc(o_bih_len
);
195 memset(priv
->o_bih
, 0, o_bih_len
);
197 mp_msg(MSGT_WIN32
,MSGL_V
,"ICDecompressGetFormatSize ret: %d\n", o_bih_len
);
199 ret
= ICDecompressGetFormat(priv
->handle
, sh
->bih
, priv
->o_bih
);
201 mp_msg(MSGT_WIN32
,MSGL_ERR
,"ICDecompressGetFormat failed: Error %d\n", (int)ret
);
202 for (i
=0; i
< o_bih_len
; i
++) mp_msg(MSGT_WIN32
, MSGL_DBG2
, "%02x ", priv
->o_bih
[i
]);
205 mp_msg(MSGT_WIN32
,MSGL_V
,"ICDecompressGetFormat OK\n");
208 // workaround for pegasus MJPEG:
209 if(!sh_video
->o_bih
.biWidth
) sh_video
->o_bih
.biWidth
=sh_video
->bih
->biWidth
;
210 if(!sh_video
->o_bih
.biHeight
) sh_video
->o_bih
.biHeight
=sh_video
->bih
->biHeight
;
211 if(!sh_video
->o_bih
.biPlanes
) sh_video
->o_bih
.biPlanes
=sh_video
->bih
->biPlanes
;
214 // ok let libvo and vd core to handshake and decide the optimal csp:
215 if(!mpcodecs_config_vo(sh
,sh
->disp_w
,sh
->disp_h
,IMGFMT_YUY2
)) return 0;
217 if (!(sh
->codec
->outflags
[sh
->outfmtidx
]&CODECS_FLAG_FLIP
)) {
218 priv
->o_bih
->biHeight
=-sh
->bih
->biHeight
; // flip image!
221 // ok, let's set the choosen colorspace:
222 set_csp(priv
->o_bih
,sh
->codec
->outfmt
[sh
->outfmtidx
]);
224 // fake it to RGB for broken DLLs (divx3)
225 if(sh
->codec
->outflags
[sh
->outfmtidx
] & CODECS_FLAG_YUVHACK
)
226 priv
->o_bih
->biCompression
= 0;
230 ret
= ICDecompressQueryEx(priv
->handle
, sh
->bih
, priv
->o_bih
);
232 ret
= ICDecompressQuery(priv
->handle
, sh
->bih
, priv
->o_bih
);
236 mp_msg(MSGT_WIN32
,MSGL_WARN
,"ICDecompressQuery failed: Error %d\n", (int)ret
);
239 mp_msg(MSGT_WIN32
,MSGL_V
,"ICDecompressQuery OK\n");
242 ret
= ICDecompressBeginEx(priv
->handle
, sh
->bih
, priv
->o_bih
);
244 ret
= ICDecompressBegin(priv
->handle
, sh
->bih
, priv
->o_bih
);
248 mp_msg(MSGT_WIN32
,MSGL_WARN
,"ICDecompressBegin failed: Error %d\n", (int)ret
);
252 // for broken codecs set it again:
253 if(sh
->codec
->outflags
[sh
->outfmtidx
] & CODECS_FLAG_YUVHACK
)
254 set_csp(priv
->o_bih
,sh
->codec
->outfmt
[sh
->outfmtidx
]);
256 mp_msg(MSGT_WIN32
, MSGL_V
, "Input format:\n");
257 if( mp_msg_test(MSGT_HEADER
,MSGL_V
) ) print_video_header(sh
->bih
,MSGL_V
);
258 mp_msg(MSGT_WIN32
, MSGL_V
, "Output format:\n");
259 if( mp_msg_test(MSGT_HEADER
,MSGL_V
) ) print_video_header(priv
->o_bih
,MSGL_V
);
261 // set postprocessing level in xvid/divx4 .dll
262 ICSendMessage(priv
->handle
, ICM_USER
+80, (long)(&divx_quality
), 0);
264 // don't do this palette mess always, it makes div3 dll crashing...
265 if(sh
->codec
->outfmt
[sh
->outfmtidx
]==IMGFMT_BGR8
){
266 if(ICDecompressGetPalette(priv
->handle
, sh
->bih
, priv
->o_bih
)){
267 priv
->palette
= (unsigned char*)(priv
->o_bih
+1);
268 mp_msg(MSGT_WIN32
,MSGL_V
,"ICDecompressGetPalette OK\n");
270 if(sh
->bih
->biSize
>=40+4*4)
271 priv
->palette
= (unsigned char*)(sh
->bih
+1);
275 mp_msg(MSGT_DECVIDEO
,MSGL_V
,"INFO: Win32 video codec init OK!\n");
280 static void uninit(sh_video_t
*sh
){
282 vd_vfw_ctx
*priv
= sh
->context
;
285 ret
= ICDecompressEndEx(priv
->handle
);
287 ret
= ICDecompressEnd(priv
->handle
);
291 mp_msg(MSGT_WIN32
, MSGL_WARN
, "ICDecompressEnd failed: %ld\n", ret
);
295 ret
= ICClose(priv
->handle
);
298 mp_msg(MSGT_WIN32
, MSGL_WARN
, "ICClose failed: %ld\n", ret
);
307 static mp_image_t
* decode(sh_video_t
*sh
,void* data
,int len
,int flags
){
308 vd_vfw_ctx
*priv
= sh
->context
;
312 if(len
<=0) return NULL
; // skipped frame
314 mpi
=mpcodecs_get_image(sh
,
315 (sh
->codec
->outflags
[sh
->outfmtidx
] & CODECS_FLAG_STATIC
) ?
316 MP_IMGTYPE_STATIC
: MP_IMGTYPE_TEMP
, MP_IMGFLAG_ACCEPT_WIDTH
,
317 sh
->disp_w
, sh
->disp_h
);
318 if(!mpi
){ // temporary!
319 mp_msg(MSGT_DECVIDEO
,MSGL_WARN
,MSGTR_MPCODECS_CouldntAllocateImageForCinepakCodec
);
323 // set stride: (trick discovered by Andreas Ackermann - thanx!)
324 sh
->bih
->biWidth
=mpi
->width
; //mpi->stride[0]/(mpi->bpp/8);
325 priv
->o_bih
->biWidth
=mpi
->width
; //mpi->stride[0]/(mpi->bpp/8);
327 sh
->bih
->biSizeImage
= len
;
330 ret
= ICDecompressEx(priv
->handle
,
332 ret
= ICDecompress(priv
->handle
,
334 ( (sh
->ds
->flags
&1) ? 0 : ICDECOMPRESS_NOTKEYFRAME
) |
335 ( ((flags
&3)==2 && !(sh
->ds
->flags
&1))?(ICDECOMPRESS_HURRYUP
|ICDECOMPRESS_PREROL
):0 ),
336 sh
->bih
, data
, priv
->o_bih
, (flags
&3) ? 0 : mpi
->planes
[0]);
339 mp_msg(MSGT_DECVIDEO
,MSGL_WARN
,"Error decompressing frame, err=%ld\n",ret
);
344 if(mpi
->imgfmt
==IMGFMT_RGB8
|| mpi
->imgfmt
==IMGFMT_BGR8
){
347 mpi
->planes
[1] = priv
->palette
;
348 mp_dbg(MSGT_DECVIDEO
, MSGL_DBG2
, "Found and copied palette\n");