1 /***************************************************************************
2 \fn ADM_ffMpeg4
3 \brief Front end for libavcodec Mpeg4 asp encoder
4 -------------------
5
6 copyright : (C) 2002/2009 by mean
7 email : fixounet@free.fr
8 ***************************************************************************/
9
10 /***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
19 #include "ADM_default.h"
20 #include "ADM_ffMpeg4.h"
21 #undef ADM_MINIMAL_UI_INTERFACE // we need the full UI
22 #include "DIA_factory.h"
23
24 #if 1
25 #define aprintf(...) {}
26 #else
27 #define aprintf printf
28 #endif
29
30 FFcodecSettings Mp4Settings = MPEG4_CONF_DEFAULT;
31
32 /**
33 \fn ADM_ffMpeg4Encoder
34 */
ADM_ffMpeg4Encoder(ADM_coreVideoFilter * src,bool globalHeader)35 ADM_ffMpeg4Encoder::ADM_ffMpeg4Encoder(ADM_coreVideoFilter *src,bool globalHeader) : ADM_coreVideoEncoderFFmpeg(src,&Mp4Settings,globalHeader)
36 {
37 printf("[ffMpeg4Encoder] Creating.\n");
38
39
40 }
41
42 /**
43 \fn pre-open
44 */
configureContext(void)45 bool ADM_ffMpeg4Encoder::configureContext(void)
46 {
47
48 switch(Settings.params.mode)
49 {
50 case COMPRESS_2PASS:
51 case COMPRESS_2PASS_BITRATE:
52 if(false==setupPass())
53 {
54 printf("[ffmpeg] Multipass setup failed\n");
55 return false;
56 }
57 break;
58 case COMPRESS_SAME:
59 case COMPRESS_CQ:
60 _context->flags |= AV_CODEC_FLAG_QSCALE;
61 _context->bit_rate = 0;
62 break;
63 case COMPRESS_CBR:
64 _context->bit_rate=Settings.params.bitrate*1000; // kb->b;
65 break;
66 default:
67 return false;
68 }
69 presetContext(&Settings);
70
71 return true;
72 }
73
74 /**
75 \fn setup
76 */
setup(void)77 bool ADM_ffMpeg4Encoder::setup(void)
78 {
79
80 if(false== ADM_coreVideoEncoderFFmpeg::setup(AV_CODEC_ID_MPEG4))
81 return false;
82
83 printf("[ffMpeg] Setup ok\n");
84 return true;
85 }
86
87
88 /**
89 \fn ~ADM_ffMpeg4Encoder
90 */
~ADM_ffMpeg4Encoder()91 ADM_ffMpeg4Encoder::~ADM_ffMpeg4Encoder()
92 {
93 printf("[ffMpeg4Encoder] Destroying.\n");
94
95
96 }
97
98 /**
99 \fn encode
100 */
encode(ADMBitstream * out)101 bool ADM_ffMpeg4Encoder::encode (ADMBitstream * out)
102 {
103 int sz,q,r,gotData;
104 again:
105 sz=0;
106 if(false==preEncode()) // Pop - out the frames stored in the queue due to B-frames
107 {
108 r=encodeWrapper(NULL,out);
109 if(r<0)
110 {
111 ADM_warning("[ffMpeg4] Error %d encoding video\n",r);
112 return false;
113 }
114 sz=r;
115 printf("[ffmpeg4] Popping delayed bframes (%d)\n",sz);
116 goto link;
117 return false;
118 }
119 q=image->_Qp;
120
121 if(!q) q=2;
122 switch(Settings.params.mode)
123 {
124 case COMPRESS_SAME:
125 // Keep same frame type & same Qz as the incoming frame...
126 _frame->quality = (int) floor (FF_QP2LAMBDA * q+ 0.5);
127
128 if(image->flags & AVI_KEY_FRAME) _frame->pict_type = AV_PICTURE_TYPE_I;
129 else if(image->flags & AVI_B_FRAME) _frame->pict_type = AV_PICTURE_TYPE_B;
130 else _frame->pict_type = AV_PICTURE_TYPE_P;
131
132 break;
133 case COMPRESS_2PASS:
134 case COMPRESS_2PASS_BITRATE:
135 switch(pass)
136 {
137 case 1:
138 break;
139 case 2:
140 break; // Get Qz for this frame...
141 }
142 case COMPRESS_CQ:
143 _frame->quality = (int) floor (FF_QP2LAMBDA * Settings.params.qz+ 0.5);
144 break;
145 case COMPRESS_CBR:
146 break;
147 default:
148 printf("[ffMpeg4] Unsupported encoding mode\n");
149 return false;
150 }
151 aprintf("[CODEC] Flags = 0x%x, QSCALE=%x, bit_rate=%d, quality=%d qz=%d incoming qz=%d\n",_context->flags,CODEC_FLAG_QSCALE,
152 _context->bit_rate, _frame->quality, _frame->quality/ FF_QP2LAMBDA,q);
153
154 _frame->reordered_opaque=image->Pts;
155 r=encodeWrapper(_frame,out);
156 if(r<0)
157 {
158 ADM_warning("[ffMpeg4] Error %d encoding video\n",r);
159 return false;
160 }
161 sz=r;
162 if(sz==0) // no pic, probably pre filling, try again
163 goto again;
164 link:
165 return postEncode(out,sz);
166 }
167
168 /**
169 \fn isDualPass
170
171 */
isDualPass(void)172 bool ADM_ffMpeg4Encoder::isDualPass(void)
173 {
174 if(Settings.params.mode==COMPRESS_2PASS || Settings.params.mode==COMPRESS_2PASS_BITRATE ) return true;
175 return false;
176
177 }
178
179 /**
180 \fn jpegConfigure
181 \brief UI configuration for jpeg encoder
182 */
183
ffMpeg4Configure(void)184 bool ffMpeg4Configure(void)
185 {
186 diaMenuEntry qzE[]={
187 {0,QT_TRANSLATE_NOOP("ffmpeg4","H.263")},
188 {1,QT_TRANSLATE_NOOP("ffmpeg4","MPEG")}
189 };
190
191 diaMenuEntry rdE[]={
192 {0,QT_TRANSLATE_NOOP("ffmpeg4","MB comparison")},
193 {1,QT_TRANSLATE_NOOP("ffmpeg4","Fewest bits (vhq)")},
194 {2,QT_TRANSLATE_NOOP("ffmpeg4","Rate distortion")}
195 };
196 diaMenuEntry threads[]={
197 {0,QT_TRANSLATE_NOOP("ffmpeg4","One thread")},
198 {2,QT_TRANSLATE_NOOP("ffmpeg4","Two threads)")},
199 {3,QT_TRANSLATE_NOOP("ffmpeg4","Three threads")},
200 {99,QT_TRANSLATE_NOOP("ffmpeg4","Auto (#cpu)")}
201 };
202
203
204 FFcodecSettings *conf=&Mp4Settings;
205
206 #define PX(x) &(conf->lavcSettings.x)
207
208 diaElemBitrate bitrate(&(Mp4Settings.params),NULL);
209 diaElemMenu threadM(PX(MultiThreaded),QT_TRANSLATE_NOOP("ffmpeg4","Threading"),4,threads);
210 diaElemUInteger qminM(PX(qmin),QT_TRANSLATE_NOOP("ffmpeg4","Mi_n. quantizer:"),1,31);
211 diaElemUInteger qmaxM(PX(qmax),QT_TRANSLATE_NOOP("ffmpeg4","Ma_x. quantizer:"),1,31);
212 diaElemUInteger qdiffM(PX(max_qdiff),QT_TRANSLATE_NOOP("ffmpeg4","Max. quantizer _difference:"),1,31);
213
214 diaElemToggle fourMv(PX(_4MV),QT_TRANSLATE_NOOP("ffmpeg4","4_MV"));
215 diaElemToggle trellis(PX(_TRELLIS_QUANT),QT_TRANSLATE_NOOP("ffmpeg4","_Trellis quantization"));
216
217 diaElemToggle qpel(PX(_QPEL),QT_TRANSLATE_NOOP("ffmpeg4","_Quarter pixel"));
218
219 diaElemUInteger max_b_frames(PX(max_b_frames),QT_TRANSLATE_NOOP("ffmpeg4","_Number of B frames:"),0,32);
220 diaElemMenu qzM(PX(mpeg_quant),QT_TRANSLATE_NOOP("ffmpeg4","_Quantization type:"),2,qzE);
221
222 diaElemMenu rdM(PX(mb_eval),QT_TRANSLATE_NOOP("ffmpeg4","_Macroblock decision:"),3,rdE);
223
224 diaElemUInteger filetol(PX(vratetol),QT_TRANSLATE_NOOP("ffmpeg4","_Filesize tolerance (kb):"),0,100000);
225
226 diaElemFloat qzComp(PX(qcompress),QT_TRANSLATE_NOOP("ffmpeg4","_Quantizer compression:"),0,1);
227 diaElemFloat qzBlur(PX(qblur),QT_TRANSLATE_NOOP("ffmpeg4","Quantizer _blur:"),0,1);
228
229 diaElemUInteger GopSize(PX(gop_size),QT_TRANSLATE_NOOP("ffmpeg4","_Gop Size:"),1,500);
230 /* First Tab : encoding mode */
231 diaElem *diamode[]={&GopSize,&threadM,&bitrate};
232 diaElemTabs tabMode(QT_TRANSLATE_NOOP("ffmpeg4","User Interface"),3,diamode);
233
234 /* 2nd Tab : ME */
235 diaElemFrame frameMe(QT_TRANSLATE_NOOP("ffmpeg4","Advanced Simple Profile"));
236
237 frameMe.swallow(&max_b_frames);
238 frameMe.swallow(&qpel);
239
240 diaElem *diaME[]={&fourMv,&frameMe};
241 diaElemTabs tabME(QT_TRANSLATE_NOOP("ffmpeg4","Motion Estimation"),2,diaME);
242 /* 3nd Tab : Qz */
243
244 diaElem *diaQze[]={&qzM,&rdM,&qminM,&qmaxM,&qdiffM,&trellis};
245 diaElemTabs tabQz(QT_TRANSLATE_NOOP("ffmpeg4","Quantization"),6,diaQze);
246
247 /* 4th Tab : RControl */
248
249 diaElem *diaRC[]={&filetol,&qzComp,&qzBlur};
250 diaElemTabs tabRC(QT_TRANSLATE_NOOP("ffmpeg4","Rate Control"),3,diaRC);
251
252 diaElemTabs *tabs[]={&tabMode,&tabME,&tabQz,&tabRC};
253 if( diaFactoryRunTabs(QT_TRANSLATE_NOOP("ffmpeg4","libavcodec MPEG-4 configuration"),4,tabs))
254 {
255 return true;
256 }
257 return false;
258 }
259 // EOF
260