1 /***************************************************************************
2 ffv1codec
3
4 Interface to lavcodec codec family
5 -------------------
6 begin : Fri Jul 28 2003
7 copyright : (C) 2003 by mean
8 email : fixounet@free.fr
9 ***************************************************************************/
10
11 /***************************************************************************
12 * *
13 * This program is free software; you can redistribute it and/or modify *
14 * it under the terms of the GNU General Public License as published by *
15 * the Free Software Foundation; either version 2 of the License, or *
16 * (at your option) any later version. *
17 * *
18 ***************************************************************************/
19
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <time.h>
26 #include <assert.h>
27 #include <xvid.h>
28 #include "../../config.h"
29 #include "avcodec.h"
30
31 #include "ffv1.h"
32
33 static int _w,_h;
34 AVCodecContext *_context;
35 AVFrame _frame;
36 int pagesize=0;
37 void YU_YV12_mmx(unsigned char *in,unsigned char *out, int w,int h);
38 /**********Xvid **********/
39 #ifdef USE_XVID_4
40 static xvid_gbl_init_t xvid_gbl_init2;
41 static xvid_enc_create_t xvid_enc_create;
42 static xvid_plugin_single_t single;
43 static xvid_enc_plugin_t plugins[7];
44 static xvid_enc_frame_t xvid_enc_frame;
45 static xvid_enc_stats_t xvid_enc_stats;
46 static xvid_gbl_info_t xvid_gbl_info;
47 #define MMSET(x) memset(&x,0,sizeof(x))
48 #else
49 static XVID_ENC_FRAME fr;
50 static XVID_ENC_PARAM xparam;
51 static XVID_ENC_STATS xstats;
52 #endif
53 static void *xvid_handle=0;
54 static int nextIsKF=0;
55 static v4linfo vinfo;
56 #ifndef USE_XVID_4
57 static int const divx4_motion_presets[7] = {
58 0,
59 PMV_EARLYSTOP16,
60 PMV_EARLYSTOP16 | PMV_ADVANCEDDIAMOND16,
61 PMV_EARLYSTOP16 | PMV_HALFPELREFINE16,
62 PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EARLYSTOP8 |
63 PMV_HALFPELREFINE8,
64 PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EARLYSTOP8 |
65 PMV_HALFPELREFINE8,
66 PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | PMV_EXTSEARCH16 | PMV_EARLYSTOP8 |
67 PMV_HALFPELREFINE8
68 };
69
70 static int const divx4_general_presets[7] = {
71 0,
72 0,
73 0,
74 0 | XVID_HALFPEL,
75 0 | XVID_INTER4V | XVID_HALFPEL,
76 0 | XVID_INTER4V | XVID_HALFPEL,
77 0 | XVID_INTER4V | XVID_HALFPEL
78 };
79 #else
80 static const int X4motion_presets[] = {
81 0,
82 0,
83 0,
84 0,
85 XVID_ME_HALFPELREFINE16,
86 XVID_ME_HALFPELREFINE16 | XVID_ME_ADVANCEDDIAMOND16,
87 XVID_ME_HALFPELREFINE16 | XVID_ME_EXTSEARCH16 |
88 XVID_ME_HALFPELREFINE8 | XVID_ME_USESQUARES16
89 };
90 #endif
91
92 /*----------------------*/
93 typedef enum
94 {
95 FF_HUFF=1,
96 FF_FFV1=2,
97 FF_MJPEG=3,
98 FF_MPEG4=4,
99 FF_XVID=5,
100 FF_FFHUFF=6,
101 FF_MPEG1=7,
102 FF_MPEG2=8
103 } FFCODEC;
104
105 typedef struct codecName
106 {
107 FFCODEC codec;
108 char *name;
109 }codecName;
110
111 codecName listOfCodec[]=
112 {
113 {FF_HUFF,"HUFFYUV"},
114 {FF_FFHUFF,"FFHUFF"},
115 {FF_FFV1,"FFV1"},
116 {FF_MJPEG,"MJPEG"},
117 {FF_MPEG4,"MPEG4"},
118 {FF_XVID,"XVID"},
119 {FF_MPEG1,"MPEG1"},
120 {FF_MPEG2,"MPEG2"},
121 };
122
123 FFCODEC codec=FF_FFV1;
124 /****************************************
125
126 ***************************************/
127
FFV1_selectByName(char * name)128 int FFV1_selectByName( char *name)
129 {
130 unsigned int i;
131 for(i=0;i<sizeof(listOfCodec)/sizeof(codecName);i++)
132 {
133 if(!strcmp(name,listOfCodec[i].name))
134 {
135 codec=listOfCodec[i].codec;
136 return 1;
137 }
138
139 }
140 return 0;
141 }
142 /****************************************
143
144 ***************************************/
145
146 #ifdef USE_XVID_4
FFV1_XvidCompress(unsigned char * in,unsigned char * out,uint32_t * outlen)147 int FFV1_XvidCompress(unsigned char *in,unsigned char *out,uint32_t *outlen)
148 {
149 int ret;
150
151 MMSET(xvid_enc_frame);
152 MMSET(xvid_enc_stats);
153
154 xvid_enc_frame.version = XVID_VERSION;
155 xvid_enc_stats.version = XVID_VERSION;
156 xvid_enc_frame.length = 0;
157 xvid_enc_frame.vop_flags|=XVID_VOP_HALFPEL;
158 if(vinfo.quant)
159 xvid_enc_frame.vol_flags|=XVID_VOL_MPEGQUANT;
160
161 xvid_enc_frame.input.csp = XVID_CSP_YV12;
162 xvid_enc_frame.input.stride[0] = _w;
163 xvid_enc_frame.input.stride[1] = _w>>1;
164 xvid_enc_frame.input.stride[2] = _w>>1;
165 xvid_enc_frame.type = XVID_TYPE_AUTO;
166
167
168 /* Set up motion estimation flags */
169 xvid_enc_frame.input.plane[0] = in;
170 xvid_enc_frame.input.plane[2] = in+(_w*_h);
171 xvid_enc_frame.input.plane[1] = in+((_w*_h*5)>>2);
172
173 xvid_enc_frame.bitstream = out;
174
175 xvid_enc_frame.quant = vinfo.quality;
176 xvid_enc_frame.motion = X4motion_presets[vinfo.me];
177 if(nextIsKF)
178 {
179 xvid_enc_frame.type = XVID_TYPE_IVOP; // let the codec decide between I-frame (1) and P-frame (0)
180 nextIsKF=0;
181 }
182 else
183 {
184 xvid_enc_frame.type = XVID_TYPE_VOL; // let the codec decide between I-frame (1) and P-frame (0)
185 }
186
187
188 ret = xvid_encore(xvid_handle, XVID_ENC_ENCODE, &xvid_enc_frame,
189 &xvid_enc_stats);
190 *outlen = ret;
191 #ifdef ADM_DEBUG
192 printf("Outlen: %lu\n",*outlen);
193 #endif
194
195 return 1;
196
197 }
198
199 #else //xvid 0.9
200
FFV1_XvidCompress(unsigned char * in,unsigned char * out,uint32_t * outlen)201 int FFV1_XvidCompress(unsigned char *in,unsigned char *out,uint32_t *outlen)
202 {
203 XVID_ENC_FRAME xframe;
204
205 int xerr;
206 memset(&xframe,0,sizeof(xframe));
207
208 xframe.general = divx4_general_presets[vinfo.me];
209 xframe.motion = divx4_motion_presets[vinfo.me];
210
211 xframe.general |= XVID_H263QUANT;// + XVID_INTERLACING;
212
213 xframe.bitstream = out;
214 xframe.length = -1; // this is written by the routine
215
216 xframe.image = in;
217 xframe.colorspace = XVID_CSP_I420; // defined in <xvid.h>
218
219 if(nextIsKF)
220 {
221 xframe.intra = 1; // let the codec decide between I-frame (1) and P-frame (0)
222 nextIsKF=0;
223 }
224 else
225 {
226 xframe.intra = -1; // let the codec decide between I-frame (1) and P-frame (0)
227 }
228 xframe.quant = vinfo.quality;
229 // xframe.quant = QUANTI; // is quant != 0, use a fixed quant (and ignore bitrate)
230
231
232 xerr =xvid_encore(xvid_handle, XVID_ENC_ENCODE, &xframe, &xstats);
233 assert(XVID_ERR_OK==xerr);
234 *outlen = xframe.length;
235
236
237 return 1;
238
239 }
240 #endif
241 /*-------------------------------------------------------------------------*/
FFV1_Compress(unsigned char * in,unsigned char * out,uint32_t * outlen)242 int FFV1_Compress(unsigned char *in,unsigned char *out,uint32_t *outlen)
243 {
244 uint32_t sz;
245 unsigned char *src;
246
247 if(codec==FF_XVID)
248 {
249 return FFV1_XvidCompress(in,out,outlen);
250 }
251 #ifdef CONVERT_YUV
252 static char tmp[720*576*3];
253 #endif
254
255 _frame.linesize[0]=_w;
256 _frame.linesize[1]=_w>>1;
257 _frame.linesize[2]=_w>>1;
258 _frame.pts = AV_NOPTS_VALUE;
259 _frame.quality=vinfo.quality;
260
261 // printf("\n in Qual : %f \n",_frame.quality);
262
263 #ifdef CONVERT_YUV
264 src=tmp;
265 YU_YV12_mmx(in,tmp, _w,_h);
266 #else
267 src=in;
268 #endif
269
270 _frame.data[0]=(uint8_t *)src;
271 _frame.data[1]=(uint8_t *)src+pagesize;
272 _frame.data[2]=(uint8_t *)src+pagesize+(pagesize>>2);
273
274 if(nextIsKF)
275 {
276 _frame.key_frame = 1;
277 _frame.pict_type=FF_I_TYPE;
278 nextIsKF=0;
279 }
280 else
281 {
282 _frame.pict_type=0;
283 _frame.key_frame = 0;
284 }
285 if( (sz=avcodec_encode_video( _context,
286 (uint8_t *)out,
287 _w*_h*3,
288 &_frame))<0)
289 {
290
291 printf("error encoding !\n");
292 exit(3);
293 }
294 //printf("\n out Qual : %f \n",_context->coded_frame->quality);
295
296 *outlen=sz;
297 return 1;
298 }
299 /*
300
301 __________________________________________
302 */
303
304 #ifdef USE_XVID_4
FFV1_XvidInit(v4linfo * info)305 int FFV1_XvidInit(v4linfo *info)
306 {
307 int err;
308 printf("Initializing Xvid4 with width =%d, height = %d in YUV420P format\n",info->width,info->height);
309
310
311 MMSET(xvid_gbl_init2);
312 MMSET(xvid_gbl_info);
313
314 printf("Initializing global xvid 4\n");
315 xvid_gbl_init2.version = XVID_VERSION;
316 xvid_global(NULL, XVID_GBL_INIT, &xvid_gbl_init2, NULL);
317 xvid_gbl_info.version = XVID_VERSION;
318 xvid_global(NULL, XVID_GBL_INFO, &xvid_gbl_info, NULL);
319 if(xvid_gbl_info.build)
320 {
321 printf("\txvid build:%s\n",xvid_gbl_info.build);
322 }
323 printf("\txvid thread:%d\n",xvid_gbl_info.num_threads);
324 printf("\txvid SIMD supported:(%x)\n",xvid_gbl_info.cpu_flags);
325
326
327 //
328 MMSET(xvid_enc_create);
329 xvid_enc_create.version = XVID_VERSION;
330 xvid_enc_create.width = info->width;
331 xvid_enc_create.height = info->height;
332 MMSET(single);
333
334
335 plugins[0].func = xvid_plugin_single;
336 plugins[0].param = &single;
337
338 single.version = XVID_VERSION;
339 single.bitrate = 1500;
340
341 xvid_enc_create.plugins = plugins;
342 xvid_enc_create.num_plugins = 1;
343 if(info->ntsc)
344 xvid_enc_create.fbase =29970;
345 else
346 xvid_enc_create.fbase =25000;
347 //Framerate
348 xvid_enc_create.fincr = 1000;
349
350 //
351
352 //
353 err = xvid_encore(NULL, XVID_ENC_CREATE, &xvid_enc_create, NULL);
354 if(err<0)
355 {
356 printf("Xvid-4 init error :%d\n",err);
357 return 0;
358
359 }
360
361 xvid_handle = xvid_enc_create.handle;
362
363 printf("Xvid-4 CQ init Ok\n");
364 return 1;
365
366 }
367 #else
FFV1_XvidInit(v4linfo * info)368 int FFV1_XvidInit(v4linfo *info)
369 {
370 int err;
371 printf("Initializing Xvid with width =%d, height = %d in YUV420P format\n",info->width,info->height);
372
373 XVID_INIT_PARAM xinit;
374
375 memset(&xinit,0,sizeof(xinit));
376 memset(&fr, 0, sizeof(fr));
377
378 xinit.cpu_flags = XVID_CPU_MMX;
379 xvid_init(NULL, 0, &xinit, NULL);
380
381 xparam.fincr = 1000;
382 if(info->ntsc)
383 xparam.fbase =29970;
384 else
385 xparam.fbase =25000;
386 xparam.width = info->width;
387 xparam.height = info->height;
388 xparam.min_quantizer = info->quality;
389 xparam.max_quantizer = info->quality;
390 xparam.max_key_interval = info->keydist;
391 err = xvid_encore(NULL, XVID_ENC_CREATE, &xparam, NULL);
392 if( XVID_ERR_OK!=err)
393 {
394 printf("\n Error initializing xvid !!!\n");
395 return 0;
396 }
397 xvid_handle=xparam.handle;
398 printf("Xvid successfully initialized\n");
399 return 1;
400
401 }
402 #endif
FFV1_Init(v4linfo * info)403 int FFV1_Init(v4linfo *info)
404 {
405 int res;
406 _w=info->width;
407 _h=info->height;
408 memcpy(&vinfo,info,sizeof(vinfo));
409
410 printf("Quality : %d \n",vinfo.quality);
411 printf("Keydist : %d \n",vinfo.keydist);
412 printf("ME : %d \n",vinfo.me);
413 printf("Mpeg Qz : %d \n",vinfo.quant);
414 if(codec==FF_XVID)
415 return FFV1_XvidInit(info);
416
417 printf("Initializing ffv1 with width =%d, height = %d in YUV420P format\n",info->width,info->height);
418 _context=avcodec_alloc_context();
419 memset(&_frame,0,sizeof(_frame));
420 if(info->ntsc)
421 _context->time_base= (AVRational){1000,29970};
422 //_context->frame_rate = 29970;
423 else
424 _context->time_base= (AVRational){1000,25000};
425 //_context->frame_rate = 25000;
426 _context->width=info->width;
427 _context->height=info->height;
428 //_context->frame_rate_base=1000;
429 _context->strict_std_compliance=-2;
430
431 pagesize=info->width*info->height;
432 _context->pix_fmt = PIX_FMT_YUV420P; //PIX_FMT_YV12;
433 _context->flags = CODEC_FLAG_QSCALE;
434
435 /*S.Ellis: For FFVHUFF context_model=1 gives much better compression */
436 if(codec==FF_FFHUFF) {
437 _context->context_model=1;
438 _context->prediction_method=2;
439 }
440
441 switch(codec)
442 {
443 case FF_HUFF: res=avcodec_open(_context,&huffyuv_encoder);break;
444 case FF_FFHUFF: res=avcodec_open(_context,&ffvhuff_encoder);break;
445 case FF_FFV1: res=avcodec_open(_context,&ffv1_encoder);break;
446 case FF_MJPEG: res=avcodec_open(_context,&mjpeg_encoder);break;
447 case FF_MPEG4: res=avcodec_open(_context,&mpeg4_encoder);break;
448 case FF_MPEG1: res=avcodec_open(_context,&mpeg1video_encoder);break;
449 case FF_MPEG2: res=avcodec_open(_context,&mpeg2video_encoder);break;
450 default: assert(0);
451 }
452
453 if(res<0)
454 {
455 printf("cannot init ffencoder");
456 return 0;
457
458 }
459 _w=info->width;
460 _h=info->height;
461 printf("FFV1 init successfull\n");
462 return 1;
463 }
464 /*---------------------------------------------------------*/
getVideoFourCC(void)465 unsigned long int getVideoFourCC( void )
466 {
467 switch(codec)
468 {
469 case FF_HUFF: return 'UYFH';
470 case FF_FFHUFF: return 'HVFF';
471 case FF_FFV1: return '1VFF';
472 case FF_MJPEG: return 'GPJM';
473 case FF_MPEG4: return 'XVID';
474 case FF_XVID: return 'DIVX';
475 case FF_MPEG1: return 'GEPM';
476 case FF_MPEG2: return 'GEPM';
477 default: assert(0);
478 }
479 return 0;
480 }
481 /*---------------------------------------------------------*/
getVideoData(char ** data)482 unsigned long int getVideoData( char **data )
483 {
484 if(codec==FF_XVID) return 0;
485 *data=(char *)_context->extradata;
486 return _context->extradata_size;
487
488 }
FFV1_videoForceKeyFrame(void)489 void FFV1_videoForceKeyFrame( void )
490 {
491 nextIsKF=1;
492 }
493 // eof
494