~ubuntu-branches/ubuntu/oneiric/mplayer2/oneiric-proposed

« back to all changes in this revision

Viewing changes to mplayer/libmpcodecs/vd_vfw.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2011-03-20 22:48:03 UTC
  • Revision ID: james.westby@ubuntu.com-20110320224803-kc2nlrxz6pcphmf1
Tags: upstream-2.0~rc2
ImportĀ upstreamĀ versionĀ 2.0~rc2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of MPlayer.
 
3
 *
 
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.
 
8
 *
 
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.
 
13
 *
 
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.
 
17
 */
 
18
 
 
19
#include <stdio.h>
 
20
#include <stdlib.h>
 
21
 
 
22
#include "config.h"
 
23
#include "mp_msg.h"
 
24
 
 
25
#include "vd_internal.h"
 
26
#include "libmpdemux/aviprint.h"
 
27
#include "loader/wine/driver.h"
 
28
#include "loader/wine/vfw.h"
 
29
 
 
30
static const vd_info_t info = {
 
31
#ifdef BUILD_VFWEX
 
32
        "Win32/VfWex video codecs",
 
33
        "vfwex",
 
34
#else
 
35
        "Win32/VfW video codecs",
 
36
        "vfw",
 
37
#endif
 
38
        "A'rpi & Alex",
 
39
        "avifile.sf.net",
 
40
        "win32 codecs"
 
41
};
 
42
 
 
43
#ifdef BUILD_VFWEX
 
44
LIBVD_EXTERN(vfwex)
 
45
#else
 
46
LIBVD_EXTERN(vfw)
 
47
#endif
 
48
 
 
49
typedef struct {
 
50
    BITMAPINFOHEADER *o_bih;
 
51
    HIC handle;
 
52
    unsigned char *palette;
 
53
} vd_vfw_ctx;
 
54
 
 
55
static int vfw_set_postproc(sh_video_t* sh, int quality)
 
56
{
 
57
    vd_vfw_ctx *priv = sh->context;
 
58
    // Works only with opendivx/divx4 based DLL
 
59
    return ICSendMessage(priv->handle, ICM_USER+80, (long)(&quality), 0);
 
60
}
 
61
 
 
62
static void set_csp(BITMAPINFOHEADER *o_bih,unsigned int outfmt){
 
63
    int yuv = 0;
 
64
 
 
65
        switch (outfmt)
 
66
        {
 
67
        /* planar format */
 
68
        case IMGFMT_YV12:
 
69
        case IMGFMT_I420:
 
70
        case IMGFMT_IYUV:
 
71
            o_bih->biBitCount=12;
 
72
            yuv=1;
 
73
            break;
 
74
        case IMGFMT_YVU9:
 
75
        case IMGFMT_IF09:
 
76
            o_bih->biBitCount=9;
 
77
            yuv=1;
 
78
            break;
 
79
        /* packed format */
 
80
        case IMGFMT_YUY2:
 
81
        case IMGFMT_UYVY:
 
82
        case IMGFMT_YVYU:
 
83
            o_bih->biBitCount=16;
 
84
            yuv=1;
 
85
            break;
 
86
        /* rgb/bgr format */
 
87
        case IMGFMT_RGB8:
 
88
        case IMGFMT_BGR8:
 
89
            o_bih->biBitCount=8;
 
90
            break;
 
91
        case IMGFMT_RGB15:
 
92
        case IMGFMT_RGB16:
 
93
        case IMGFMT_BGR15:
 
94
        case IMGFMT_BGR16:
 
95
            o_bih->biBitCount=16;
 
96
            break;
 
97
        case IMGFMT_RGB24:
 
98
        case IMGFMT_BGR24:
 
99
            o_bih->biBitCount=24;
 
100
            break;
 
101
        case IMGFMT_RGB32:
 
102
        case IMGFMT_BGR32:
 
103
            o_bih->biBitCount=32;
 
104
            break;
 
105
        default:
 
106
            mp_msg(MSGT_WIN32,MSGL_ERR,"Unsupported image format: %s\n", vo_format_name(outfmt));
 
107
            return;
 
108
        }
 
109
 
 
110
        o_bih->biSizeImage = abs(o_bih->biWidth * o_bih->biHeight * (o_bih->biBitCount/8));
 
111
 
 
112
// Note: we cannot rely on sh->outfmtidx here, it's undefined at this stage!!!
 
113
//      if (yuv && !(sh->codec->outflags[sh->outfmtidx] & CODECS_FLAG_YUVHACK))
 
114
        if (yuv)
 
115
            o_bih->biCompression = outfmt;
 
116
        else
 
117
            o_bih->biCompression = 0;
 
118
}
 
