sync with ffmpeg
[mplayer/glamo.git] / libmpcodecs / ve_vfw.c
blobefdac241b6b39acac49336898bbee4c59d720610
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <inttypes.h>
6 #include <sys/stat.h>
8 #include "config.h"
10 #include "mp_msg.h"
11 #include "help_mp.h"
13 #include "codec-cfg.h"
14 //#include "stream/stream.h"
15 //#include "libmpdemux/demuxer.h"
16 //#include "libmpdemux/stheader.h"
18 #include "loader/loader.h"
19 //#include "loader/wine/mmreg.h"
20 #include "loader/wine/vfw.h"
21 #include "libmpdemux/aviheader.h"
22 #include "loader/wine/winerror.h"
23 #include "loader/wine/objbase.h"
25 #include "img_format.h"
26 #include "mp_image.h"
27 #include "vf.h"
29 #include "stream/stream.h"
30 #include "libmpdemux/muxer.h"
32 //===========================================================================//
34 static char *vfw_param_codec = NULL;
35 static char *vfw_param_compdata = NULL;
36 static HRESULT CoInitRes = -1;
38 #include "m_option.h"
40 m_option_t vfwopts_conf[]={
41 {"codec", &vfw_param_codec, CONF_TYPE_STRING, 0, 0, 0, NULL},
42 {"compdata", &vfw_param_compdata, CONF_TYPE_STRING, 0, 0, 0, NULL},
43 {NULL, NULL, 0, 0, 0, 0, NULL}
46 struct vf_priv_s {
47 muxer_stream_t* mux;
48 BITMAPINFOHEADER* bih;
51 static HIC encoder_hic;
52 static void* encoder_buf=NULL;
53 static int encoder_buf_size=0;
54 static int encoder_frameno=0;
56 //int init_vfw_encoder(char *dll_name, BITMAPINFOHEADER *input_bih, BITMAPINFOHEADER *output_bih)
57 static BITMAPINFOHEADER* vfw_open_encoder(char *dll_name, char *compdatafile, BITMAPINFOHEADER *input_bih,unsigned int out_fourcc)
59 HRESULT ret;
60 BITMAPINFOHEADER* output_bih=NULL;
61 int temp_len;
62 FILE *fd=NULL;
63 char *drvdata=NULL;
64 struct stat st;
66 //sh_video = malloc(sizeof(sh_video_t));
68 mp_msg(MSGT_WIN32,MSGL_V,"======= Win32 (VFW) VIDEO Encoder init =======\n");
69 CoInitRes = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
70 // memset(&sh_video->o_bih, 0, sizeof(BITMAPINFOHEADER));
71 // output_bih->biSize = sizeof(BITMAPINFOHEADER);
73 // encoder_hic = ICOpen( 0x63646976, out_fourcc, ICMODE_COMPRESS);
74 encoder_hic = ICOpen( (long) dll_name, out_fourcc, ICMODE_COMPRESS);
75 if(!encoder_hic){
76 mp_msg(MSGT_WIN32,MSGL_ERR,"ICOpen failed! unknown codec / wrong parameters?\n");
77 return NULL;
79 mp_msg(MSGT_WIN32,MSGL_INFO,"HIC: %x\n", encoder_hic);
81 #if 1
83 ICINFO icinfo;
85 ret = ICGetInfo(encoder_hic, &icinfo, sizeof(ICINFO));
86 mp_msg(MSGT_WIN32,MSGL_INFO,"%ld - %ld - %d\n", ret, icinfo.dwSize, sizeof(ICINFO));
87 mp_msg(MSGT_WIN32,MSGL_INFO,MSGTR_MPCODECS_CompressorType, icinfo.fccType);
88 mp_msg(MSGT_WIN32,MSGL_INFO,MSGTR_MPCODECS_CompressorSubtype, icinfo.fccHandler);
89 mp_msg(MSGT_WIN32,MSGL_INFO,MSGTR_MPCODECS_CompressorFlags,
90 icinfo.dwFlags, icinfo.dwVersion, icinfo.dwVersionICM);
91 //printf("Compressor name: %s\n", icinfo.szName);
92 //printf("Compressor description: %s\n", icinfo.szDescription);
94 mp_msg(MSGT_WIN32,MSGL_INFO,MSGTR_MPCODECS_Flags);
95 if (icinfo.dwFlags & VIDCF_QUALITY)
96 mp_msg(MSGT_WIN32,MSGL_INFO,MSGTR_MPCODECS_Quality);
97 if (icinfo.dwFlags & VIDCF_FASTTEMPORALD)
98 mp_msg(MSGT_WIN32,MSGL_INFO," fast-decompr");
99 if (icinfo.dwFlags & VIDCF_QUALITYTIME)
100 mp_msg(MSGT_WIN32,MSGL_INFO," temp-quality");
101 mp_msg(MSGT_WIN32,MSGL_INFO,"\n");
103 #endif
105 if(compdatafile){
106 if (!strncmp(compdatafile, "dialog", 6)){
107 if (ICSendMessage(encoder_hic, ICM_CONFIGURE, -1, 0) != ICERR_OK){
108 mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor doesn't have a configure dialog!\n");
109 return NULL;
111 if (ICSendMessage(encoder_hic, ICM_CONFIGURE, 0, 0) != ICERR_OK){
112 mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor configure dialog failed!\n");
113 return NULL;
116 else {
117 if (stat(compdatafile, &st) < 0){
118 mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor data file not found!\n");
119 return NULL;
121 fd = fopen(compdatafile, "rb");
122 if (!fd){
123 mp_msg(MSGT_WIN32,MSGL_ERR,"Cannot open Compressor data file!\n");
124 return NULL;
126 drvdata = (char *) malloc(st.st_size);
127 if (fread(drvdata, st.st_size, 1, fd) != 1) {
128 mp_msg(MSGT_WIN32,MSGL_ERR,"Cannot read Compressor data file!\n");
129 fclose(fd);
130 free(drvdata);
131 return NULL;
133 fclose(fd);
134 mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor data %d bytes\n", st.st_size);
135 if (!(temp_len = (unsigned int) ICSendMessage(encoder_hic, ICM_SETSTATE, (LPARAM) drvdata, (int) st.st_size))){
136 mp_msg(MSGT_WIN32,MSGL_ERR,"ICSetState failed!\n");
137 free(drvdata);
138 return NULL;
140 free(drvdata);
141 mp_msg(MSGT_WIN32,MSGL_INFO,"ICSetState ret: %d\n", temp_len);
145 temp_len = ICCompressGetFormatSize(encoder_hic, input_bih);
146 mp_msg(MSGT_WIN32,MSGL_INFO,"ICCompressGetFormatSize ret: %d\n", temp_len);
148 if (temp_len < sizeof(BITMAPINFOHEADER)) temp_len=sizeof(BITMAPINFOHEADER);
150 output_bih = malloc(temp_len+4);
151 memset(output_bih,0,temp_len);
152 output_bih->biSize = temp_len; //sizeof(BITMAPINFOHEADER);
154 return output_bih;
157 static int vfw_start_encoder(BITMAPINFOHEADER *input_bih, BITMAPINFOHEADER *output_bih){
158 HRESULT ret;
159 int temp_len=output_bih->biSize;
160 int i;
162 ret = ICCompressGetFormat(encoder_hic, input_bih, output_bih);
163 if(ret < 0){
164 unsigned char* temp=(unsigned char*)output_bih;
165 mp_msg(MSGT_WIN32,MSGL_ERR,"ICCompressGetFormat failed: Error %d (0x%X)\n", (int)ret, (int)ret);
166 for (i=0; i < temp_len; i++) mp_msg(MSGT_WIN32, MSGL_DBG2, "%02x ", temp[i]);
167 return 0;
169 mp_msg(MSGT_WIN32,MSGL_V,"ICCompressGetFormat OK\n");
171 if (temp_len > sizeof(BITMAPINFOHEADER))
173 unsigned char* temp=(unsigned char*)output_bih;
174 mp_msg(MSGT_WIN32, MSGL_V, "Extra info in o_bih (%d bytes)!\n",
175 temp_len-sizeof(BITMAPINFOHEADER));
176 for(i=sizeof(output_bih);i<temp_len;i++) mp_msg(MSGT_WIN32, MSGL_DBG2, "%02X ",temp[i]);
179 // if( mp_msg_test(MSGT_WIN32,MSGL_V) ) {
180 printf("Starting compression:\n");
181 printf(" Input format:\n");
182 printf(" biSize %ld\n", input_bih->biSize);
183 printf(" biWidth %ld\n", input_bih->biWidth);
184 printf(" biHeight %ld\n", input_bih->biHeight);
185 printf(" biPlanes %d\n", input_bih->biPlanes);
186 printf(" biBitCount %d\n", input_bih->biBitCount);
187 printf(" biCompression 0x%lx ('%.4s')\n", input_bih->biCompression, (char *)&input_bih->biCompression);
188 printf(" biSizeImage %ld\n", input_bih->biSizeImage);
189 printf(" Output format:\n");
190 printf(" biSize %ld\n", output_bih->biSize);
191 printf(" biWidth %ld\n", output_bih->biWidth);
192 printf(" biHeight %ld\n", output_bih->biHeight);
193 printf(" biPlanes %d\n", output_bih->biPlanes);
194 printf(" biBitCount %d\n", output_bih->biBitCount);
195 printf(" biCompression 0x%lx ('%.4s')\n", output_bih->biCompression, (char *)&output_bih->biCompression);
196 printf(" biSizeImage %ld\n", output_bih->biSizeImage);
197 // }
199 output_bih->biWidth=input_bih->biWidth;
200 output_bih->biHeight=input_bih->biHeight;
202 ret = ICCompressQuery(encoder_hic, input_bih, output_bih);
203 if(ret){
204 mp_msg(MSGT_WIN32,MSGL_ERR,"ICCompressQuery failed: Error %d\n", (int)ret);
205 return 0;
206 } else
207 mp_msg(MSGT_WIN32,MSGL_V,"ICCompressQuery OK\n");
209 ret = ICCompressBegin(encoder_hic, input_bih, output_bih);
210 if(ret){
211 mp_msg(MSGT_WIN32,MSGL_ERR,"ICCompressBegin failed: Error %d\n", (int)ret);
212 // return 0;
213 } else
214 mp_msg(MSGT_WIN32,MSGL_V,"ICCompressBegin OK\n");
215 mp_msg(MSGT_WIN32,MSGL_INFO," Output format after query/begin:\n");
216 mp_msg(MSGT_WIN32,MSGL_INFO," biSize %ld\n", output_bih->biSize);
217 mp_msg(MSGT_WIN32,MSGL_INFO," biWidth %ld\n", output_bih->biWidth);
218 mp_msg(MSGT_WIN32,MSGL_INFO," biHeight %ld\n", output_bih->biHeight);
219 mp_msg(MSGT_WIN32,MSGL_INFO," biPlanes %d\n", output_bih->biPlanes);
220 mp_msg(MSGT_WIN32,MSGL_INFO," biBitCount %d\n", output_bih->biBitCount);
221 mp_msg(MSGT_WIN32,MSGL_INFO," biCompression 0x%lx ('%.4s')\n", output_bih->biCompression, (char *)&output_bih->biCompression);
222 mp_msg(MSGT_WIN32,MSGL_INFO," biSizeImage %ld\n", output_bih->biSizeImage);
224 encoder_buf_size=input_bih->biSizeImage;
225 encoder_buf=malloc(encoder_buf_size);
226 encoder_frameno=0;
228 mp_msg(MSGT_WIN32,MSGL_V,"VIDEO CODEC Init OK!!! ;-)\n");
229 return 1;
232 static int vfw_encode_frame(BITMAPINFOHEADER* biOutput,void* OutBuf,
233 BITMAPINFOHEADER* biInput,void* Image,
234 long* keyframe, int quality){
235 HRESULT ret;
237 //long VFWAPIV ICCompress(
238 // HIC hic,long dwFlags,LPBITMAPINFOHEADER lpbiOutput,void* lpOutputBuf,
239 // LPBITMAPINFOHEADER lpbiInput,void* lpImage,long* lpckid,
240 // long* lpdwFlags,long lFrameNum,long dwFrameSize,long dwQuality,
241 // LPBITMAPINFOHEADER lpbiInputPrev,void* lpImagePrev
242 //);
244 // printf("vfw_encode_frame(%p,%p, %p,%p, %p,%d)\n",biOutput,OutBuf,biInput,Image,keyframe,quality);
246 ret=ICCompress(encoder_hic, 0,
247 biOutput, OutBuf,
248 biInput, Image,
249 NULL, keyframe, encoder_frameno, 0, quality,
250 biInput, encoder_buf);
252 // printf("ok. size=%ld\n",biOutput->biSizeImage);
254 memcpy(encoder_buf,Image,encoder_buf_size);
255 ++encoder_frameno;
257 return (int)ret;
259 #define mux_v (vf->priv->mux)
260 #define vfw_bih (vf->priv->bih)
262 static int config(struct vf_instance_s* vf,
263 int width, int height, int d_width, int d_height,
264 unsigned int flags, unsigned int outfmt){
266 vfw_bih->biWidth=width;
267 vfw_bih->biHeight=height;
268 vfw_bih->biSizeImage=width*height*((vfw_bih->biBitCount+7)/8);
269 mux_v->aspect = (float)d_width/d_height;
271 if(!vfw_start_encoder(vfw_bih, mux_v->bih)) return 0;
273 // mux_v->bih->biWidth=width;
274 // mux_v->bih->biHeight=height;
275 // mux_v->bih->biSizeImage=width*height*((mux_v->bih->biBitCount+7)/8);
277 return 1;
280 static int control(struct vf_instance_s* vf, int request, void* data){
282 return CONTROL_UNKNOWN;
285 static int query_format(struct vf_instance_s* vf, unsigned int fmt){
286 if(fmt==IMGFMT_BGR24) return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_FLIPPED;
287 return 0;
290 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts){
291 long flags=0;
292 int ret;
293 // flip_upside_down(vo_image_ptr,vo_image_ptr,3*vo_w,vo_h); // dirty hack
294 ret=vfw_encode_frame(mux_v->bih, mux_v->buffer, vfw_bih, mpi->planes[0], &flags, 10000);
295 // if (ret != ICERR_OK)
296 // return 0;
297 muxer_write_chunk(mux_v,mux_v->bih->biSizeImage,flags, pts, pts);
298 return 1;
301 static void uninit(struct vf_instance_s* vf)
303 HRESULT ret;
305 if(encoder_hic){
306 if(encoder_buf){
307 ret=ICCompressEnd(encoder_hic);
308 if(ret) mp_msg(MSGT_WIN32, MSGL_WARN, "ICCompressEnd failed: %ld\n", ret);
309 free(encoder_buf);
310 encoder_buf=NULL;
312 ret=ICClose(encoder_hic);
313 if(ret) mp_msg(MSGT_WIN32, MSGL_WARN, "ICClose failed: %ld\n", ret);
314 encoder_hic=0;
315 if ((CoInitRes == S_OK) || (CoInitRes == S_FALSE)) CoUninitialize();
319 //===========================================================================//
321 static int vf_open(vf_instance_t *vf, char* args){
322 vf->config=config;
323 vf->default_caps=VFCAP_CONSTANT;
324 vf->control=control;
325 vf->query_format=query_format;
326 vf->put_image=put_image;
327 vf->uninit=uninit;
328 vf->priv=malloc(sizeof(struct vf_priv_s));
329 memset(vf->priv,0,sizeof(struct vf_priv_s));
330 vf->priv->mux=(muxer_stream_t*)args;
332 vfw_bih=calloc(1, sizeof(BITMAPINFOHEADER));
333 vfw_bih->biSize=sizeof(BITMAPINFOHEADER);
334 vfw_bih->biWidth=0; // FIXME ?
335 vfw_bih->biHeight=0;
336 vfw_bih->biPlanes=1;
337 vfw_bih->biBitCount=24;
338 vfw_bih->biCompression=0;
339 // vfw_bih->biSizeImage=vo_w*vo_h*((vfw_bih->biBitCount+7)/8);
341 if (!vfw_param_codec)
343 mp_msg(MSGT_WIN32,MSGL_WARN, MSGTR_MPCODECS_NoVfwCodecSpecified);
344 return 0;
346 // mux_v->bih=vfw_open_encoder("divxc32.dll",vfw_bih,mmioFOURCC('D', 'I', 'V', '3'));
347 // mux_v->bih=vfw_open_encoder("AvidAVICodec.dll",vfw_bih, 0);
348 mux_v->bih = vfw_open_encoder(vfw_param_codec, vfw_param_compdata, vfw_bih, 0);
349 if(!mux_v->bih) return 0;
351 return 1;
354 vf_info_t ve_info_vfw = {
355 "Win32/VfW encoders",
356 "vfw",
357 "A'rpi",
358 "for internal use by mencoder",
359 vf_open
362 //===========================================================================//