mplayer.c: move some --identify code to a separate function
[mplayer/glamo.git] / libmpcodecs / vd_qtvideo.c
blob18c769e32ce246d83b0f5bfd526c4f4cc63172b7
1 /*
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.
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <inttypes.h>
23 #include "config.h"
24 #include "mp_msg.h"
25 #include "mpbswap.h"
26 #include "vd_internal.h"
28 #ifdef CONFIG_QUICKTIME
29 #include <QuickTime/ImageCodec.h>
30 #define dump_ImageDescription(x)
31 #else
32 #include "loader/ldt_keeper.h"
33 #include "loader/qtx/qtxsdk/components.h"
34 #include "loader/wine/windef.h"
35 #endif
37 static const vd_info_t info = {
38 "Quicktime Video decoder",
39 "qtvideo",
40 "A'rpi",
41 "Sascha Sommer",
42 "win32"
45 LIBVD_EXTERN(qtvideo)
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,
65 CGrafPtr port,
66 /*GDHandle*/void* gdh,
67 const Rect *srcRect,
68 MatrixRecordPtr matrix,
69 short mode,
70 RgnHandle mask,
71 CodecFlags flags,
72 CodecQ accuracy,
73 DecompressorComponent codec);
74 static OSErr (*DecompressSequenceFrameS)(ImageSequence seqID,
75 Ptr data,
76 long dataSize,
77 CodecFlags inFlags,
78 CodecFlags *outFlags,
79 ICMCompletionProcRecordPtr asyncCompletionProc);
80 static PixMapHandle (*GetGWorldPixMap)(GWorldPtr offscreenGWorld);
81 static OSErr (*QTNewGWorldFromPtr)(GWorldPtr *gw,
82 OSType pixelFormat,
83 const Rect *boundsRect,
84 CTabHandle cTable,
85 /*GDHandle*/void* aGDevice, //unused anyway
86 GWorldFlags flags,
87 void *baseAddr,
88 long rowBytes);
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;
100 // init driver
101 static int init(sh_video_t *sh){
102 OSErr result = 1;
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");
106 return 0;
109 #ifndef CONFIG_QUICKTIME
110 #ifdef WIN32_LOADER
111 Setup_LDT_Keeper();
112 #endif
114 //preload quicktime.qts to avoid the problems caused by the hardcoded path inside the dll
115 qtime_qts = LoadLibraryA("QuickTime.qts");
116 if(!qtime_qts){
117 mp_msg(MSGT_DECVIDEO,MSGL_ERR,"unable to load QuickTime.qts\n" );
118 return 0;
121 handler = LoadLibraryA("qtmlClient.dll");
122 if(!handler){
123 mp_msg(MSGT_DECVIDEO,MSGL_ERR,"unable to load qtmlClient.dll\n");
124 return 0;
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");
141 return 0;
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);
153 //make a yuy2 gworld
154 OutBufferRect.top=0;
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];
171 int qt_imgfmt;
172 switch(imgfmt)
174 case IMGFMT_YUY2:
175 qt_imgfmt = kYUVSPixelFormat;
176 break;
177 case IMGFMT_YVU9:
178 qt_imgfmt = 0x73797639; //kYVU9PixelFormat;
179 break;
180 case IMGFMT_YV12:
181 qt_imgfmt = 0x79343230;
182 break;
183 case IMGFMT_UYVY:
184 qt_imgfmt = k2vuyPixelFormat;
185 break;
186 case IMGFMT_YVYU:
187 qt_imgfmt = kYVYU422PixelFormat;
188 imgfmt = IMGFMT_YUY2;
189 break;
190 case IMGFMT_RGB16:
191 qt_imgfmt = k16LE555PixelFormat;
192 break;
193 case IMGFMT_BGR24:
194 qt_imgfmt = k24BGRPixelFormat;
195 break;
196 case IMGFMT_BGR32:
197 qt_imgfmt = k32BGRAPixelFormat;
198 break;
199 case IMGFMT_RGB32:
200 qt_imgfmt = k32RGBAPixelFormat;
201 break;
202 default:
203 mp_msg(MSGT_DECVIDEO,MSGL_ERR,"Unknown requested csp\n");
204 return 0;
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);
213 if(!mpi) return 0;
215 result = QTNewGWorldFromPtr(
216 &OutBufferGWorld,
217 (OSType)sh->context,
218 &OutBufferRect, //we should benchmark if yvu9 is faster for svq3, too
222 mpi->planes[0],
223 mpi->stride[0]);
224 if (result) {
225 mp_msg(MSGT_DECVIDEO,MSGL_ERR,"QTNewGWorldFromPtr result=%d\n",result);
226 return 0;
229 result = DecompressSequenceBegin(&imageSeq, framedescHandle, (CGrafPtr)OutBufferGWorld,
230 NULL, NULL, NULL, srcCopy, NULL, 0,
231 codecNormalQuality, 0);
232 if(result) {
233 mp_msg(MSGT_DECVIDEO,MSGL_ERR,"DecompressSequenceBegin result=%d\n",result);
234 return 0;
237 return 1;
240 // uninit driver
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;
250 if(imageSeq) {
251 CDSequenceEnd(imageSeq);
252 imageSeq = 0;
254 ExitMovies();
257 // decode a frame
258 static mp_image_t* decode(sh_video_t *sh,void* data,int len,int flags){
259 OSErr result = 1;
260 CodecFlags ignore;
262 if(len<=0) return NULL; // skipped frame
264 #ifdef WIN32_LOADER
265 Setup_FS_Segment();
266 #endif
268 result = DecompressSequenceFrameS(imageSeq, data, len, 0, &ignore, NULL);
269 if(result) {
270 mp_msg(MSGT_DECVIDEO,MSGL_ERR,"DecompressSequenceFrameS result=0x%d\n",result);
271 return NULL;
274 if((int)sh->context==0x73797639){ // Sorenson 16-bit YUV -> std YVU9
275 int i;
277 PixMap dstPixMap = **GetGWorldPixMap(OutBufferGWorld);
278 short *src0=(short *)((char*)dstPixMap.baseAddr+0x20);
280 for(i=0;i<mpi->h;i++){
281 int x;
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++){
288 int x;
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++){
296 int x;
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;
306 return mpi;