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.
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"
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;
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
}
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
)
78 BITMAPINFOHEADER
* output_bih
=NULL
;
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
);
94 mp_msg(MSGT_WIN32
,MSGL_ERR
,"ICOpen failed! unknown codec / wrong parameters?\n");
97 mp_msg(MSGT_WIN32
,MSGL_INFO
,"HIC: %x\n", encoder_hic
);
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");
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");
129 if (ICSendMessage(encoder_hic
, ICM_CONFIGURE
, 0, 0) != ICERR_OK
){
130 mp_msg(MSGT_WIN32
,MSGL_ERR
,"Compressor configure dialog failed!\n");
135 if (stat(compdatafile
, &st
) < 0){
136 mp_msg(MSGT_WIN32
,MSGL_ERR
,"Compressor data file not found!\n");
139 fd
= fopen(compdatafile
, "rb");
141 mp_msg(MSGT_WIN32
,MSGL_ERR
,"Cannot open Compressor data file!\n");
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");
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");
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);
175 static int vfw_start_encoder(BITMAPINFOHEADER
*input_bih
, BITMAPINFOHEADER
*output_bih
){
177 int temp_len
=output_bih
->biSize
;
180 ret
= ICCompressGetFormat(encoder_hic
, input_bih
, output_bih
);
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
]);
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
);
217 output_bih
->biWidth
=input_bih
->biWidth
;
218 output_bih
->biHeight
=input_bih
->biHeight
;
220 ret
= ICCompressQuery(encoder_hic
, input_bih
, output_bih
);
222 mp_msg(MSGT_WIN32
,MSGL_ERR
,"ICCompressQuery failed: Error %d\n", (int)ret
);
225 mp_msg(MSGT_WIN32
,MSGL_V
,"ICCompressQuery OK\n");
227 ret
= ICCompressBegin(encoder_hic
, input_bih
, output_bih
);
229 mp_msg(MSGT_WIN32
,MSGL_ERR
,"ICCompressBegin failed: Error %d\n", (int)ret
);
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
);
246 mp_msg(MSGT_WIN32
,MSGL_V
,"VIDEO CODEC Init OK!!! ;-)\n");
250 static int vfw_encode_frame(BITMAPINFOHEADER
* biOutput
,void* OutBuf
,
251 BITMAPINFOHEADER
* biInput
,void* Image
,
252 long* keyframe
, int quality
){
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
262 // printf("vfw_encode_frame(%p,%p, %p,%p, %p,%d)\n",biOutput,OutBuf,biInput,Image,keyframe,quality);
264 ret
=ICCompress(encoder_hic
, 0,
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
);
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);
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
;
308 static int put_image(struct vf_instance
* vf
, mp_image_t
*mpi
, double pts
){
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)
315 muxer_write_chunk(mux_v
,mux_v
->bih
->biSizeImage
,flags
, pts
, pts
);
319 static void uninit(struct vf_instance
* vf
)
325 ret
=ICCompressEnd(encoder_hic
);
326 if(ret
) mp_msg(MSGT_WIN32
, MSGL_WARN
, "ICCompressEnd failed: %ld\n", ret
);
330 ret
=ICClose(encoder_hic
);
331 if(ret
) mp_msg(MSGT_WIN32
, MSGL_WARN
, "ICClose failed: %ld\n", ret
);
333 if ((CoInitRes
== S_OK
) || (CoInitRes
== S_FALSE
)) CoUninitialize();
337 //===========================================================================//
339 static int vf_open(vf_instance_t
*vf
, char* args
){
341 vf
->default_caps
=VFCAP_CONSTANT
;
343 vf
->query_format
=query_format
;
344 vf
->put_image
=put_image
;
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 ?
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");
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;
372 vf_info_t ve_info_vfw
= {
373 "Win32/VfW encoders",
376 "for internal use by mencoder",
380 //===========================================================================//