stream/tv: move new_handle() function from header to tv.c
[mplayer.git] / libmpcodecs / ve_qtvideo.c
blob59b8731c93cec471f868034db9f24d89d54da083
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/winbase.h"
39 #include "loader/wine/windef.h"
41 #include "codec-cfg.h"
42 #include "stream/stream.h"
43 #include "libmpdemux/demuxer.h"
44 #include "libmpdemux/stheader.h"
46 #include "stream/stream.h"
47 #include "libmpdemux/muxer.h"
49 #include "img_format.h"
50 #include "mp_image.h"
51 #include "vf.h"
54 static HINSTANCE qtime_qts; //handle to preloaded quicktime.qts
55 static HMODULE handler;
57 static OSErr (*FindCodec)(CodecType cType,
58 CodecComponent specCodec,
59 CompressorComponent * compressor,
60 DecompressorComponent * decompressor);
61 static OSErr (*InitializeQTML)(long flags);
62 static PixMapHandle (*GetGWorldPixMap)(GWorldPtr offscreenGWorld);
63 static OSErr (*QTNewGWorldFromPtr)(GWorldPtr *gw,
64 OSType pixelFormat,
65 const Rect *boundsRect,
66 CTabHandle cTable,
67 /*GDHandle*/void* aGDevice, /*unused anyway*/
68 GWorldFlags flags,
69 void *baseAddr,
70 long rowBytes);
71 static Handle (*NewHandleClear)(Size byteCount);
72 static OSErr (*CompressSequenceBegin) (
73 ImageSequence *seqID,
74 PixMapHandle src,
75 PixMapHandle prev,
76 const Rect *srcRect,
77 const Rect *prevRect,
78 short colorDepth,
79 CodecType cType,
80 CompressorComponent codec,
81 CodecQ spatialQuality,
82 CodecQ temporalQuality,
83 long keyFrameRate,
84 CTabHandle ctable,
85 CodecFlags flags,
86 ImageDescriptionHandle desc );
88 static OSErr (*CompressSequenceFrame) (
89 ImageSequence seqID,
90 PixMapHandle src,
91 const Rect *srcRect,
92 CodecFlags flags,
93 Ptr data,
94 long *dataSize,
95 UInt8 *similarity,
96 ICMCompletionProcRecordPtr asyncCompletionProc );
98 static OSErr (*GetMaxCompressionSize)(PixMapHandle src,
99 const Rect *srcRect,
100 short colorDepth,
101 CodecQ quality,
102 CodecType cType,
103 CompressorComponent codec,
104 long *size );
105 static OSErr (*CDSequenceEnd)( ImageSequence seqID );
106 static Component (*FindNextComponent)(Component prev,ComponentDescription* desc);
107 static long (*CountComponents)(ComponentDescription* desc);
108 static OSErr (*GetComponentInfo)(Component prev,ComponentDescription* desc,Handle h1,Handle h2,Handle h3);
112 //static int format=mmioFOURCC('S','V','Q','1');
113 static int format=mmioFOURCC('S','V','Q','3');
117 //static void *frame_in; //input frame
118 static void *frame_prev; //previous frame
119 static void *frame_comp; //compressed frame
120 static GWorldPtr frame_GWorld_in = NULL;//a GWorld is some kind of description for a drawing environment
121 static GWorldPtr frame_GWorld_prev = NULL;
122 static Rect FrameRect;
124 static CompressorComponent compressor;
125 static ImageDescriptionHandle desc;
126 static ImageSequence seq;
132 struct vf_priv_s {
133 muxer_stream_t* mux;
134 //dv_encoder_t* enc;
137 #define mux_v (vf->priv->mux)
139 //===========================================================================//
141 static int config(struct vf_instance *vf,
142 int width, int height, int d_width, int d_height,
143 unsigned int flags, unsigned int outfmt){
144 // OSErr cres;
145 ComponentDescription cdesc;
146 mux_v->bih->biWidth=width;
147 mux_v->bih->biHeight=height;
148 mux_v->bih->biSizeImage=width*height*2;
149 mux_v->aspect = (float)d_width/d_height;
153 memset(&cdesc,0,sizeof(cdesc));
154 cdesc.componentType= (((unsigned char)'i')<<24)|
155 (((unsigned char)'m')<<16)|
156 (((unsigned char)'c')<<8)|
157 (((unsigned char)'o'));
159 cdesc.componentSubType=bswap_32(format);
160 cdesc.componentManufacturer=0;
161 cdesc.componentFlags=0;
162 cdesc.componentFlagsMask=0;
165 mp_msg(MSGT_MENCODER,MSGL_DBG2,"Count = %ld\n",CountComponents(&cdesc));
166 compressor=FindNextComponent(NULL,&cdesc);
167 if(!compressor){
168 mp_msg(MSGT_MENCODER,MSGL_ERR,"Cannot find requested component\n");
169 return 0;
171 mp_msg(MSGT_MENCODER,MSGL_DBG2,"Found it! ID = %p\n",compressor);
173 // cres= FindCodec (fourcc,anyCodec,&compressor,&decompressor );
174 // printf("FindCodec returned:%i compressor: 0x%X decompressor: 0x%X\n",cres&0xFFFF,compressor,decompressor);
176 return 1;
179 static int control(struct vf_instance *vf, int request, void* data){
181 return CONTROL_UNKNOWN;
184 static int query_format(struct vf_instance *vf, unsigned int fmt){
185 if(fmt==IMGFMT_YUY2) return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW;
186 return 0;
189 static int codec_initialized = 0;
191 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
193 OSErr cres;
194 long framesizemax;
195 UInt8 similarity=0;
196 long compressedsize;
197 OSType in_format=kYUVSPixelFormat;
198 int width = mpi->width;
199 int height = mpi->height;
200 int stride = width*2;
201 if(!codec_initialized){
202 FrameRect.top=0;
203 FrameRect.left=0;
204 FrameRect.right=width;
205 FrameRect.bottom=height;
206 cres = QTNewGWorldFromPtr(
207 &frame_GWorld_in,
208 in_format,
209 &FrameRect,
213 mpi->planes[0],
214 stride);
215 mp_msg(MSGT_MENCODER,MSGL_DBG2,"NewGWorldFromPtr returned:%i\n",cres&0xFFFF);
216 //dunno what todo about this
217 frame_prev = malloc(stride * height);
218 cres = QTNewGWorldFromPtr(
219 &frame_GWorld_prev,
220 in_format,
221 &FrameRect,
225 frame_prev,
226 stride);
227 mp_msg(MSGT_MENCODER,MSGL_DBG2,"height:%i width:%i stride:%i\n",height,width,stride);
228 mp_msg(MSGT_MENCODER,MSGL_DBG2,"NewGWorldFromPtr returned:%i\n",cres&0xFFFF);
229 cres= GetMaxCompressionSize (
230 GetGWorldPixMap(frame_GWorld_in),
231 &FrameRect,
233 codecNormalQuality,
234 bswap_32(format),
235 compressor,
236 &framesizemax );
237 mp_msg(MSGT_MENCODER,MSGL_DBG2,"GetMaxCompressionSize returned:%i : MaxSize:%li\n",cres&0xFFFF,framesizemax);
238 frame_comp=malloc(framesizemax);
240 desc = (ImageDescriptionHandle)NewHandleClear(MAX_IDSIZE); //memory where the desc will be stored
241 (*desc)->idSize=MAX_IDSIZE;
243 cres= CompressSequenceBegin (
244 &seq,
245 GetGWorldPixMap( frame_GWorld_in),
246 GetGWorldPixMap( frame_GWorld_prev),
247 &FrameRect,
248 &FrameRect,
249 24, // color depth
250 bswap_32(format), // fourcc
251 compressor, // codec component
252 codecNormalQuality, //codecNormalQuality,
253 codecMaxQuality, //codecNormalQuality,
254 10*30, // keyframe rate
257 desc);
258 mp_msg(MSGT_MENCODER,MSGL_DBG2,"CompressSequenceBegin returned:%i\n",cres&0xFFFF);
259 mp_msg(MSGT_MENCODER,MSGL_DBG2,"Sequence ID:%i\n",seq);
261 dump_ImageDescription(*desc);
262 codec_initialized++;
264 cres = CompressSequenceFrame (
265 seq,
266 GetGWorldPixMap(frame_GWorld_in),
267 &FrameRect,
269 (char*)mux_v->buffer,
270 &compressedsize,
271 &similarity,
274 if(cres&0xFFFF)mp_msg(MSGT_MENCODER,MSGL_DBG2,"CompressSequenceFrame returned:%i\n",cres&0xFFFF);
275 #if 0
276 printf("Size %i->%i \n",stride*height,compressedsize);
277 printf("Ratio: %i:1\n",(stride*height)/compressedsize);
278 #endif
279 muxer_write_chunk(mux_v, compressedsize , similarity?0:0x10, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
281 if(((*desc)->idSize)>MAX_IDSIZE){
282 mp_msg(MSGT_MENCODER,MSGL_ERR,"FATAL! idSize=%d too big, increase MAX_IDSIZE in ve_qtvideo.c!\n",((*desc)->idSize));
283 } else {
284 // according to QT docs, imagedescription may be changed while encoding
285 // a frame (even its size may (and does!) change!)
286 memcpy(mux_v->bih+1,*desc,(*desc)->idSize);
289 return 1;
292 //===========================================================================//
294 static int vf_open(vf_instance_t *vf, char* args){
295 OSErr cres = 1;
296 vf->config=config;
297 vf->default_caps=VFCAP_CONSTANT;
298 vf->control=control;
299 vf->query_format=query_format;
300 vf->put_image=put_image;
301 vf->priv=malloc(sizeof(struct vf_priv_s));
302 memset(vf->priv,0,sizeof(struct vf_priv_s));
303 vf->priv->mux=(muxer_stream_t*)args;
305 mux_v->bih=calloc(1, sizeof(BITMAPINFOHEADER)+MAX_IDSIZE);
306 mux_v->bih->biSize=sizeof(BITMAPINFOHEADER)+MAX_IDSIZE;
307 mux_v->bih->biWidth=0;
308 mux_v->bih->biHeight=0;
309 mux_v->bih->biCompression=format;
310 mux_v->bih->biPlanes=1;
311 mux_v->bih->biBitCount=24;
314 #ifdef WIN32_LOADER
315 Setup_LDT_Keeper();
316 #endif
317 //preload quicktime.qts to avoid the problems caused by the hardcoded path inside the dll
318 qtime_qts = LoadLibraryA("QuickTime.qts");
319 if(!qtime_qts){
320 mp_msg(MSGT_MENCODER,MSGL_ERR,"unable to load QuickTime.qts\n" );
321 return 0;
324 handler = LoadLibraryA("qtmlClient.dll");
325 if(!handler){
326 mp_msg(MSGT_MENCODER,MSGL_ERR,"unable to load qtmlClient.dll\n");
327 return 0;
329 InitializeQTML = (OSErr (*)(long))GetProcAddress(handler, "InitializeQTML");
330 GetGWorldPixMap = (PixMapHandle (*)(GWorldPtr))GetProcAddress(handler, "GetGWorldPixMap");
331 QTNewGWorldFromPtr = (OSErr(*)(GWorldPtr *,OSType,const Rect *,CTabHandle,void*,GWorldFlags,void *,long))GetProcAddress(handler, "QTNewGWorldFromPtr");
332 NewHandleClear = (OSErr(*)(Size))GetProcAddress(handler, "NewHandleClear");
333 FindCodec = (OSErr (*)(CodecType,CodecComponent,CompressorComponent *,DecompressorComponent *))GetProcAddress(handler,"FindCodec");
334 CompressSequenceBegin = (OSErr(*)(ImageSequence *,PixMapHandle,PixMapHandle,const Rect *,const Rect *,short,CodecType,CompressorComponent,CodecQ,CodecQ,long,CTabHandle,CodecFlags,ImageDescriptionHandle))GetProcAddress(handler,"CompressSequenceBegin");
335 CompressSequenceFrame = (OSErr(*)(ImageSequence,PixMapHandle,const Rect *,CodecFlags,Ptr,long *,UInt8 *,ICMCompletionProcRecordPtr))GetProcAddress(handler,"CompressSequenceFrame");
336 GetMaxCompressionSize = (OSErr(*)(PixMapHandle,const Rect *,short,CodecQ,CodecType,CompressorComponent,long *))GetProcAddress(handler,"GetMaxCompressionSize");
337 CDSequenceEnd = (OSErr (*)(ImageSequence))GetProcAddress(handler,"CDSequenceEnd");
338 FindNextComponent = (Component (*)(Component,ComponentDescription*))GetProcAddress(handler, "FindNextComponent");
339 CountComponents = (long (*)(ComponentDescription*))GetProcAddress(handler, "CountComponents");
340 GetComponentInfo = (OSErr (*)(Component,ComponentDescription*,Handle,Handle,Handle))GetProcAddress(handler, "GetComponentInfo");
341 if(!InitializeQTML ||!CompressSequenceBegin){
342 mp_msg(MSGT_MENCODER,MSGL_ERR,"invalid qt DLL!\n");
343 return 0;
345 //printf("%i,%i,%i\n",mmioFOURCC('S','V','Q','1'),'SVQ1',bswap_32(mmioFOURCC('S','V','Q','1')));
346 cres=InitializeQTML(6+16);
347 mp_msg(MSGT_MENCODER,MSGL_DBG2,"InitializeQTML returned %i\n",cres);
348 return 1;
351 vf_info_t ve_info_qtvideo = {
352 "Quicktime video encoder using win32 DLLs",
353 "qtvideo",
354 "Sascha Sommer",
355 "for internal use by mencoder",
356 vf_open
359 //===========================================================================//