fix
[mplayer/glamo.git] / libmpcodecs / ve_qtvideo.c
blob5652ac99b2b68b8969e01967f6df04a750aeb84d
1 /*qt video encoder using win32 libs
2 released under gnu gpl
3 (C)Sascha Sommer */
5 #define MAX_IDSIZE 0x6F
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
11 #include "config.h"
12 #include "mp_msg.h"
13 #include "bswap.h"
15 #ifdef WIN32_LOADER
16 #include "ldt_keeper.h"
17 #endif
19 #ifdef USE_QTX_CODECS
20 #include "loader/qtx/qtxsdk/components.h"
21 #include "wine/windef.h"
23 #include "codec-cfg.h"
24 #include "stream.h"
25 #include "demuxer.h"
26 #include "stheader.h"
28 #include "muxer.h"
30 #include "img_format.h"
31 #include "mp_image.h"
32 #include "vf.h"
34 HMODULE WINAPI LoadLibraryA(LPCSTR);
35 FARPROC WINAPI GetProcAddress(HMODULE,LPCSTR);
36 int WINAPI FreeLibrary(HMODULE);
37 static HINSTANCE qtime_qts; //handle to preloaded quicktime.qts
38 static HMODULE handler;
40 static OSErr (*FindCodec)(CodecType cType,
41 CodecComponent specCodec,
42 CompressorComponent * compressor,
43 DecompressorComponent * decompressor);
44 static OSErr (*InitializeQTML)(long flags);
45 static PixMapHandle (*GetGWorldPixMap)(GWorldPtr offscreenGWorld);
46 static OSErr (*QTNewGWorldFromPtr)(GWorldPtr *gw,
47 OSType pixelFormat,
48 const Rect *boundsRect,
49 CTabHandle cTable,
50 /*GDHandle*/void* aGDevice, /*unused anyway*/
51 GWorldFlags flags,
52 void *baseAddr,
53 long rowBytes);
54 static OSErr (*NewHandleClear)(Size byteCount);
55 static OSErr (*CompressSequenceBegin) (
56 ImageSequence *seqID,
57 PixMapHandle src,
58 PixMapHandle prev,
59 const Rect *srcRect,
60 const Rect *prevRect,
61 short colorDepth,
62 CodecType cType,
63 CompressorComponent codec,
64 CodecQ spatialQuality,
65 CodecQ temporalQuality,
66 long keyFrameRate,
67 CTabHandle ctable,
68 CodecFlags flags,
69 ImageDescriptionHandle desc );
71 static OSErr (*CompressSequenceFrame) (
72 ImageSequence seqID,
73 PixMapHandle src,
74 const Rect *srcRect,
75 CodecFlags flags,
76 Ptr data,
77 long *dataSize,
78 UInt8 *similarity,
79 ICMCompletionProcRecordPtr asyncCompletionProc );
81 static OSErr (*GetMaxCompressionSize)(PixMapHandle src,
82 const Rect *srcRect,
83 short colorDepth,
84 CodecQ quality,
85 CodecType cType,
86 CompressorComponent codec,
87 long *size );
88 static OSErr (*CDSequenceEnd)( ImageSequence seqID );
89 static Component (*FindNextComponent)(Component prev,ComponentDescription* desc);
90 static long (*CountComponents)(ComponentDescription* desc);
91 static OSErr (*GetComponentInfo)(Component prev,ComponentDescription* desc,Handle h1,Handle h2,Handle h3);
95 //static int format=mmioFOURCC('S','V','Q','1');
96 static int format=mmioFOURCC('S','V','Q','3');
100 //static void *frame_in; //input frame
101 static void *frame_prev; //previous frame
102 static void *frame_comp; //compressed frame
103 static GWorldPtr frame_GWorld_in = NULL;//a GWorld is some kind of description for a drawing environment
104 static GWorldPtr frame_GWorld_prev = NULL;
105 static Rect FrameRect;
107 static CompressorComponent compressor;
108 static DecompressorComponent decompressor;
109 static ImageDescriptionHandle desc;
110 static ImageSequence seq;
116 struct vf_priv_s {
117 muxer_stream_t* mux;
118 //dv_encoder_t* enc;
121 #define mux_v (vf->priv->mux)
123 //===========================================================================//
125 static int config(struct vf_instance_s* vf,
126 int width, int height, int d_width, int d_height,
127 unsigned int flags, unsigned int outfmt){
128 OSErr cres;
129 ComponentDescription cdesc;
130 mux_v->bih->biWidth=width;
131 mux_v->bih->biHeight=height;
132 mux_v->bih->biSizeImage=width*height*2;
133 mux_v->aspect = (float)d_width/d_height;
137 memset(&cdesc,0,sizeof(cdesc));
138 cdesc.componentType= (((unsigned char)'i')<<24)|
139 (((unsigned char)'m')<<16)|
140 (((unsigned char)'c')<<8)|
141 (((unsigned char)'o'));
143 cdesc.componentSubType=bswap_32(format);
144 cdesc.componentManufacturer=0;
145 cdesc.componentFlags=0;
146 cdesc.componentFlagsMask=0;
149 mp_msg(MSGT_MENCODER,MSGL_DBG2,"Count = %d\n",CountComponents(&cdesc));
150 compressor=FindNextComponent(NULL,&cdesc);
151 if(!compressor){
152 mp_msg(MSGT_MENCODER,MSGL_ERR,"Cannot find requested component\n");
153 return(0);
155 mp_msg(MSGT_MENCODER,MSGL_DBG2,"Found it! ID = 0x%X\n",compressor);
157 // cres= FindCodec (fourcc,anyCodec,&compressor,&decompressor );
158 // printf("FindCodec returned:%i compressor: 0x%X decompressor: 0x%X\n",cres&0xFFFF,compressor,decompressor);
160 return 1;
163 static int control(struct vf_instance_s* vf, int request, void* data){
165 return CONTROL_UNKNOWN;
168 static int query_format(struct vf_instance_s* vf, unsigned int fmt){
169 if(fmt==IMGFMT_YUY2) return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW;
170 return 0;
173 static int codec_inited = 0;
175 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi){
177 OSErr cres;
178 long framesizemax;
179 UInt8 similarity=0;
180 long compressedsize;
181 OSType in_format=kYUVSPixelFormat;
182 int width = mpi->width;
183 int height = mpi->height;
184 int stride = width*2;
185 if(!codec_inited){
186 FrameRect.top=0;
187 FrameRect.left=0;
188 FrameRect.right=width;
189 FrameRect.bottom=height;
190 cres = QTNewGWorldFromPtr(
191 &frame_GWorld_in,
192 in_format,
193 &FrameRect,
197 mpi->planes[0],
198 stride);
199 mp_msg(MSGT_MENCODER,MSGL_DBG2,"NewGWorldFromPtr returned:%i\n",cres&0xFFFF);
200 //dunno what todo about this
201 frame_prev = malloc(stride * height);
202 cres = QTNewGWorldFromPtr(
203 &frame_GWorld_prev,
204 in_format,
205 &FrameRect,
209 frame_prev,
210 stride);
211 mp_msg(MSGT_MENCODER,MSGL_DBG2,"height:%i width:%i stride:%i\n",height,width,stride);
212 mp_msg(MSGT_MENCODER,MSGL_DBG2,"NewGWorldFromPtr returned:%i\n",cres&0xFFFF);
213 cres= GetMaxCompressionSize (
214 GetGWorldPixMap(frame_GWorld_in),
215 &FrameRect,
217 codecNormalQuality,
218 bswap_32(format),
219 compressor,
220 &framesizemax );
221 mp_msg(MSGT_MENCODER,MSGL_DBG2,"GetMaxCompressionSize returned:%i : MaxSize:%i\n",cres&0xFFFF,framesizemax);
222 frame_comp=malloc(framesizemax);
224 desc = (ImageDescriptionHandle)NewHandleClear(MAX_IDSIZE); //memory where the desc will be stored
225 (*desc)->idSize=MAX_IDSIZE;
227 cres= CompressSequenceBegin (
228 &seq,
229 GetGWorldPixMap( frame_GWorld_in),
230 GetGWorldPixMap( frame_GWorld_prev),
231 &FrameRect,
232 &FrameRect,
233 24, // color depth
234 bswap_32(format), // fourcc
235 compressor, // codec component
236 codecNormalQuality, //codecNormalQuality,
237 codecMaxQuality, //codecNormalQuality,
238 10*30, // keyframe rate
241 desc);
242 mp_msg(MSGT_MENCODER,MSGL_DBG2,"CompressSequenceBegin returned:%i\n",cres&0xFFFF);
243 mp_msg(MSGT_MENCODER,MSGL_DBG2,"Sequence ID:%i\n",seq);
245 dump_ImageDescription(*desc);
246 codec_inited++;
248 cres = CompressSequenceFrame (
249 seq,
250 GetGWorldPixMap(frame_GWorld_in),
251 &FrameRect,
253 (char*)mux_v->buffer,
254 &compressedsize,
255 &similarity,
258 if(cres&0xFFFF)mp_msg(MSGT_MENCODER,MSGL_DBG2,"CompressSequenceFrame returned:%i\n",cres&0xFFFF);
259 #if 0
260 printf("Size %i->%i \n",stride*height,compressedsize);
261 printf("Ratio: %i:1\n",(stride*height)/compressedsize);
262 #endif
263 muxer_write_chunk(mux_v, compressedsize , similarity?0:0x10);
265 if(((*desc)->idSize)>MAX_IDSIZE){
266 mp_msg(MSGT_MENCODER,MSGL_ERR,"FATAL! idSize=%d too big, increase MAX_IDSIZE in ve_qtvideo.c!\n",((*desc)->idSize));
267 } else {
268 // according to QT docs, imagedescription may be changed while encoding
269 // a frame (even its size may (and does!) change!)
270 memcpy(mux_v->bih+1,*desc,(*desc)->idSize);
273 return 1;
276 //===========================================================================//
278 static int vf_open(vf_instance_t *vf, char* args){
279 OSErr cres = 1;
280 vf->config=config;
281 vf->default_caps=VFCAP_CONSTANT;
282 vf->control=control;
283 vf->query_format=query_format;
284 vf->put_image=put_image;
285 vf->priv=malloc(sizeof(struct vf_priv_s));
286 memset(vf->priv,0,sizeof(struct vf_priv_s));
287 vf->priv->mux=(muxer_stream_t*)args;
289 mux_v->bih=calloc(1, sizeof(BITMAPINFOHEADER)+MAX_IDSIZE);
290 mux_v->bih->biSize=sizeof(BITMAPINFOHEADER)+MAX_IDSIZE;
291 mux_v->bih->biWidth=0;
292 mux_v->bih->biHeight=0;
293 mux_v->bih->biCompression=format;
294 mux_v->bih->biPlanes=1;
295 mux_v->bih->biBitCount=24;
298 #ifdef WIN32_LOADER
299 Setup_LDT_Keeper();
300 #endif
301 //preload quicktime.qts to avoid the problems caused by the hardcoded path inside the dll
302 qtime_qts = LoadLibraryA("QuickTime.qts");
303 if(!qtime_qts){
304 mp_msg(MSGT_MENCODER,MSGL_ERR,"unable to load QuickTime.qts\n" );
305 return 0;
308 handler = LoadLibraryA("qtmlClient.dll");
309 if(!handler){
310 mp_msg(MSGT_MENCODER,MSGL_ERR,"unable to load qtmlClient.dll\n");
311 return 0;
313 InitializeQTML = (OSErr (*)(long))GetProcAddress(handler, "InitializeQTML");
314 GetGWorldPixMap = (PixMapHandle (*)(GWorldPtr))GetProcAddress(handler, "GetGWorldPixMap");
315 QTNewGWorldFromPtr = (OSErr(*)(GWorldPtr *,OSType,const Rect *,CTabHandle,void*,GWorldFlags,void *,long))GetProcAddress(handler, "QTNewGWorldFromPtr");
316 NewHandleClear = (OSErr(*)(Size))GetProcAddress(handler, "NewHandleClear");
317 FindCodec = (OSErr (*)(CodecType,CodecComponent,CompressorComponent *,DecompressorComponent *))GetProcAddress(handler,"FindCodec");
318 CompressSequenceBegin = (OSErr(*)(ImageSequence *,PixMapHandle,PixMapHandle,const Rect *,const Rect *,short,CodecType,CompressorComponent,CodecQ,CodecQ,long,CTabHandle,CodecFlags,ImageDescriptionHandle))GetProcAddress(handler,"CompressSequenceBegin");
319 CompressSequenceFrame = (OSErr(*)(ImageSequence,PixMapHandle,const Rect *,CodecFlags,Ptr,long *,UInt8 *,ICMCompletionProcRecordPtr))GetProcAddress(handler,"CompressSequenceFrame");
320 GetMaxCompressionSize = (OSErr(*)(PixMapHandle,const Rect *,short,CodecQ,CodecType,CompressorComponent,long *))GetProcAddress(handler,"GetMaxCompressionSize");
321 CDSequenceEnd = (OSErr (*)(ImageSequence))GetProcAddress(handler,"CDSequenceEnd");
322 FindNextComponent = (Component (*)(Component,ComponentDescription*))GetProcAddress(handler, "FindNextComponent");
323 CountComponents = (long (*)(ComponentDescription*))GetProcAddress(handler, "CountComponents");
324 GetComponentInfo = (OSErr (*)(Component,ComponentDescription*,Handle,Handle,Handle))GetProcAddress(handler, "GetComponentInfo");
325 if(!InitializeQTML ||!CompressSequenceBegin){
326 mp_msg(MSGT_MENCODER,MSGL_ERR,"invalid qt DLL!\n");
327 return 0;
329 //printf("%i,%i,%i\n",mmioFOURCC('S','V','Q','1'),'SVQ1',bswap_32(mmioFOURCC('S','V','Q','1')));
330 cres=InitializeQTML(6+16);
331 mp_msg(MSGT_MENCODER,MSGL_DBG2,"InitializeQTML returned %i\n",cres);
332 return 1;
335 vf_info_t ve_info_qtvideo = {
336 "Quicktime video encoder using win32 DLLs",
337 "qtvideo",
338 "Sascha Sommer",
339 "for internal use by mencoder",
340 vf_open
343 //===========================================================================//
344 #endif