Fix indentation.
[mplayer/glamo.git] / libmpcodecs / ve_qtvideo.c
bloba41cb00e96896745173b86840e0231fee930db2e
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 "mpbswap.h"
15 #ifdef WIN32_LOADER
16 #include "loader/ldt_keeper.h"
17 #endif
19 #include "loader/qtx/qtxsdk/components.h"
20 #include "loader/wine/windef.h"
22 #include "codec-cfg.h"
23 #include "stream/stream.h"
24 #include "libmpdemux/demuxer.h"
25 #include "libmpdemux/stheader.h"
27 #include "stream/stream.h"
28 #include "libmpdemux/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 ImageDescriptionHandle desc;
109 static ImageSequence seq;
115 struct vf_priv_s {
116 muxer_stream_t* mux;
117 //dv_encoder_t* enc;
120 #define mux_v (vf->priv->mux)
122 //===========================================================================//
124 static int config(struct vf_instance_s* vf,
125 int width, int height, int d_width, int d_height,
126 unsigned int flags, unsigned int outfmt){
127 // OSErr cres;
128 ComponentDescription cdesc;
129 mux_v->bih->biWidth=width;
130 mux_v->bih->biHeight=height;
131 mux_v->bih->biSizeImage=width*height*2;
132 mux_v->aspect = (float)d_width/d_height;
136 memset(&cdesc,0,sizeof(cdesc));
137 cdesc.componentType= (((unsigned char)'i')<<24)|
138 (((unsigned char)'m')<<16)|
139 (((unsigned char)'c')<<8)|
140 (((unsigned char)'o'));
142 cdesc.componentSubType=bswap_32(format);
143 cdesc.componentManufacturer=0;
144 cdesc.componentFlags=0;
145 cdesc.componentFlagsMask=0;
148 mp_msg(MSGT_MENCODER,MSGL_DBG2,"Count = %ld\n",CountComponents(&cdesc));
149 compressor=FindNextComponent(NULL,&cdesc);
150 if(!compressor){
151 mp_msg(MSGT_MENCODER,MSGL_ERR,"Cannot find requested component\n");
152 return 0;
154 mp_msg(MSGT_MENCODER,MSGL_DBG2,"Found it! ID = %p\n",compressor);
156 // cres= FindCodec (fourcc,anyCodec,&compressor,&decompressor );
157 // printf("FindCodec returned:%i compressor: 0x%X decompressor: 0x%X\n",cres&0xFFFF,compressor,decompressor);
159 return 1;
162 static int control(struct vf_instance_s* vf, int request, void* data){
164 return CONTROL_UNKNOWN;
167 static int query_format(struct vf_instance_s* vf, unsigned int fmt){
168 if(fmt==IMGFMT_YUY2) return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW;
169 return 0;
172 static int codec_initialized = 0;
174 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){
176 OSErr cres;
177 long framesizemax;
178 UInt8 similarity=0;
179 long compressedsize;
180 OSType in_format=kYUVSPixelFormat;
181 int width = mpi->width;
182 int height = mpi->height;
183 int stride = width*2;
184 if(!codec_initialized){
185 FrameRect.top=0;
186 FrameRect.left=0;
187 FrameRect.right=width;
188 FrameRect.bottom=height;
189 cres = QTNewGWorldFromPtr(
190 &frame_GWorld_in,
191 in_format,
192 &FrameRect,
196 mpi->planes[0],
197 stride);
198 mp_msg(MSGT_MENCODER,MSGL_DBG2,"NewGWorldFromPtr returned:%i\n",cres&0xFFFF);
199 //dunno what todo about this
200 frame_prev = malloc(stride * height);
201 cres = QTNewGWorldFromPtr(
202 &frame_GWorld_prev,
203 in_format,
204 &FrameRect,
208 frame_prev,
209 stride);
210 mp_msg(MSGT_MENCODER,MSGL_DBG2,"height:%i width:%i stride:%i\n",height,width,stride);
211 mp_msg(MSGT_MENCODER,MSGL_DBG2,"NewGWorldFromPtr returned:%i\n",cres&0xFFFF);
212 cres= GetMaxCompressionSize (
213 GetGWorldPixMap(frame_GWorld_in),
214 &FrameRect,
216 codecNormalQuality,
217 bswap_32(format),
218 compressor,
219 &framesizemax );
220 mp_msg(MSGT_MENCODER,MSGL_DBG2,"GetMaxCompressionSize returned:%i : MaxSize:%li\n",cres&0xFFFF,framesizemax);
221 frame_comp=malloc(framesizemax);
223 desc = (ImageDescriptionHandle)NewHandleClear(MAX_IDSIZE); //memory where the desc will be stored
224 (*desc)->idSize=MAX_IDSIZE;
226 cres= CompressSequenceBegin (
227 &seq,
228 GetGWorldPixMap( frame_GWorld_in),
229 GetGWorldPixMap( frame_GWorld_prev),
230 &FrameRect,
231 &FrameRect,
232 24, // color depth
233 bswap_32(format), // fourcc
234 compressor, // codec component
235 codecNormalQuality, //codecNormalQuality,
236 codecMaxQuality, //codecNormalQuality,
237 10*30, // keyframe rate
240 desc);
241 mp_msg(MSGT_MENCODER,MSGL_DBG2,"CompressSequenceBegin returned:%i\n",cres&0xFFFF);
242 mp_msg(MSGT_MENCODER,MSGL_DBG2,"Sequence ID:%i\n",seq);
244 dump_ImageDescription(*desc);
245 codec_initialized++;
247 cres = CompressSequenceFrame (
248 seq,
249 GetGWorldPixMap(frame_GWorld_in),
250 &FrameRect,
252 (char*)mux_v->buffer,
253 &compressedsize,
254 &similarity,
257 if(cres&0xFFFF)mp_msg(MSGT_MENCODER,MSGL_DBG2,"CompressSequenceFrame returned:%i\n",cres&0xFFFF);
258 #if 0
259 printf("Size %i->%i \n",stride*height,compressedsize);
260 printf("Ratio: %i:1\n",(stride*height)/compressedsize);
261 #endif
262 muxer_write_chunk(mux_v, compressedsize , similarity?0:0x10, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
264 if(((*desc)->idSize)>MAX_IDSIZE){
265 mp_msg(MSGT_MENCODER,MSGL_ERR,"FATAL! idSize=%d too big, increase MAX_IDSIZE in ve_qtvideo.c!\n",((*desc)->idSize));
266 } else {
267 // according to QT docs, imagedescription may be changed while encoding
268 // a frame (even its size may (and does!) change!)
269 memcpy(mux_v->bih+1,*desc,(*desc)->idSize);
272 return 1;
275 //===========================================================================//
277 static int vf_open(vf_instance_t *vf, char* args){
278 OSErr cres = 1;
279 vf->config=config;
280 vf->default_caps=VFCAP_CONSTANT;
281 vf->control=control;
282 vf->query_format=query_format;
283 vf->put_image=put_image;
284 vf->priv=malloc(sizeof(struct vf_priv_s));
285 memset(vf->priv,0,sizeof(struct vf_priv_s));
286 vf->priv->mux=(muxer_stream_t*)args;
288 mux_v->bih=calloc(1, sizeof(BITMAPINFOHEADER)+MAX_IDSIZE);
289 mux_v->bih->biSize=sizeof(BITMAPINFOHEADER)+MAX_IDSIZE;
290 mux_v->bih->biWidth=0;
291 mux_v->bih->biHeight=0;
292 mux_v->bih->biCompression=format;
293 mux_v->bih->biPlanes=1;
294 mux_v->bih->biBitCount=24;
297 #ifdef WIN32_LOADER
298 Setup_LDT_Keeper();
299 #endif
300 //preload quicktime.qts to avoid the problems caused by the hardcoded path inside the dll
301 qtime_qts = LoadLibraryA("QuickTime.qts");
302 if(!qtime_qts){
303 mp_msg(MSGT_MENCODER,MSGL_ERR,"unable to load QuickTime.qts\n" );
304 return 0;
307 handler = LoadLibraryA("qtmlClient.dll");
308 if(!handler){
309 mp_msg(MSGT_MENCODER,MSGL_ERR,"unable to load qtmlClient.dll\n");
310 return 0;
312 InitializeQTML = (OSErr (*)(long))GetProcAddress(handler, "InitializeQTML");
313 GetGWorldPixMap = (PixMapHandle (*)(GWorldPtr))GetProcAddress(handler, "GetGWorldPixMap");
314 QTNewGWorldFromPtr = (OSErr(*)(GWorldPtr *,OSType,const Rect *,CTabHandle,void*,GWorldFlags,void *,long))GetProcAddress(handler, "QTNewGWorldFromPtr");
315 NewHandleClear = (OSErr(*)(Size))GetProcAddress(handler, "NewHandleClear");
316 FindCodec = (OSErr (*)(CodecType,CodecComponent,CompressorComponent *,DecompressorComponent *))GetProcAddress(handler,"FindCodec");
317 CompressSequenceBegin = (OSErr(*)(ImageSequence *,PixMapHandle,PixMapHandle,const Rect *,const Rect *,short,CodecType,CompressorComponent,CodecQ,CodecQ,long,CTabHandle,CodecFlags,ImageDescriptionHandle))GetProcAddress(handler,"CompressSequenceBegin");
318 CompressSequenceFrame = (OSErr(*)(ImageSequence,PixMapHandle,const Rect *,CodecFlags,Ptr,long *,UInt8 *,ICMCompletionProcRecordPtr))GetProcAddress(handler,"CompressSequenceFrame");
319 GetMaxCompressionSize = (OSErr(*)(PixMapHandle,const Rect *,short,CodecQ,CodecType,CompressorComponent,long *))GetProcAddress(handler,"GetMaxCompressionSize");
320 CDSequenceEnd = (OSErr (*)(ImageSequence))GetProcAddress(handler,"CDSequenceEnd");
321 FindNextComponent = (Component (*)(Component,ComponentDescription*))GetProcAddress(handler, "FindNextComponent");
322 CountComponents = (long (*)(ComponentDescription*))GetProcAddress(handler, "CountComponents");
323 GetComponentInfo = (OSErr (*)(Component,ComponentDescription*,Handle,Handle,Handle))GetProcAddress(handler, "GetComponentInfo");
324 if(!InitializeQTML ||!CompressSequenceBegin){
325 mp_msg(MSGT_MENCODER,MSGL_ERR,"invalid qt DLL!\n");
326 return 0;
328 //printf("%i,%i,%i\n",mmioFOURCC('S','V','Q','1'),'SVQ1',bswap_32(mmioFOURCC('S','V','Q','1')));
329 cres=InitializeQTML(6+16);
330 mp_msg(MSGT_MENCODER,MSGL_DBG2,"InitializeQTML returned %i\n",cres);
331 return 1;
334 vf_info_t ve_info_qtvideo = {
335 "Quicktime video encoder using win32 DLLs",
336 "qtvideo",
337 "Sascha Sommer",
338 "for internal use by mencoder",
339 vf_open
342 //===========================================================================//