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