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
const 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);
102
ret = ICGetInfo(encoder_hic, &icinfo, sizeof(ICINFO));
103
mp_msg(MSGT_WIN32,MSGL_INFO,"%ld - %ld - %d\n", ret, icinfo.dwSize, sizeof(ICINFO));
104
mp_msg(MSGT_WIN32,MSGL_INFO,MSGTR_MPCODECS_CompressorType, icinfo.fccType);
105
mp_msg(MSGT_WIN32,MSGL_INFO,MSGTR_MPCODECS_CompressorSubtype, icinfo.fccHandler);
106
mp_msg(MSGT_WIN32,MSGL_INFO,MSGTR_MPCODECS_CompressorFlags,
107
icinfo.dwFlags, icinfo.dwVersion, icinfo.dwVersionICM);
108
//printf("Compressor name: %s\n", icinfo.szName);
109
//printf("Compressor description: %s\n", icinfo.szDescription);
111
mp_msg(MSGT_WIN32,MSGL_INFO,MSGTR_MPCODECS_Flags);
112
if (icinfo.dwFlags & VIDCF_QUALITY)
113
mp_msg(MSGT_WIN32,MSGL_INFO,MSGTR_MPCODECS_Quality);
114
if (icinfo.dwFlags & VIDCF_FASTTEMPORALD)
115
mp_msg(MSGT_WIN32,MSGL_INFO," fast-decompr");
116
if (icinfo.dwFlags & VIDCF_QUALITYTIME)
117
mp_msg(MSGT_WIN32,MSGL_INFO," temp-quality");
118
mp_msg(MSGT_WIN32,MSGL_INFO,"\n");
122
if (!strncmp(compdatafile, "dialog", 6)){
123
if (ICSendMessage(encoder_hic, ICM_CONFIGURE, -1, 0) != ICERR_OK){
124
mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor doesn't have a configure dialog!\n");
127
if (ICSendMessage(encoder_hic, ICM_CONFIGURE, 0, 0) != ICERR_OK){
128
mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor configure dialog failed!\n");
133
if (stat(compdatafile, &st) < 0){
134
mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor data file not found!\n");
137
fd = fopen(compdatafile, "rb");
139
mp_msg(MSGT_WIN32,MSGL_ERR,"Cannot open Compressor data file!\n");
142
drvdata = malloc(st.st_size);
143
if (fread(drvdata, st.st_size, 1, fd) != 1) {
144
mp_msg(MSGT_WIN32,MSGL_ERR,"Cannot read Compressor data file!\n");
150
mp_msg(MSGT_WIN32,MSGL_ERR,"Compressor data %d bytes\n", st.st_size);
151
if (!(temp_len = (unsigned int) ICSendMessage(encoder_hic, ICM_SETSTATE, (LPARAM) drvdata, (int) st.st_size))){
152
mp_msg(MSGT_WIN32,MSGL_ERR,"ICSetState failed!\n");
157
mp_msg(MSGT_WIN32,MSGL_INFO,"ICSetState ret: %d\n", temp_len);
161
temp_len = ICCompressGetFormatSize(encoder_hic, input_bih);
162
mp_msg(MSGT_WIN32,MSGL_INFO,"ICCompressGetFormatSize ret: %d\n", temp_len);
164
if (temp_len < sizeof(BITMAPINFOHEADER)) temp_len=sizeof(BITMAPINFOHEADER);
166
output_bih = malloc(temp_len+4);
167
memset(output_bih,0,temp_len);
168
output_bih->biSize = temp_len; //sizeof(BITMAPINFOHEADER);
173
static int vfw_start_encoder(BITMAPINFOHEADER *input_bih, BITMAPINFOHEADER *output_bih){
175
int temp_len=output_bih->biSize;
178
ret = ICCompressGetFormat(encoder_hic, input_bih, output_bih);
180
unsigned char* temp=(unsigned char*)output_bih;
181
mp_msg(MSGT_WIN32,MSGL_ERR,"ICCompressGetFormat failed: Error %d (0x%X)\n", (int)ret, (int)ret);
182
for (i=0; i < temp_len; i++) mp_msg(MSGT_WIN32, MSGL_DBG2, "%02x ", temp[i]);
185
mp_msg(MSGT_WIN32,MSGL_V,"ICCompressGetFormat OK\n");
187
if (temp_len > sizeof(BITMAPINFOHEADER))
189
unsigned char* temp=(unsigned char*)output_bih;
190
mp_msg(MSGT_WIN32, MSGL_V, "Extra info in o_bih (%d bytes)!\n",
191
temp_len-sizeof(BITMAPINFOHEADER));
192
for(i=sizeof(output_bih);i<temp_len;i++) mp_msg(MSGT_WIN32, MSGL_DBG2, "%02X ",temp[i]);
195
// if( mp_msg_test(MSGT_WIN32,MSGL_V) ) {
196
printf("Starting compression:\n");
197
printf(" Input format:\n");
198
printf(" biSize %ld\n", input_bih->biSize);
199
printf(" biWidth %ld\n", input_bih->biWidth);
200
printf(" biHeight %ld\n", input_bih->biHeight);
201
printf(" biPlanes %d\n", input_bih->biPlanes);
202
printf(" biBitCount %d\n", input_bih->biBitCount);
203
printf(" biCompression 0x%lx ('%.4s')\n", input_bih->biCompression, (char *)&input_bih->biCompression);
204
printf(" biSizeImage %ld\n", input_bih->biSizeImage);
205
printf(" Output format:\n");
206
printf(" biSize %ld\n", output_bih->biSize);
207
printf(" biWidth %ld\n", output_bih->biWidth);
208
printf(" biHeight %ld\n", output_bih->biHeight);
209
printf(" biPlanes %d\n", output_bih->biPlanes);
210
printf(" biBitCount %d\n", output_bih->biBitCount);
211
printf(" biCompression 0x%lx ('%.4s')\n", output_bih->biCompression, (char *)&output_bih->biCompression);
212
printf(" biSizeImage %ld\n", output_bih->biSizeImage);
215
output_bih->biWidth=input_bih->biWidth;
216
output_bih->biHeight=input_bih->biHeight;
218
ret = ICCompressQuery(encoder_hic, input_bih, output_bih);
220
mp_msg(MSGT_WIN32,MSGL_ERR,"ICCompressQuery failed: Error %d\n", (int)ret);
223
mp_msg(MSGT_WIN32,MSGL_V,"ICCompressQuery OK\n");
225
ret = ICCompressBegin(encoder_hic, input_bih, output_bih);
227
mp_msg(MSGT_WIN32,MSGL_ERR,"ICCompressBegin failed: Error %d\n", (int)ret);
230
mp_msg(MSGT_WIN32,MSGL_V,"ICCompressBegin OK\n");
231
mp_msg(MSGT_WIN32,MSGL_INFO," Output format after query/begin:\n");
232
mp_msg(MSGT_WIN32,MSGL_INFO," biSize %ld\n", output_bih->biSize);
233
mp_msg(MSGT_WIN32,MSGL_INFO," biWidth %ld\n", output_bih->biWidth);
234
mp_msg(MSGT_WIN32,MSGL_INFO," biHeight %ld\n", output_bih->biHeight);
235
mp_msg(MSGT_WIN32,MSGL_INFO," biPlanes %d\n", output_bih->biPlanes);
236
mp_msg(MSGT_WIN32,MSGL_INFO," biBitCount %d\n", output_bih->biBitCount);
237
mp_msg(MSGT_WIN32,MSGL_INFO," biCompression 0x%lx ('%.4s')\n", output_bih->biCompression, (char *)&output_bih->biCompression);
238
mp_msg(MSGT_WIN32,MSGL_INFO," biSizeImage %ld\n", output_bih->biSizeImage);
240
encoder_buf_size=input_bih->biSizeImage;
241
encoder_buf=malloc(encoder_buf_size);
244
mp_msg(MSGT_WIN32,MSGL_V,"VIDEO CODEC Init OK!!! ;-)\n");
248
static int vfw_encode_frame(BITMAPINFOHEADER* biOutput,void* OutBuf,
249
BITMAPINFOHEADER* biInput,void* Image,
250
long* keyframe, int quality){
253
//long VFWAPIV ICCompress(
254
// HIC hic,long dwFlags,LPBITMAPINFOHEADER lpbiOutput,void* lpOutputBuf,
255
// LPBITMAPINFOHEADER lpbiInput,void* lpImage,long* lpckid,
256
// long* lpdwFlags,long lFrameNum,long dwFrameSize,long dwQuality,
257
// LPBITMAPINFOHEADER lpbiInputPrev,void* lpImagePrev
260
// printf("vfw_encode_frame(%p,%p, %p,%p, %p,%d)\n",biOutput,OutBuf,biInput,Image,keyframe,quality);
262
ret=ICCompress(encoder_hic, 0,
265
NULL, keyframe, encoder_frameno, 0, quality,
266
biInput, encoder_buf);
268
// printf("ok. size=%ld\n",biOutput->biSizeImage);
270
memcpy(encoder_buf,Image,encoder_buf_size);
275
#define mux_v (vf->priv->mux)
276
#define vfw_bih (vf->priv->bih)
278
static int config(struct vf_instance *vf,
279
int width, int height, int d_width, int d_height,
280
unsigned int flags, unsigned int outfmt){
282
vfw_bih->biWidth=width;
283
vfw_bih->biHeight=height;
284
vfw_bih->biSizeImage=width*height*((vfw_bih->biBitCount+7)/8);
285
mux_v->aspect = (float)d_width/d_height;
287
if(!vfw_start_encoder(vfw_bih, mux_v->bih)) return 0;
289
// mux_v->bih->biWidth=width;
290
// mux_v->bih->biHeight=height;
291
// mux_v->bih->biSizeImage=width*height*((mux_v->bih->biBitCount+7)/8);
296
static int control(struct vf_instance *vf, int request, void* data){
298
return CONTROL_UNKNOWN;
301
static int query_format(struct vf_instance *vf, unsigned int fmt){
302
if(fmt==IMGFMT_BGR24) return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_FLIPPED;
306
static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts){
309
// flip_upside_down(vo_image_ptr,vo_image_ptr,3*vo_w,vo_h); // dirty hack
310
ret=vfw_encode_frame(mux_v->bih, mux_v->buffer, vfw_bih, mpi->planes[0], &flags, 10000);
311
// if (ret != ICERR_OK)
313
muxer_write_chunk(mux_v,mux_v->bih->biSizeImage,flags, pts, pts);
317
static void uninit(struct vf_instance *vf)
323
ret=ICCompressEnd(encoder_hic);
324
if(ret) mp_msg(MSGT_WIN32, MSGL_WARN, "ICCompressEnd failed: %ld\n", ret);
328
ret=ICClose(encoder_hic);
329
if(ret) mp_msg(MSGT_WIN32, MSGL_WARN, "ICClose failed: %ld\n", ret);
331
if ((CoInitRes == S_OK) || (CoInitRes == S_FALSE)) CoUninitialize();
335
//===========================================================================//
337
static int vf_open(vf_instance_t *vf, char* args){
339
vf->default_caps=VFCAP_CONSTANT;
341
vf->query_format=query_format;
342
vf->put_image=put_image;
344
vf->priv=malloc(sizeof(struct vf_priv_s));
345
memset(vf->priv,0,sizeof(struct vf_priv_s));
346
vf->priv->mux=(muxer_stream_t*)args;
348
vfw_bih=calloc(1, sizeof(BITMAPINFOHEADER));
349
vfw_bih->biSize=sizeof(BITMAPINFOHEADER);
350
vfw_bih->biWidth=0; // FIXME ?
353
vfw_bih->biBitCount=24;
354
vfw_bih->biCompression=0;
355
// vfw_bih->biSizeImage=vo_w*vo_h*((vfw_bih->biBitCount+7)/8);
357
if (!vfw_param_codec)
359
mp_msg(MSGT_WIN32,MSGL_WARN, MSGTR_MPCODECS_NoVfwCodecSpecified);
362
// mux_v->bih=vfw_open_encoder("divxc32.dll",vfw_bih,mmioFOURCC('D', 'I', 'V', '3'));
363
// mux_v->bih=vfw_open_encoder("AvidAVICodec.dll",vfw_bih, 0);
364
mux_v->bih = vfw_open_encoder(vfw_param_codec, vfw_param_compdata, vfw_bih, 0);
365
if(!mux_v->bih) return 0;
370
const vf_info_t ve_info_vfw = {
371
"Win32/VfW encoders",
374
"for internal use by mencoder",
378
//===========================================================================//