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"
28 #ifdef CONFIG_QUICKTIME
29 #include <QuickTime/ImageCodec.h>
30 #define dump_ImageDescription(x)
32 #include "loader/ldt_keeper.h"
33 #include "loader/qtx/qtxsdk/components.h"
34 #include "loader/wine/windef.h"
37 static const vd_info_t info
= {
38 "Quicktime Video decoder",
47 static mp_image_t
* mpi
;
48 static Rect OutBufferRect
; //the dimensions of our GWorld
50 static GWorldPtr OutBufferGWorld
= NULL
;//a GWorld is some kind of description for a drawing environment
51 static ImageDescriptionHandle framedescHandle
;
52 static ImageSequence imageSeq
;
54 #ifndef CONFIG_QUICKTIME
55 HMODULE WINAPI
LoadLibraryA(LPCSTR
);
56 FARPROC WINAPI
GetProcAddress(HMODULE
,LPCSTR
);
57 int WINAPI
FreeLibrary(HMODULE
);
58 static HINSTANCE qtime_qts
; // handle to the preloaded quicktime.qts
59 static HMODULE handler
;
60 static OSErr (*InitializeQTML
)(long flags
);
61 static OSErr (*EnterMovies
)(void);
62 static void (*ExitMovies
)(void);
63 static OSErr (*DecompressSequenceBegin
)(ImageSequence
*seqID
,
64 ImageDescriptionHandle desc
,
66 /*GDHandle*/void* gdh
,
68 MatrixRecordPtr matrix
,
73 DecompressorComponent codec
);
74 static OSErr (*DecompressSequenceFrameS
)(ImageSequence seqID
,
79 ICMCompletionProcRecordPtr asyncCompletionProc
);
80 static PixMapHandle (*GetGWorldPixMap
)(GWorldPtr offscreenGWorld
);
81 static OSErr (*QTNewGWorldFromPtr
)(GWorldPtr
*gw
,
83 const Rect
*boundsRect
,
85 /*GDHandle*/void* aGDevice
, //unused anyway
89 static Handle (*NewHandleClear
)(Size byteCount
);
90 static void (*DisposeHandle
)(Handle h
);
91 static void (*DisposeGWorld
)(GWorldPtr offscreenGWorld
);
92 static OSErr (*CDSequenceEnd
)(ImageSequence seqID
);
93 #endif /* #ifndef CONFIG_QUICKTIME */
95 // to set/get/query special features/parameters
96 static int control(sh_video_t
*sh
,int cmd
,void* arg
,...){
97 return CONTROL_UNKNOWN
;
101 static int init(sh_video_t
*sh
){
104 if (sh
->ImageDesc
== NULL
) {
105 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,"sh->ImageDesc not set, cannot use binary QuickTime codecs (try -demuxer mov?)\n");
109 #ifndef CONFIG_QUICKTIME
114 //preload quicktime.qts to avoid the problems caused by the hardcoded path inside the dll
115 qtime_qts
= LoadLibraryA("QuickTime.qts");
117 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,"unable to load QuickTime.qts\n" );
121 handler
= LoadLibraryA("qtmlClient.dll");
123 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,"unable to load qtmlClient.dll\n");
127 InitializeQTML
= (OSErr (*)(long))GetProcAddress(handler
, "InitializeQTML");
128 EnterMovies
= (OSErr (*)(void))GetProcAddress(handler
, "EnterMovies");
129 ExitMovies
= (void (*)(void))GetProcAddress(handler
, "ExitMovies");
130 DecompressSequenceBegin
= (OSErr (*)(ImageSequence
*,ImageDescriptionHandle
,CGrafPtr
,void *,const Rect
*,MatrixRecordPtr
,short,RgnHandle
,CodecFlags
,CodecQ
,DecompressorComponent
))GetProcAddress(handler
, "DecompressSequenceBegin");
131 DecompressSequenceFrameS
= (OSErr (*)(ImageSequence
,Ptr
,long,CodecFlags
,CodecFlags
*,ICMCompletionProcRecordPtr
))GetProcAddress(handler
, "DecompressSequenceFrameS");
132 GetGWorldPixMap
= (PixMapHandle (*)(GWorldPtr
))GetProcAddress(handler
, "GetGWorldPixMap");
133 QTNewGWorldFromPtr
= (OSErr(*)(GWorldPtr
*,OSType
,const Rect
*,CTabHandle
,void*,GWorldFlags
,void *,long))GetProcAddress(handler
, "QTNewGWorldFromPtr");
134 NewHandleClear
= (OSErr(*)(Size
))GetProcAddress(handler
, "NewHandleClear");
135 DisposeHandle
= (void (*)(Handle
))GetProcAddress(handler
, "DisposeHandle");
136 DisposeGWorld
= (void (*)(GWorldPtr
))GetProcAddress(handler
, "DisposeGWorld");
137 CDSequenceEnd
= (OSErr (*)(ImageSequence
))GetProcAddress(handler
, "CDSequenceEnd");
139 if(!InitializeQTML
|| !EnterMovies
|| !DecompressSequenceBegin
|| !DecompressSequenceFrameS
){
140 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,"invalid qtmlClient.dll!\n");
144 result
=InitializeQTML(kInitializeQTMLDisableDirectSound
|
145 kInitializeQTMLUseGDIFlag
|
146 kInitializeQTMLDisableDDClippers
);
147 mp_msg(MSGT_DECVIDEO
,MSGL_DBG2
,"InitializeQTML returned %d\n",result
);
148 #endif /* CONFIG_QUICKTIME */
150 result
=EnterMovies();
151 mp_msg(MSGT_DECVIDEO
,MSGL_DBG2
,"EnterMovies returned %d\n",result
);
155 OutBufferRect
.left
=0;
156 OutBufferRect
.right
=sh
->disp_w
;
157 OutBufferRect
.bottom
=sh
->disp_h
;
159 //Fill the imagedescription for our SVQ3 frame
160 //we can probably get this from Demuxer
161 if(!sh
->ImageDesc
) sh
->ImageDesc
=(sh
->bih
+1); // hack for SVQ3-in-AVI
162 mp_msg(MSGT_DECVIDEO
,MSGL_DBG2
,"ImageDescription size: %d\n",((ImageDescription
*)(sh
->ImageDesc
))->idSize
);
163 framedescHandle
=(ImageDescriptionHandle
)NewHandleClear(((ImageDescription
*)(sh
->ImageDesc
))->idSize
);
164 memcpy(*framedescHandle
,sh
->ImageDesc
,((ImageDescription
*)(sh
->ImageDesc
))->idSize
);
165 dump_ImageDescription(*framedescHandle
);
167 (**framedescHandle
).cType
= bswap_32(sh
->format
);
168 sh
->context
= (void *)kYUVSPixelFormat
;
170 int imgfmt
= sh
->codec
->outfmt
[sh
->outfmtidx
];
175 qt_imgfmt
= kYUVSPixelFormat
;
178 qt_imgfmt
= 0x73797639; //kYVU9PixelFormat;
181 qt_imgfmt
= 0x79343230;
184 qt_imgfmt
= k2vuyPixelFormat
;
187 qt_imgfmt
= kYVYU422PixelFormat
;
188 imgfmt
= IMGFMT_YUY2
;
191 qt_imgfmt
= k16LE555PixelFormat
;
194 qt_imgfmt
= k24BGRPixelFormat
;
197 qt_imgfmt
= k32BGRAPixelFormat
;
200 qt_imgfmt
= k32RGBAPixelFormat
;
203 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,"Unknown requested csp\n");
206 mp_msg(MSGT_DECVIDEO
,MSGL_DBG2
,"imgfmt: %s qt_imgfmt: %.4s\n", vo_format_name(imgfmt
), (char *)&qt_imgfmt
);
207 sh
->context
= (void *)qt_imgfmt
;
208 if(!mpcodecs_config_vo(sh
,sh
->disp_w
,sh
->disp_h
,imgfmt
)) return 0;
211 mpi
=mpcodecs_get_image(sh
, MP_IMGTYPE_STATIC
, MP_IMGFLAG_PRESERVE
,
212 sh
->disp_w
, sh
->disp_h
);
215 result
= QTNewGWorldFromPtr(
218 &OutBufferRect
, //we should benchmark if yvu9 is faster for svq3, too
225 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,"QTNewGWorldFromPtr result=%d\n",result
);
229 result
= DecompressSequenceBegin(&imageSeq
, framedescHandle
, (CGrafPtr
)OutBufferGWorld
,
230 NULL
, NULL
, NULL
, srcCopy
, NULL
, 0,
231 codecNormalQuality
, 0);
233 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,"DecompressSequenceBegin result=%d\n",result
);
241 static void uninit(sh_video_t
*sh
){
242 if(OutBufferGWorld
) {
243 DisposeGWorld(OutBufferGWorld
);
244 OutBufferGWorld
= NULL
;
246 if(framedescHandle
) {
247 DisposeHandle((Handle
)framedescHandle
);
248 framedescHandle
= NULL
;
251 CDSequenceEnd(imageSeq
);
258 static mp_image_t
* decode(sh_video_t
*sh
,void* data
,int len
,int flags
){
262 if(len
<=0) return NULL
; // skipped frame
268 result
= DecompressSequenceFrameS(imageSeq
, data
, len
, 0, &ignore
, NULL
);
270 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,"DecompressSequenceFrameS result=0x%d\n",result
);
274 if((int)sh
->context
==0x73797639){ // Sorenson 16-bit YUV -> std YVU9
277 PixMap dstPixMap
= **GetGWorldPixMap(OutBufferGWorld
);
278 short *src0
=(short *)((char*)dstPixMap
.baseAddr
+0x20);
280 for(i
=0;i
<mpi
->h
;i
++){
282 unsigned char* dst
=mpi
->planes
[0]+i
*mpi
->stride
[0];
283 unsigned short* src
=src0
+i
*((mpi
->w
+15)&(~15));
284 for(x
=0;x
<mpi
->w
;x
++) dst
[x
]=src
[x
];
286 src0
+=((mpi
->w
+15)&(~15))*((mpi
->h
+15)&(~15));
287 for(i
=0;i
<mpi
->h
/4;i
++){
289 unsigned char* dst
=mpi
->planes
[1]+i
*mpi
->stride
[1];
290 unsigned short* src
=src0
+i
*(((mpi
->w
+63)&(~63))/4);
291 for(x
=0;x
<mpi
->w
/4;x
++) dst
[x
]=src
[x
];
292 src
+=((mpi
->w
+63)&(~63))/4;
294 src0
+=(((mpi
->w
+63)&(~63))/4)*(((mpi
->h
+63)&(~63))/4);
295 for(i
=0;i
<mpi
->h
/4;i
++){
297 unsigned char* dst
=mpi
->planes
[2]+i
*mpi
->stride
[2];
298 unsigned short* src
=src0
+i
*(((mpi
->w
+63)&(~63))/4);
299 for(x
=0;x
<mpi
->w
/4;x
++) dst
[x
]=src
[x
];
300 src
+=((mpi
->w
+63)&(~63))/4;