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