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