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
34 #include "loader/ldt_keeper.h"
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"
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
,
66 const Rect
*boundsRect
,
68 /*GDHandle*/void* aGDevice
, /*unused anyway*/
72 static OSErr (*NewHandleClear
)(Size byteCount
);
73 static OSErr (*CompressSequenceBegin
) (
81 CompressorComponent codec
,
82 CodecQ spatialQuality
,
83 CodecQ temporalQuality
,
87 ImageDescriptionHandle desc
);
89 static OSErr (*CompressSequenceFrame
) (
97 ICMCompletionProcRecordPtr asyncCompletionProc
);
99 static OSErr (*GetMaxCompressionSize
)(PixMapHandle src
,
104 CompressorComponent codec
,
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
;
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
){
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
);
169 mp_msg(MSGT_MENCODER
,MSGL_ERR
,"Cannot find requested component\n");
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);
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
;
190 static int codec_initialized
= 0;
192 static int put_image(struct vf_instance_s
* vf
, mp_image_t
*mpi
, double pts
){
198 OSType in_format
=kYUVSPixelFormat
;
199 int width
= mpi
->width
;
200 int height
= mpi
->height
;
201 int stride
= width
*2;
202 if(!codec_initialized
){
205 FrameRect
.right
=width
;
206 FrameRect
.bottom
=height
;
207 cres
= QTNewGWorldFromPtr(
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(
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
),
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 (
246 GetGWorldPixMap( frame_GWorld_in
),
247 GetGWorldPixMap( frame_GWorld_prev
),
251 bswap_32(format
), // fourcc
252 compressor
, // codec component
253 codecNormalQuality
, //codecNormalQuality,
254 codecMaxQuality
, //codecNormalQuality,
255 10*30, // keyframe rate
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
);
265 cres
= CompressSequenceFrame (
267 GetGWorldPixMap(frame_GWorld_in
),
270 (char*)mux_v
->buffer
,
275 if(cres
&0xFFFF)mp_msg(MSGT_MENCODER
,MSGL_DBG2
,"CompressSequenceFrame returned:%i\n",cres
&0xFFFF);
277 printf("Size %i->%i \n",stride
*height
,compressedsize
);
278 printf("Ratio: %i:1\n",(stride
*height
)/compressedsize
);
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
));
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
);
293 //===========================================================================//
295 static int vf_open(vf_instance_t
*vf
, char* args
){
298 vf
->default_caps
=VFCAP_CONSTANT
;
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;
318 //preload quicktime.qts to avoid the problems caused by the hardcoded path inside the dll
319 qtime_qts
= LoadLibraryA("QuickTime.qts");
321 mp_msg(MSGT_MENCODER
,MSGL_ERR
,"unable to load QuickTime.qts\n" );
325 handler
= LoadLibraryA("qtmlClient.dll");
327 mp_msg(MSGT_MENCODER
,MSGL_ERR
,"unable to load qtmlClient.dll\n");
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");
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
);
352 vf_info_t ve_info_qtvideo
= {
353 "Quicktime video encoder using win32 DLLs",
356 "for internal use by mencoder",
360 //===========================================================================//