119
 
 
120
// to set/get/query special features/parameters
 
121
static int control(sh_video_t *sh,int cmd,void* arg,...){
 
122
    vd_vfw_ctx *priv = sh->context;
 
123
    switch(cmd){
 
124
    case VDCTRL_QUERY_MAX_PP_LEVEL:
 
125
        return 9;
 
126
    case VDCTRL_SET_PP_LEVEL:
 
127
        vfw_set_postproc(sh,10*(*((int*)arg)));
 
128
        return CONTROL_OK;
 
129
    // FIXME: make this optional...
 
130
    case VDCTRL_QUERY_FORMAT:
 
131
      {
 
132
        HRESULT ret;
 
133
        if(!(sh->codec->outflags[sh->outfmtidx]&CODECS_FLAG_QUERY))
 
134
            return CONTROL_UNKNOWN;     // do not query!
 
135
        set_csp(priv->o_bih,*((int*)arg));
 
136
#ifdef BUILD_VFWEX
 
137
        ret = ICDecompressQueryEx(priv->handle, sh->bih, priv->o_bih);
 
138
#else
 
139
        ret = ICDecompressQuery(priv->handle, sh->bih, priv->o_bih);
 
140
#endif
 
141
        if (ret)
 
142
        {
 
143
            mp_msg(MSGT_WIN32, MSGL_DBG2, "ICDecompressQuery failed:: Error %d\n", (int)ret);
 
144
            return CONTROL_FALSE;
 
145
        }
 
146
        return CONTROL_TRUE;
 
147
      }
 
148
    }
 
149
    return CONTROL_UNKNOWN;
 
150
}
 
151
 
 
152
// init driver
 
