libcdio
[mplayer.git] / divx4_vbr.c
blob467f77691016846de261f082e35fda0f5654fd6d
1 /*
2 * divx4_vbr.c
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file COPYING in the main directory of the Linux
6 * distribution for more details.
8 * 2-pass code OpenDivX port:
9 * Copyright (C) 2001 Christoph Lampert <gruel@gmx.de>
11 * Large parts of this code were taken from VbrControl() from the OpenDivX
12 * project, (C) divxnetworks, written by Eugene Kuznetsov <ekuznetsov@divxnetworks.com>
13 * with the permission of Darrius "Junto" Thompson, Director DivX
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21 #include <math.h>
22 #include <inttypes.h>
24 #include "divx4_vbr.h"
26 #include "mp_msg.h"
27 #include "help_mp.h"
29 //#include "transcode.h"
31 #define FALSE 0
32 #define TRUE 1
34 /* Absolute maximum and minimum quantizers used in VBR modes */
35 static const int min_quantizer=1;
36 static const int max_quantizer=31;
38 /* Limits on frame-level deviation of quantizer ( higher values
39 correspond to frames with more changes and vice versa ) */
40 static const float min_quant_delta=-10.f;
41 static const float max_quant_delta=5.f;
42 /* Limits on stream-level deviation of quantizer ( used to make
43 overall bitrate of stream close to requested value ) */
44 static const float min_rc_quant_delta=.6f;
45 static const float max_rc_quant_delta=1.5f;
47 /* Crispness parameter controls threshold for decision whether
48 to skip the frame or to code it. */
49 //static const float max_crispness=100.f;
50 /* Maximum allowed number of skipped frames in a line. */
51 //static const int max_drops_line=0; // CHL We don't drop frames at the moment!
54 typedef struct entry_s
55 /* max 28 bytes/frame or 5 Mb for 2-hour movie */
57 int quant;
58 int text_bits;
59 int motion_bits;
60 int total_bits;
61 float mult;
62 short is_key_frame;
63 short drop;
64 } entry;
66 static int m_iCount;
67 static int m_iQuant;
68 /*static int m_iCrispness;*/
69 static short m_bDrop;
70 static float m_fQuant;
72 static int64_t m_lEncodedBits;
73 static int64_t m_lExpectedBits;
75 static FILE *m_pFile;
77 static entry vFrame;
78 static entry *m_vFrames;
79 static long lFrameStart;
81 static int iNumFrames;
82 static int dummy;
85 void VbrControl_init_1pass_vbr(int quality, int crispness)
87 m_fQuant=min_quantizer+((max_quantizer-min_quantizer)/6.)*(6-quality);
88 m_iCount=0;
89 m_bDrop=FALSE;
90 VbrControl_update_1pass_vbr();
93 int VbrControl_init_2pass_vbr_analysis(const char *filename, int quality)
95 m_pFile=fopen(filename, "wb");
96 if(m_pFile==0)
97 return -1;
98 m_iCount=0;
99 m_bDrop=FALSE;
100 fprintf(m_pFile, "##version 1\n");
101 fprintf(m_pFile, "quality %d\n", quality);
102 return 0;
105 int VbrControl_init_2pass_vbr_encoding(const char *filename, int bitrate, double framerate, int crispness, int quality)
107 int i;
109 int64_t text_bits=0;
110 int64_t total_bits=0;
111 int64_t complexity=0;
112 int64_t new_complexity=0;
113 int64_t motion_bits=0;
114 int64_t denominator=0;
115 float qual_multiplier=1.;
116 char head[20];
118 int64_t desired_bits;
119 int64_t non_text_bits;
121 float average_complexity;
123 m_pFile=fopen(filename, "rb");
124 if(m_pFile==0)
125 return -1;
126 m_bDrop=FALSE;
127 m_iCount=0;
129 fread(head, 10, 1, m_pFile);
130 if(!strncmp("##version ", head, 10))
132 int version;
133 int iOldQual;
134 float old_qual, new_qual;
135 fscanf(m_pFile, "%d\n", &version);
136 fscanf(m_pFile, "quality %d\n", &iOldQual);
137 switch(iOldQual)
139 case 5:
140 old_qual=1.f;
141 break;
142 case 4:
143 old_qual=1.1f;
144 break;
145 case 3:
146 old_qual=1.25f;
147 break;
148 case 2:
149 old_qual=1.4f;
150 break;
151 case 1:
152 old_qual=2.f;
153 break;
155 switch(quality)
157 case 5:
158 new_qual=1.f;
159 break;
160 case 4:
161 new_qual=1.1f;
162 break;
163 case 3:
164 new_qual=1.25f;
165 break;
166 case 2:
167 new_qual=1.4f;
168 break;
169 case 1:
170 new_qual=2.f;
171 break;
173 qual_multiplier=new_qual/old_qual;
175 else
176 fseek(m_pFile, 0, SEEK_SET);
178 lFrameStart=ftell(m_pFile); // save current position
180 /* removed C++ dependencies, now read file twice :-( */
183 while(!feof(m_pFile))
184 { fscanf(m_pFile, "Frame %d: intra %hd, quant %d, texture %d, motion %d, total %d\n",
185 &iNumFrames, &(vFrame.is_key_frame), &(vFrame.quant), &(vFrame.text_bits), &(vFrame.motion_bits), &(vFrame.total_bits));
187 vFrame.total_bits+=vFrame.text_bits*(qual_multiplier-1);
188 vFrame.text_bits*=qual_multiplier;
189 text_bits +=(int64_t)vFrame.text_bits;
190 motion_bits += (int64_t)vFrame.motion_bits;
191 total_bits +=(int64_t)vFrame.total_bits;
192 complexity +=(int64_t)vFrame.text_bits*vFrame.quant;
194 // printf("Frames %d, texture %d, motion %d, quant %d total %d ",
195 // iNumFrames, vFrame.text_bits, vFrame.motion_bits, vFrame.quant, vFrame.total_bits);
196 // printf("texture %d, total %d, complexity %lld \n",vFrame.text_bits,vFrame.total_bits, complexity);
198 iNumFrames++;
199 average_complexity=complexity/iNumFrames;
201 // if (verbose & TC_DEBUG) {
202 // fprintf(stderr, "(%s) frames %d, texture %lld, motion %lld, total %lld, complexity %lld\n", __FILE__, iNumFrames, text_bits, motion_bits, total_bits, complexity);
203 // }
205 m_vFrames = (entry*)malloc(iNumFrames*sizeof(entry));
206 if (!m_vFrames)
207 { mp_msg(MSGT_FIXME, MSGL_FIXME,MSGTR_OutOfMemory);
208 return -2; //TC_EXPORT_ERROR;
211 fseek(m_pFile, lFrameStart, SEEK_SET); // start again
213 for (i=0;i<iNumFrames;i++)
214 { fscanf(m_pFile, "Frame %d: intra %hd, quant %d, texture %d, motion %d, total %d\n",
215 &dummy, &(m_vFrames[i].is_key_frame), &(m_vFrames[i].quant),
216 &(m_vFrames[i].text_bits), &(m_vFrames[i].motion_bits),
217 &(m_vFrames[i].total_bits));
219 m_vFrames[i].total_bits += m_vFrames[i].text_bits*(qual_multiplier-1);
220 m_vFrames[i].text_bits *= qual_multiplier;
223 if (m_pFile)
224 { fclose(m_pFile);
225 m_pFile=NULL;
228 desired_bits=(int64_t)bitrate*(int64_t)iNumFrames/framerate;
229 non_text_bits=total_bits-text_bits;
231 if(desired_bits<=non_text_bits)
233 /* char s[200];*/
234 mp_msg(MSGT_FIXME, MSGL_FIXME, MSGTR_OverridingTooLowBitrate,
235 (float)(non_text_bits*framerate/(int64_t)iNumFrames));
237 desired_bits=non_text_bits*3/2;
239 m_fQuant=max_quantizer;
240 for(int i=0; i<iNumFrames; i++)
242 m_vFrames[i].drop=0;
243 m_vFrames[i].mult=1;
245 VbrControl_set_quant(m_fQuant);
246 return 0;
250 desired_bits -= non_text_bits;
252 BRIEF EXPLANATION OF WHAT'S GOING ON HERE.
253 We assume that
254 text_bits=complexity / quantizer
255 total_bits-text_bits = const(complexity)
256 where 'complexity' is a characteristic of the frame
257 and does not depend much on quantizer dynamics.
258 Using this equation, we calculate 'average' quantizer
259 to be used for encoding ( 1st order effect ).
260 Having constant quantizer for the entire stream is not
261 very convenient - reconstruction errors are
262 more noticeable in low-motion scenes. To compensate
263 this effect, we multiply quantizer for each frame by
264 (complexity/average_complexity)^k,
265 ( k - parameter of adjustment ). k=0 means 'no compensation'
266 and k=1 is 'constant bitrate mode'. We choose something in
267 between, like 0.5 ( 2nd order effect ).
270 average_complexity=complexity/iNumFrames;
272 for(i=0; i<iNumFrames; i++)
274 float mult;
275 if(m_vFrames[i].is_key_frame)
277 if((i+1<iNumFrames) && (m_vFrames[i+1].is_key_frame))
278 mult=1.25;
279 else
280 mult=.75;
282 else
284 mult=m_vFrames[i].text_bits*m_vFrames[i].quant;
285 mult=(float)sqrt(mult/average_complexity);
287 // if(i && m_vFrames[i-1].is_key_frame)
288 // mult *= 0.75;
289 if(mult<0.5)
290 mult=0.5;
291 if(mult>1.5)
292 mult=1.5;
295 m_vFrames[i].mult=mult;
296 m_vFrames[i].drop=FALSE;
297 new_complexity+=m_vFrames[i].text_bits*m_vFrames[i].quant;
299 denominator+=desired_bits*m_vFrames[i].mult/iNumFrames;
302 m_fQuant=((double)new_complexity)/(double)denominator;
304 if(m_fQuant<min_quantizer) m_fQuant=min_quantizer;
305 if(m_fQuant>max_quantizer) m_fQuant=max_quantizer;
306 m_pFile=fopen("analyse.log", "wb");
307 if(m_pFile)
309 fprintf(m_pFile, "Total frames: %d Avg quantizer: %f\n",
310 iNumFrames, m_fQuant);
311 fprintf(m_pFile, "Expecting %12lld bits\n", desired_bits+non_text_bits);
312 fflush(m_pFile);
314 VbrControl_set_quant(m_fQuant*m_vFrames[0].mult);
315 m_lEncodedBits=m_lExpectedBits=0;
316 return 0;
319 int VbrControl_get_intra()
321 return m_vFrames[m_iCount].is_key_frame;
324 short VbrControl_get_drop()
326 return m_bDrop;
329 int VbrControl_get_quant()
331 return m_iQuant;
334 void VbrControl_set_quant(float quant)
336 m_iQuant=quant;
337 if((rand() % 10)<((quant-m_iQuant) * 10))
338 m_iQuant++;
339 if(m_iQuant<min_quantizer) m_iQuant=min_quantizer;
340 if(m_iQuant>max_quantizer) m_iQuant=max_quantizer;
343 void VbrControl_update_1pass_vbr()
345 VbrControl_set_quant(m_fQuant);
346 m_iCount++;
349 void VbrControl_update_2pass_vbr_analysis(int is_key_frame, int motion_bits, int texture_bits, int total_bits, int quant)
351 if(!m_pFile)
352 return;
353 fprintf(m_pFile, "Frame %d: intra %d, quant %d, texture %d, motion %d, total %d\n",
354 m_iCount, is_key_frame, quant, texture_bits, motion_bits, total_bits);
355 m_iCount++;
358 void VbrControl_update_2pass_vbr_encoding(int motion_bits, int texture_bits, int total_bits)
360 double q;
361 double dq;
363 if(m_iCount>=iNumFrames)
364 return;
366 m_lExpectedBits+=(m_vFrames[m_iCount].total_bits-m_vFrames[m_iCount].text_bits)
367 + m_vFrames[m_iCount].text_bits*m_vFrames[m_iCount].quant/m_fQuant;
368 m_lEncodedBits+=(int64_t)total_bits;
370 if(m_pFile)
371 fprintf(m_pFile, "Frame %d: PRESENT, complexity %d, quant multiplier %f, texture %d, total %d ",
372 m_iCount, m_vFrames[m_iCount].text_bits*m_vFrames[m_iCount].quant,
373 m_vFrames[m_iCount].mult, texture_bits, total_bits);
375 m_iCount++;
377 q = m_fQuant * m_vFrames[m_iCount].mult;
378 if(q<m_fQuant+min_quant_delta) q=m_fQuant+min_quant_delta;
379 if(q>m_fQuant+max_quant_delta) q=m_fQuant+max_quant_delta;
381 dq = (double)m_lEncodedBits/(double)m_lExpectedBits;
382 dq*=dq;
383 if(dq<min_rc_quant_delta)
384 dq=min_rc_quant_delta;
385 if(dq>max_rc_quant_delta)
386 dq=max_rc_quant_delta;
387 if(m_iCount<20) // no framerate corrections in first frames
388 dq=1;
389 if(m_pFile)
390 fprintf(m_pFile, "Progress: expected %12lld, achieved %12lld, dq %f",
391 m_lExpectedBits, m_lEncodedBits, dq);
392 q *= dq;
393 VbrControl_set_quant(q);
394 if(m_pFile)
395 fprintf(m_pFile, ", new quant %d\n", m_iQuant);
398 void VbrControl_close()
400 if(m_pFile)
402 fclose(m_pFile);
403 m_pFile=NULL;
405 free(m_vFrames);