Add support for VDPAU video out, including hardware decoding.
[mplayer/glamo.git] / libmpcodecs / ve_qtvideo.c
blob238f539df8c0e49b8bf998a78101aa88f61ae89c
1 /*
2 * QT video encoder using Win32 libs
4 * Copyright (C) 2002 Sascha Sommer
6 * This file is part of MPlayer.
8 * MPlayer is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #define MAX_IDSIZE 0x6F
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
29 #include "config.h"
30 #include "mp_msg.h"
31 #include "mpbswap.h"
33 #ifdef WIN32_LOADER
34 #include "loader/ldt_keeper.h"
35 #endif
37 #include "loader/qtx/qtxsdk/components.h"
38 #include "loader/wine/windef.h"
40 #include "codec-cfg.h"
41 #include "stream/stream.h"
42 #include "libmpdemux/demuxer.h"
43 #include "libmpdemux/stheader.h"
45 #include "stream/stream.h"
46 #include "libmpdemux/muxer.h"
48 #include "img_format.h"
49 #include "mp_image.h"
50 #include "vf.h"
52 HMODULE WINAPI LoadLibraryA(LPCSTR);
53 FARPROC WINAPI GetProcAddress(HMODULE,LPCSTR);
54 int WINAPI FreeLibrary(HMODULE);
55 static HINSTANCE qtime_qts; //handle to preloaded quicktime.qts
56 static HMODULE handler;
58 static OSErr (*FindCodec)(CodecType cType,
59 CodecComponent specCodec,
60 CompressorComponent * compressor,
61 DecompressorComponent * decompressor);
62 static OSErr (*InitializeQTML)(long flags);
63 static PixMapHandle (*GetGWorldPixMap)(GWorldPtr offscreenGWorld);
64 static OSErr (*QTNewGWorldFromPtr)(GWorldPtr *gw,
65 OSType pixelFormat,
66 const Rect *boundsRect,
67 CTabHandle cTable,
68 /*GDHandle*/void* aGDevice, /*unused anyway*/
69 GWorldFlags flags,
70 void *baseAddr,
71 long rowBytes);
72 static OSErr (*NewHandleClear)(Size byteCount);
73 static OSErr (*CompressSequenceBegin) (
74 ImageSequence *seqID,
75 PixMapHandle src,
76 PixMapHandle prev,
77 const Rect *srcRect,
78 const Rect *prevRect,
79 short colorDepth,
80 CodecType cType,
81 CompressorComponent codec,
82 CodecQ spatialQuality,
83 CodecQ temporalQuality,
84 long keyFrameRate,
85 CTabHandle ctable,
86 CodecFlags flags,
87 ImageDescriptionHandle desc );
89 static OSErr (*CompressSequenceFrame) (
90 ImageSequence seqID,
91 PixMapHandle src,
92 const Rect *srcRect,
93 CodecFlags flags,
94 Ptr data,
95 long *dataSize,
96 UInt8 *similarity,
97 ICMCompletionProcRecordPtr asyncCompletionProc );
99 static OSErr (*GetMaxCompressionSize)(PixMapHandle src,
100 const Rect *srcRect,
101 short colorDepth,
102 CodecQ quality,
103 CodecType cType,
104 CompressorComponent codec,
105 long *size );
106 static OSErr (*CDSequenceEnd)( ImageSequence seqID );
107 static Component (*FindNextComponent)(Component prev,ComponentDescription* desc);
108 static long (*CountComponents)(ComponentDescription* desc);
109 static OSErr (*GetComponentInfo)(Component prev,ComponentDescription* desc,Handle h1,Handle h2,Handle h3);
113 //static int format=mmioFOURCC('S','V','Q','1');
114 static int format=mmioFOURCC('S','V','Q','3');
118 //static void *frame_in; //input frame
119 static void *frame_prev; //previous frame
120 static void *frame_comp; //compressed frame
121 static GWorldPtr frame_GWorld_in = NULL;//a GWorld is some kind of description for a drawing environment
122 static GWorldPtr frame_GWorld_prev = NULL;
123 static Rect FrameRect;
125 static CompressorComponent compressor;
126 static ImageDescriptionHandle desc;
127 static ImageSequence seq;
133 struct vf_priv_s {
134 muxer_stream_t* mux;
135 //dv_encoder_t* enc;
138 #define mux_v (vf->priv->mux)
140 //===========================================================================//
142 static int config(struct vf_instance_s* vf,
143 int width, int height, int d_width, int d_height,
144 unsigned int flags, unsigned int outfmt){
145 // OSErr cres;
146 ComponentDescription cdesc;
147 mux_v->bih->biWidth=width;
148 mux_v->bih->biHeight=height;
149 mux_v->bih->biSizeImage=width*height*2;
150 mux_v->aspect = (float)d_width/d_height;
154 memset(&cdesc,0,sizeof(cdesc));
155 cdesc.componentType= (((unsigned char)'i')<<24)|
156 (((unsigned char)'m')<<16)|
157 (((unsigned char)'c')<<8)|
158 (((unsigned char)'o'));
160 cdesc.componentSubType=bswap_32(format);
161 cdesc.componentManufacturer=0;
162 cdesc.componentFlags=0;
163 cdesc.componentFlagsMask=0;
166 mp_msg(MSGT_MENCODER,MSGL_DBG2,"Count = %ld\n",CountComponents(&cdesc));
167 compressor=FindNextComponent(NULL,&cdesc);
168 if(!compressor){
169 mp_msg(MSGT_MENCODER,MSGL_ERR,"Cannot find requested component\n");
170 return 0;
172 mp_msg(MSGT_MENCODER,MSGL_DBG2,"Found it! ID = %p\n",compressor);
174 // cres= FindCodec (fourcc,anyCodec,&compressor,&decompressor );
175 // printf("FindCodec returned:%i compressor: 0x%X decompressor: 0x%X\n",cres&0xFFFF,compressor,decompressor);
177 return 1;
180 static int control(struct vf_instance_s* vf, int request, void* data){
182 return CONTROL_UNKNOWN;
185 static int query_format(struct vf_instance_s* vf, unsigned int fmt){
186 if(fmt==IMGFMT_YUY2) return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW;
187 return 0;
190 static int codec_initialized = 0;
192 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){
194 OSErr cres;
195 long framesizemax;
196 UInt8 similarity=0;
197 long compressedsize;
198 OSType in_format=kYUVSPixelFormat;
199 int width = mpi->width;
200 int height = mpi->height;
201 int stride = width*2;
202 if(!codec_initialized){
203 FrameRect.top=0;
204 FrameRect.left=0;
205 FrameRect.right=width;
206 FrameRect.bottom=height;
207 cres = QTNewGWorldFromPtr(
208 &frame_GWorld_in,
209 in_format,
210 &FrameRect,
214 mpi->planes[0],
215 stride);
216 mp_msg(MSGT_MENCODER,MSGL_DBG2,"NewGWorldFromPtr returned:%i\n",cres&0xFFFF);
217 //dunno what todo about this
218 frame_prev = malloc(stride * height);
219 cres = QTNewGWorldFromPtr(
220 &frame_GWorld_prev,
221 in_format,
222 &FrameRect,
226 frame_prev,
227 stride);
228 mp_msg(MSGT_MENCODER,MSGL_DBG2,"height:%i width:%i stride:%i\n",height,width,stride);
229 mp_msg(MSGT_MENCODER,MSGL_DBG2,"NewGWorldFromPtr returned:%i\n",cres&0xFFFF);
230 cres= GetMaxCompressionSize (
231 GetGWorldPixMap(frame_GWorld_in),
232 &FrameRect,
234 codecNormalQuality,
235 bswap_32(format),
236 compressor,
237 &framesizemax );
238 mp_msg(MSGT_MENCODER,MSGL_DBG2,"GetMaxCompressionSize returned:%i : MaxSize:%li\n",cres&0xFFFF,framesizemax);
239 frame_comp=malloc(framesizemax);
241 desc = (ImageDescriptionHandle)NewHandleClear(MAX_IDSIZE); //memory where the desc will be stored
242 (*desc)->idSize=MAX_IDSIZE;
244 cres= CompressSequenceBegin (
245 &seq,
246 GetGWorldPixMap( frame_GWorld_in),
247 GetGWorldPixMap( frame_GWorld_prev),
248 &FrameRect,
249 &FrameRect,
250 24, // color depth
251 bswap_32(format), // fourcc
252 compressor, // codec component
253 codecNormalQuality, //codecNormalQuality,
254 codecMaxQuality, //codecNormalQuality,
255 10*30, // keyframe rate
258 desc);
259 mp_msg(MSGT_MENCODER,MSGL_DBG2,"CompressSequenceBegin returned:%i\n",cres&0xFFFF);
260 mp_msg(MSGT_MENCODER,MSGL_DBG2,"Sequence ID:%i\n",seq);
262 dump_ImageDescription(*desc);
263 codec_initialized++;
265 cres = CompressSequenceFrame (
266 seq,
267 GetGWorldPixMap(frame_GWorld_in),
268 &FrameRect,
270 (char*)mux_v->buffer,
271 &compressedsize,
272 &similarity,
275 if(cres&0xFFFF)mp_msg(MSGT_MENCODER,MSGL_DBG2,"CompressSequenceFrame returned:%i\n",cres&0xFFFF);
276 #if 0
277 printf("Size %i->%i \n",stride*height,compressedsize);
278 printf("Ratio: %i:1\n",(stride*height)/compressedsize);
279 #endif
280 muxer_write_chunk(mux_v, compressedsize , similarity?0:0x10, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
282 if(((*desc)->idSize)>MAX_IDSIZE){
283 mp_msg(MSGT_MENCODER,MSGL_ERR,"FATAL! idSize=%d too big, increase MAX_IDSIZE in ve_qtvideo.c!\n",((*desc)->idSize));
284 } else {
285 // according to QT docs, imagedescription may be changed while encoding
286 // a frame (even its size may (and does!) change!)
287 memcpy(mux_v->bih+1,*desc,(*desc)->idSize);
290 return 1;
293 //===========================================================================//
295 static int vf_open(vf_instance_t *vf, char* args){
296 OSErr cres = 1;
297 vf->config=config;
298 vf->default_caps=VFCAP_CONSTANT;
299 vf->control=control;
300 vf->query_format=query_format;
301 vf->put_image=put_image;
302 vf->priv=malloc(sizeof(struct vf_priv_s));
303 memset(vf->priv,0,sizeof(struct vf_priv_s));
304 vf->priv->mux=(muxer_stream_t*)args;
306 mux_v->bih=calloc(1, sizeof(BITMAPINFOHEADER)+MAX_IDSIZE);
307 mux_v->bih->biSize=sizeof(BITMAPINFOHEADER)+MAX_IDSIZE;
308 mux_v->bih->biWidth=0;
309 mux_v->bih->biHeight=0;
310 mux_v->bih->biCompression=format;
311 mux_v->bih->biPlanes=1;
312 mux_v->bih->biBitCount=24;
315 #ifdef WIN32_LOADER
316 Setup_LDT_Keeper();
317 #endif
318 //preload quicktime.qts to avoid the problems caused by the hardcoded path inside the dll
319 qtime_qts = LoadLibraryA("QuickTime.qts");
320 if(!qtime_qts){
321 mp_msg(MSGT_MENCODER,MSGL_ERR,"unable to load QuickTime.qts\n" );
322 return 0;
325 handler = LoadLibraryA("qtmlClient.dll");
326 if(!handler){
327 mp_msg(MSGT_MENCODER,MSGL_ERR,"unable to load qtmlClient.dll\n");
328 return 0;
330 InitializeQTML = (OSErr (*)(long))GetProcAddress(handler, "InitializeQTML");
331 GetGWorldPixMap = (PixMapHandle (*)(GWorldPtr))GetProcAddress(handler, "GetGWorldPixMap");
332 QTNewGWorldFromPtr = (OSErr(*)(GWorldPtr *,OSType,const Rect *,CTabHandle,void*,GWorldFlags,void *,long))GetProcAddress(handler, "QTNewGWorldFromPtr");
333 NewHandleClear = (OSErr(*)(Size))GetProcAddress(handler, "NewHandleClear");
334 FindCodec = (OSErr (*)(CodecType,CodecComponent,CompressorComponent *,DecompressorComponent *))GetProcAddress(handler,"FindCodec");
335 CompressSequenceBegin = (OSErr(*)(ImageSequence *,PixMapHandle,PixMapHandle,const Rect *,const Rect *,short,CodecType,CompressorComponent,CodecQ,CodecQ,long,CTabHandle,CodecFlags,ImageDescriptionHandle))GetProcAddress(handler,"CompressSequenceBegin");
336 CompressSequenceFrame = (OSErr(*)(ImageSequence,PixMapHandle,const Rect *,CodecFlags,Ptr,long *,UInt8 *,ICMCompletionProcRecordPtr))GetProcAddress(handler,"CompressSequenceFrame");
337 GetMaxCompressionSize = (OSErr(*)(PixMapHandle,const Rect *,short,CodecQ,CodecType,CompressorComponent,long *))GetProcAddress(handler,"GetMaxCompressionSize");
338 CDSequenceEnd = (OSErr (*)(ImageSequence))GetProcAddress(handler,"CDSequenceEnd");
339 FindNextComponent = (Component (*)(Component,ComponentDescription*))GetProcAddress(handler, "FindNextComponent");
340 CountComponents = (long (*)(ComponentDescription*))GetProcAddress(handler, "CountComponents");
341 GetComponentInfo = (OSErr (*)(Component,ComponentDescription*,Handle,Handle,Handle))GetProcAddress(handler, "GetComponentInfo");
342 if(!InitializeQTML ||!CompressSequenceBegin){
343 mp_msg(MSGT_MENCODER,MSGL_ERR,"invalid qt DLL!\n");
344 return 0;
346 //printf("%i,%i,%i\n",mmioFOURCC('S','V','Q','1'),'SVQ1',bswap_32(mmioFOURCC('S','V','Q','1')));
347 cres=InitializeQTML(6+16);
348 mp_msg(MSGT_MENCODER,MSGL_DBG2,"InitializeQTML returned %i\n",cres);
349 return 1;
352 vf_info_t ve_info_qtvideo = {
353 "Quicktime video encoder using win32 DLLs",
354 "qtvideo",
355 "Sascha Sommer",
356 "for internal use by mencoder",
357 vf_open
360 //===========================================================================//