Merge svn changes up to r30463
[mplayer/kovensky.git] / libmpcodecs / ve_vfw.c
blobc04c6936a85673a817b7f52af022dac666d7d3bc
1 /*
2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <inttypes.h>
24 #include <sys/stat.h>
26 #include "config.h"
28 #include "mp_msg.h"
29 #include "help_mp.h"
31 #include "codec-cfg.h"
32 //#include "stream/stream.h"
33 //#include "libmpdemux/demuxer.h"
34 //#include "libmpdemux/stheader.h"
36 #include "loader/loader.h"
37 //#include "loader/wine/mmreg.h"
38 #include "loader/wine/vfw.h"
39 #include "libmpdemux/aviheader.h"
40 #include "loader/wine/winerror.h"
41 #include "loader/wine/objbase.h"
43 #include "img_format.h"
44 #include "mp_image.h"
45 #include "vf.h"
47 #include "stream/stream.h"
48 #include "libmpdemux/muxer.h"
50 //===========================================================================//
52 static char *vfw_param_codec = NULL;
53 static char *vfw_param_compdata = NULL;
54 static HRESULT CoInitRes = -1;
56 #include "m_option.h"
58 m_option_t vfwopts_conf[]={
59 {"codec", &vfw_param_codec, CONF_TYPE_STRING, 0, 0, 0, NULL},
60 {"compdata", &vfw_param_compdata, CONF_TYPE_STRING, 0, 0, 0, NULL},
61 {NULL, NULL, 0, 0, 0, 0, NULL}
64 struct vf_priv_s {
65 muxer_stream_t* mux;
66 BITMAPINFOHEADER* bih;
69 static HIC encoder_hic;
70 static void* encoder_buf=NULL;
71 static int encoder_buf_size=0;
72 static int encoder_frameno=0;
74 //int init_vfw_encoder(char *dll_name, BITMAPINFOHEADER *input_bih, BITMAPINFOHEADER *output_bih)
75 static BITMAPINFOHEADER* vfw_open_encoder(char *dll_name, char *compdatafile, BITMAPINFOHEADER *input_bih,unsigned int out_fourcc)
77 HRESULT ret;
78 BITMAPINFOHEADER* output_bih=NULL;
79 int temp_len;
80 FILE *fd=NULL;
81 char *drvdata=NULL;
82 struct stat st;
84 //sh_video = malloc(sizeof(sh_video_t));
86 mp_msg(MSGT_WIN32,MSGL_V,"======= Win32 (VFW) VIDEO Encoder init =======\n");
87 CoInitRes = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
88 // memset(&sh_video->o_bih, 0, sizeof(BITMAPINFOHEADER));
89 // output_bih->biSize = sizeof(BITMAPINFOHEADER);
91 // encoder_hic = ICOpen( 0x63646976, out_fourcc, ICMODE_COMPRESS);
92 encoder_hic = ICOpen( (long) dll_name, out_fourcc, ICMODE_COMPRESS);
93 if(!encoder_hic){
94 mp_msg(MSGT_WIN32,MSGL_ERR,"ICOpen failed! unknown codec / wrong parameters?\n");
95 return NULL;
97 mp_msg(MSGT_WIN32,MSGL_INFO,"HIC: %x\n", encoder_hic);
99 #if 1
101 ICINFO icinfo;
103 ret = ICGetInfo(encoder_hic, &icinfo, sizeof(ICINFO));
104 mp_msg(MSGT_WIN32,MSGL_INFO,"%ld - %ld - %d\n", ret, icinfo.dwSize, sizeof(ICINFO));
105 mp_tmsg(MSGT_WIN32,MSGL_INFO,"Compressor type: %.4lx\n", icinfo.fccType);
106 mp_tmsg(MSGT_WIN32,MSGL_INFO,"Compressor subtype: %.4lx\n", icinfo.fccHandler);
107 mp_tmsg(MSGT_WIN32,MSGL_INFO,"Compressor flags: %lu, version %lu, ICM version: %lu\n",
108 icinfo.dwFlags, icinfo.dwVersion, icinfo.dwVersionICM);
109 //printf("Compressor name: %s\n", icinfo.szName);
110 //printf("Compressor description: %s\n", icinfo.szDescription);
112 mp_tmsg(MSGT_WIN32,MSGL_INFO,"Flags:");
113 if (icinfo.dwFlags & VIDCF_QUALITY)
114 mp_tmsg(MSGT_WIN32,MSGL_INFO," quality");
115 if (icinfo.dwFlags & VIDCF_FASTTEMPORALD)
116 mp_msg(MSGT_WIN32,MSGL_INFO," fast-decompr");
117 if (icinfo.dwFlags & VIDCF_QUALITYTIME)
118 mp_msg(MSGT_WIN32,MSGL_INFO," temp-quality");
119 mp_msg(MSGT_WIN32,MSGL_INFO,"\n");
121 #endif
123 if(compdatafile){
124 if (!strncmp(compdatafile, "dialog", 6)){
125 if (ICSendMessage(encoder_hic, ICM_CONFIGURE, -1, 0) != ICERR_OK){
126 mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor doesn't have a configure dialog!\n");
127 return NULL;
129 if (ICSendMessage(encoder_hic, ICM_CONFIGURE, 0, 0) != ICERR_OK){
130 mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor configure dialog failed!\n");
131 return NULL;
134 else {
135 if (stat(compdatafile, &st) < 0){
136 mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor data file not found!\n");
137 return NULL;
139 fd = fopen(compdatafile, "rb");
140 if (!fd){
141 mp_msg(MSGT_WIN32,MSGL_ERR,"Cannot open Compressor data file!\n");
142 return NULL;
144 drvdata = (char *) malloc(st.st_size);
145 if (fread(drvdata, st.st_size, 1, fd) != 1) {
146 mp_msg(MSGT_WIN32,MSGL_ERR,"Cannot read Compressor data file!\n");
147 fclose(fd);
148 free(drvdata);
149 return NULL;
151 fclose(fd);
152 mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor data %d bytes\n", st.st_size);
153 if (!(temp_len = (unsigned int) ICSendMessage(encoder_hic, ICM_SETSTATE, (LPARAM) drvdata, (int) st.st_size))){
154 mp_msg(MSGT_WIN32,MSGL_ERR,"ICSetState failed!\n");
155 free(drvdata);
156 return NULL;
158 free(drvdata);
159 mp_msg(MSGT_WIN32,MSGL_INFO,"ICSetState ret: %d\n", temp_len);
163 temp_len = ICCompressGetFormatSize(encoder_hic, input_bih);
164 mp_msg(MSGT_WIN32,MSGL_INFO,"ICCompressGetFormatSize ret: %d\n", temp_len);
166 if (temp_len < sizeof(BITMAPINFOHEADER)) temp_len=sizeof(BITMAPINFOHEADER);
168 output_bih = malloc(temp_len+4);
169 memset(output_bih,0,temp_len);
170 output_bih->biSize = temp_len; //sizeof(BITMAPINFOHEADER);
172 return output_bih;
175 static int vfw_start_encoder(BITMAPINFOHEADER *input_bih, BITMAPINFOHEADER *output_bih){
176 HRESULT ret;
177 int temp_len=output_bih->biSize;
178 int i;
180 ret = ICCompressGetFormat(encoder_hic, input_bih, output_bih);
181 if(ret < 0){
182 unsigned char* temp=(unsigned char*)output_bih;
183 mp_msg(MSGT_WIN32,MSGL_ERR,"ICCompressGetFormat failed: Error %d (0x%X)\n", (int)ret, (int)ret);
184 for (i=0; i < temp_len; i++) mp_msg(MSGT_WIN32, MSGL_DBG2, "%02x ", temp[i]);
185 return 0;
187 mp_msg(MSGT_WIN32,MSGL_V,"ICCompressGetFormat OK\n");
189 if (temp_len > sizeof(BITMAPINFOHEADER))
191 unsigned char* temp=(unsigned char*)output_bih;
192 mp_msg(MSGT_WIN32, MSGL_V, "Extra info in o_bih (%d bytes)!\n",
193 temp_len-sizeof(BITMAPINFOHEADER));
194 for(i=sizeof(output_bih);i<temp_len;i++) mp_msg(MSGT_WIN32, MSGL_DBG2, "%02X ",temp[i]);
197 // if( mp_msg_test(MSGT_WIN32,MSGL_V) ) {
198 printf("Starting compression:\n");
199 printf(" Input format:\n");
200 printf(" biSize %ld\n", input_bih->biSize);
201 printf(" biWidth %ld\n", input_bih->biWidth);
202 printf(" biHeight %ld\n", input_bih->biHeight);
203 printf(" biPlanes %d\n", input_bih->biPlanes);
204 printf(" biBitCount %d\n", input_bih->biBitCount);
205 printf(" biCompression 0x%lx ('%.4s')\n", input_bih->biCompression, (char *)&input_bih->biCompression);
206 printf(" biSizeImage %ld\n", input_bih->biSizeImage);
207 printf(" Output format:\n");
208 printf(" biSize %ld\n", output_bih->biSize);
209 printf(" biWidth %ld\n", output_bih->biWidth);
210 printf(" biHeight %ld\n", output_bih->biHeight);
211 printf(" biPlanes %d\n", output_bih->biPlanes);
212 printf(" biBitCount %d\n", output_bih->biBitCount);
213 printf(" biCompression 0x%lx ('%.4s')\n", output_bih->biCompression, (char *)&output_bih->biCompression);
214 printf(" biSizeImage %ld\n", output_bih->biSizeImage);
215 // }
217 output_bih->biWidth=input_bih->biWidth;
218 output_bih->biHeight=input_bih->biHeight;
220 ret = ICCompressQuery(encoder_hic, input_bih, output_bih);
221 if(ret){
222 mp_msg(MSGT_WIN32,MSGL_ERR,"ICCompressQuery failed: Error %d\n", (int)ret);
223 return 0;
224 } else
225 mp_msg(MSGT_WIN32,MSGL_V,"ICCompressQuery OK\n");
227 ret = ICCompressBegin(encoder_hic, input_bih, output_bih);
228 if(ret){
229 mp_msg(MSGT_WIN32,MSGL_ERR,"ICCompressBegin failed: Error %d\n", (int)ret);
230 // return 0;
231 } else
232 mp_msg(MSGT_WIN32,MSGL_V,"ICCompressBegin OK\n");
233 mp_msg(MSGT_WIN32,MSGL_INFO," Output format after query/begin:\n");
234 mp_msg(MSGT_WIN32,MSGL_INFO," biSize %ld\n", output_bih->biSize);
235 mp_msg(MSGT_WIN32,MSGL_INFO," biWidth %ld\n", output_bih->biWidth);
236 mp_msg(MSGT_WIN32,MSGL_INFO," biHeight %ld\n", output_bih->biHeight);
237 mp_msg(MSGT_WIN32,MSGL_INFO," biPlanes %d\n", output_bih->biPlanes);
238 mp_msg(MSGT_WIN32,MSGL_INFO," biBitCount %d\n", output_bih->biBitCount);
239 mp_msg(MSGT_WIN32,MSGL_INFO," biCompression 0x%lx ('%.4s')\n", output_bih->biCompression, (char *)&output_bih->biCompression);
240 mp_msg(MSGT_WIN32,MSGL_INFO," biSizeImage %ld\n", output_bih->biSizeImage);
242 encoder_buf_size=input_bih->biSizeImage;
243 encoder_buf=malloc(encoder_buf_size);
244 encoder_frameno=0;
246 mp_msg(MSGT_WIN32,MSGL_V,"VIDEO CODEC Init OK!!! ;-)\n");
247 return 1;
250 static int vfw_encode_frame(BITMAPINFOHEADER* biOutput,void* OutBuf,
251 BITMAPINFOHEADER* biInput,void* Image,
252 long* keyframe, int quality){
253 HRESULT ret;
255 //long VFWAPIV ICCompress(
256 // HIC hic,long dwFlags,LPBITMAPINFOHEADER lpbiOutput,void* lpOutputBuf,
257 // LPBITMAPINFOHEADER lpbiInput,void* lpImage,long* lpckid,
258 // long* lpdwFlags,long lFrameNum,long dwFrameSize,long dwQuality,
259 // LPBITMAPINFOHEADER lpbiInputPrev,void* lpImagePrev
260 //);
262 // printf("vfw_encode_frame(%p,%p, %p,%p, %p,%d)\n",biOutput,OutBuf,biInput,Image,keyframe,quality);
264 ret=ICCompress(encoder_hic, 0,
265 biOutput, OutBuf,
266 biInput, Image,
267 NULL, keyframe, encoder_frameno, 0, quality,
268 biInput, encoder_buf);
270 // printf("ok. size=%ld\n",biOutput->biSizeImage);
272 memcpy(encoder_buf,Image,encoder_buf_size);
273 ++encoder_frameno;
275 return (int)ret;
277 #define mux_v (vf->priv->mux)
278 #define vfw_bih (vf->priv->bih)
280 static int config(struct vf_instance* vf,
281 int width, int height, int d_width, int d_height,
282 unsigned int flags, unsigned int outfmt){
284 vfw_bih->biWidth=width;
285 vfw_bih->biHeight=height;
286 vfw_bih->biSizeImage=width*height*((vfw_bih->biBitCount+7)/8);
287 mux_v->aspect = (float)d_width/d_height;
289 if(!vfw_start_encoder(vfw_bih, mux_v->bih)) return 0;
291 // mux_v->bih->biWidth=width;
292 // mux_v->bih->biHeight=height;
293 // mux_v->bih->biSizeImage=width*height*((mux_v->bih->biBitCount+7)/8);
295 return 1;
298 static int control(struct vf_instance* vf, int request, void* data){
300 return CONTROL_UNKNOWN;
303 static int query_format(struct vf_instance* vf, unsigned int fmt){
304 if(fmt==IMGFMT_BGR24) return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_FLIPPED;
305 return 0;
308 static int put_image(struct vf_instance* vf, mp_image_t *mpi, double pts){
309 long flags=0;
310 int ret;
311 // flip_upside_down(vo_image_ptr,vo_image_ptr,3*vo_w,vo_h); // dirty hack
312 ret=vfw_encode_frame(mux_v->bih, mux_v->buffer, vfw_bih, mpi->planes[0], &flags, 10000);
313 // if (ret != ICERR_OK)
314 // return 0;
315 muxer_write_chunk(mux_v,mux_v->bih->biSizeImage,flags, pts, pts);
316 return 1;
319 static void uninit(struct vf_instance* vf)
321 HRESULT ret;
323 if(encoder_hic){
324 if(encoder_buf){
325 ret=ICCompressEnd(encoder_hic);
326 if(ret) mp_msg(MSGT_WIN32, MSGL_WARN, "ICCompressEnd failed: %ld\n", ret);
327 free(encoder_buf);
328 encoder_buf=NULL;
330 ret=ICClose(encoder_hic);
331 if(ret) mp_msg(MSGT_WIN32, MSGL_WARN, "ICClose failed: %ld\n", ret);
332 encoder_hic=0;
333 if ((CoInitRes == S_OK) || (CoInitRes == S_FALSE)) CoUninitialize();
337 //===========================================================================//
339 static int vf_open(vf_instance_t *vf, char* args){
340 vf->config=config;
341 vf->default_caps=VFCAP_CONSTANT;
342 vf->control=control;
343 vf->query_format=query_format;
344 vf->put_image=put_image;
345 vf->uninit=uninit;
346 vf->priv=malloc(sizeof(struct vf_priv_s));
347 memset(vf->priv,0,sizeof(struct vf_priv_s));
348 vf->priv->mux=(muxer_stream_t*)args;
350 vfw_bih=calloc(1, sizeof(BITMAPINFOHEADER));
351 vfw_bih->biSize=sizeof(BITMAPINFOHEADER);
352 vfw_bih->biWidth=0; // FIXME ?
353 vfw_bih->biHeight=0;
354 vfw_bih->biPlanes=1;
355 vfw_bih->biBitCount=24;
356 vfw_bih->biCompression=0;
357 // vfw_bih->biSizeImage=vo_w*vo_h*((vfw_bih->biBitCount+7)/8);
359 if (!vfw_param_codec)
361 mp_tmsg(MSGT_WIN32,MSGL_WARN, "[VE_RAW] Required VfW codec not specified!!\n");
362 return 0;
364 // mux_v->bih=vfw_open_encoder("divxc32.dll",vfw_bih,mmioFOURCC('D', 'I', 'V', '3'));
365 // mux_v->bih=vfw_open_encoder("AvidAVICodec.dll",vfw_bih, 0);
366 mux_v->bih = vfw_open_encoder(vfw_param_codec, vfw_param_compdata, vfw_bih, 0);
367 if(!mux_v->bih) return 0;
369 return 1;
372 vf_info_t ve_info_vfw = {
373 "Win32/VfW encoders",
374 "vfw",
375 "A'rpi",
376 "for internal use by mencoder",
377 vf_open
380 //===========================================================================//