153
static int init(sh_video_t *sh){
 
154
    HRESULT ret;
 
155
//    unsigned int outfmt=sh->codec->outfmt[sh->outfmtidx];
 
156
    int i, o_bih_len;
 
157
    vd_vfw_ctx *priv;
 
158
 
 
159
    /* Hack for VSSH codec: new dll can't decode old files
 
160
     * In my samples old files have no extradata, so use that info
 
161
     * to decide what dll should be used (here and in vd_dshow).
 
162
     */
 
163
    if (!strcmp(sh->codec->dll, "vssh264.dll") && (sh->bih->biSize > 40))
 
164
      return 0;
 
165
 
 
166
    priv = malloc(sizeof(vd_vfw_ctx));
 
167
    if (!priv)
 
168
        return 0;
 
169
    memset(priv, 0, sizeof(vd_vfw_ctx));
 
170
    sh->context = priv;
 
171
 
 
172
    mp_msg(MSGT_WIN32,MSGL_V,"======= Win32 (VFW) VIDEO Codec init =======\n");
 
173
 
 
174
 
 
175
//    win32_codec_name = sh->codec->dll;
 
176
//    sh->hic = ICOpen( 0x63646976, sh->bih->biCompression, ICMODE_FASTDECOMPRESS);
 
177
//    priv->handle = ICOpen( 0x63646976, sh->bih->biCompression, ICMODE_DECOMPRESS);
 
178
    priv->handle = ICOpen( (long)(sh->codec->dll), sh->bih->biCompression, ICMODE_DECOMPRESS);
 
179
    if(!priv->handle){
 
180
        mp_msg(MSGT_WIN32,MSGL_ERR,"ICOpen failed! unknown codec / wrong parameters?\n");
 
181
        return 0;
 
182
    }
 
183
 
 
184
//    sh->bih->biBitCount=32;
 
185
 
 
186
    o_bih_len = ICDecompressGetFormatSize(priv->handle, sh->bih);
 
187
 
 
188
    if(o_bih_len < sizeof(BITMAPINFOHEADER)){
 
189
       mp_msg(MSGT_WIN32,MSGL_ERR,"ICDecompressGetFormatSize returned a bogus value: %d\n", o_bih_len);
 
190
       return 0;
 
191
    }
 
192
 
 
193
    priv->o_bih = malloc(o_bih_len);
 
194
    memset(priv->o_bih, 0, o_bih_len);
 
195
 
 
196
    mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressGetFormatSize ret: %d\n", o_bih_len);
 
197
 
 
198
    ret = ICDecompressGetFormat(priv->handle, sh->bih, priv->o_bih);
 
199
    if(ret < 0){
 
200
        mp_msg(MSGT_WIN32,MSGL_ERR,"ICDecompressGetFormat failed: Error %d\n", (int)ret);
 
201
        for (i=0; i < o_bih_len; i++) mp_msg(MSGT_WIN32, MSGL_DBG2, "%02x ", priv->o_bih[i]);
 
202
        return 0;
 
203
    }
 
204
    mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressGetFormat OK\n");
 
205
 
 
206
#if 0
 
207
    // workaround for pegasus MJPEG:
 
208
    if(!sh_video->o_bih.biWidth) sh_video->o_bih.biWidth=sh_video->bih->biWidth;
 
209
    if(!sh_video->o_bih.biHeight) sh_video->o_bih.biHeight=sh_video->bih->biHeight;
 
210
    if(!sh_video->o_bih.biPlanes) sh_video->o_bih.biPlanes=sh_video->bih->biPlanes;
 
211
#endif
 
212
 
 
213
    // ok let libvo and vd core to handshake and decide the optimal csp:
 
214
    if(!mpcodecs_config_vo(sh,sh->disp_w,sh->disp_h,IMGFMT_YUY2)) return 0;
 
215
 
 
216
    if (!(sh->codec->outflags[sh->outfmtidx]&CODECS_FLAG_FLIP)) {
 
217
        priv->o_bih->biHeight=-sh->bih->biHeight; // flip image!
 
218
    }
 
219
 
 
220
    // ok, let's set the choosen colorspace:
 
221
    set_csp(priv->o_bih,sh->codec->outfmt[sh->outfmtidx]);
 
222
 
 
223
    // fake it to RGB for broken DLLs (divx3)
 
224
    if(sh->codec->outflags[sh->outfmtidx] & CODECS_FLAG_YUVHACK)
 
225
        priv->o_bih->biCompression = 0;
 
226
 
 
227
    // sanity check:
 
228
#ifdef BUILD_VFWEX
 
229
    ret = ICDecompressQueryEx(priv->handle, sh->bih, priv->o_bih);
 
230
#else
 
231
    ret = ICDecompressQuery(priv->handle, sh->bih, priv->o_bih);
 
232
#endif
 
233
    if (ret)
 
234
    {
 
235
        mp_msg(MSGT_WIN32,MSGL_WARN,"ICDecompressQuery failed: Error %d\n", (int)ret);
 
236
//      return 0;
 
237
    } else
 
238
        mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressQuery OK\n");
 
239
 
 
240
#ifdef BUILD_VFWEX
 
241
    ret = ICDecompressBeginEx(priv->handle, sh->bih, priv->o_bih);
 
242
#else
 
243
    ret = ICDecompressBegin(priv->handle, sh->bih, priv->o_bih);
 
244
#endif
 
245
    if (ret)
 
246
    {
 
247
        mp_msg(MSGT_WIN32,MSGL_WARN,"ICDecompressBegin failed: Error %d\n", (int)ret);
 
248
//      return 0;
 
249
    }
 
250
 
 
251
    // for broken codecs set it again:
 
252
    if(sh->codec->outflags[sh->outfmtidx] & CODECS_FLAG_YUVHACK)
 
253
        set_csp(priv->o_bih,sh->codec->outfmt[sh->outfmtidx]);
 
254
 
 
255
    mp_msg(MSGT_WIN32, MSGL_V, "Input format:\n");
 
256
    if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(sh->bih,MSGL_V);
 
257
    mp_msg(MSGT_WIN32, MSGL_V, "Output format:\n");
 
258
    if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_video_header(priv->o_bih,MSGL_V);
 
259
 
 
260
    // set postprocessing level in xvid/divx4 .dll
 
261
    ICSendMessage(priv->handle, ICM_USER+80, (long)(&divx_quality), 0);
 
262
 
 
263
    // don't do this palette mess always, it makes div3 dll crashing...
 
264
    if(sh->codec->outfmt[sh->outfmtidx]==IMGFMT_BGR8){
 
265
        if(ICDecompressGetPalette(priv->handle, sh->bih, priv->o_bih)){
 
266
            priv->palette = (unsigned char*)(priv->o_bih+1);
 
267
            mp_msg(MSGT_WIN32,MSGL_V,"ICDecompressGetPalette OK\n");
 
268
        } else {
 
269
            if(sh->bih->biSize>=40+4*4)
 
270
                priv->palette = (unsigned char*)(sh->bih+1);
 
271
        }
 
272
    }
 
273
 
 
274
    mp_msg(MSGT_DECVIDEO,MSGL_V,"INFO: Win32 video codec init OK!\n");
 
275
    return 1;
 
276
}
 
277
 
 
278
// uninit driver
 
279
static void uninit(sh_video_t *sh){
 
280
    HRESULT ret;
 
281
    vd_vfw_ctx *priv = sh->context;
 
282
 
 
283
#ifdef BUILD_VFWEX
 
284
    ret = ICDecompressEndEx(priv->handle);
 
285
#else
 
286
    ret = ICDecompressEnd(priv->handle);
 
287
#endif
 
288
    if (ret)
 
289
    {
 
290
        mp_msg(MSGT_WIN32, MSGL_WARN, "ICDecompressEnd failed: %ld\n", ret);
 
291
        return;
 
292
    }
 
293
 
 
294
    ret = ICClose(priv->handle);
 
295
    if (ret)
 
296
    {
 
297
        mp_msg(MSGT_WIN32, MSGL_WARN, "ICClose failed: %ld\n", ret);
 
298
        return;
 
299
    }
 
300
 
 
301
    free(priv->o_bih);
 
302
    free(priv);
 
303
}
 
304
 
 
305
// decode a frame
 
306
static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){
 
307
    vd_vfw_ctx *priv = sh->context;
 
308
    mp_image_t* mpi;
 
309
    HRESULT ret;
 
310
 
 
311
    if(len<=0) return NULL; // skipped frame
 
312
 
 
313
    mpi=mpcodecs_get_image(sh,
 
314
        (sh->codec->outflags[sh->outfmtidx] & CODECS_FLAG_STATIC) ?
 
315
        MP_IMGTYPE_STATIC : MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_WIDTH,
 
316
        sh->disp_w, sh->disp_h);
 
317
    if(!mpi){   // temporary!
 
318
        mp_tmsg(MSGT_DECVIDEO,MSGL_WARN,"[VD_DMO] Couldn't allocate image for cinepak codec.\n");
 
319
        return NULL;
 
320
    }
 
321
 
 
322
    // set stride:  (trick discovered by Andreas Ackermann - thanx!)
 
323
    sh->bih->biWidth=mpi->width; //mpi->stride[0]/(mpi->bpp/8);
 
324
    priv->o_bih->biWidth=mpi->width; //mpi->stride[0]/(mpi->bpp/8);
 
325
 
 
326
    sh->bih->biSizeImage = len;
 
327
 
 
328
#ifdef BUILD_VFWEX
 
329
    ret = ICDecompressEx(priv->handle,
 
330
#else
 
331
    ret = ICDecompress(priv->handle,
 
332
#endif
 
333
          ( (sh->ds->flags&1) ? 0 : ICDECOMPRESS_NOTKEYFRAME ) |
 
334
          ( ((flags&3)==2 && !(sh->ds->flags&1))?(ICDECOMPRESS_HURRYUP|ICDECOMPRESS_PREROL):0 ),
 
335
           sh->bih, data, priv->o_bih, (flags&3) ? 0 : mpi->planes[0]);
 
336
 
 
337
    if ((int)ret){
 
338
      mp_msg(MSGT_DECVIDEO,MSGL_WARN,"Error decompressing frame, err=%ld\n",ret);
 
339
      return NULL;
 
340
    }
 
341
 
 
342
    // export palette:
 
343
    if(mpi->imgfmt==IMGFMT_RGB8 || mpi->imgfmt==IMGFMT_BGR8){
 
344
        if (priv->palette)
 
345
        {
 
346
            mpi->planes[1] = priv->palette;
 
347
            mp_dbg(MSGT_DECVIDEO, MSGL_DBG2, "Found and copied palette\n");
 
348
        }
 
349
        else
 
350
            mpi->planes[1]=NULL;
 
351
    }
 
352
 
 
353
    return mpi;
 
354
}