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
24 #include "divx4_vbr.h"
29 //#include "transcode.h"
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 */
68 /*static int m_iCrispness;*/
70 static float m_fQuant
;
72 static int64_t m_lEncodedBits
;
73 static int64_t m_lExpectedBits
;
78 static entry
*m_vFrames
;
79 static long lFrameStart
;
81 static int iNumFrames
;
85 void VbrControl_init_1pass_vbr(int quality
, int crispness
)
87 m_fQuant
=min_quantizer
+((max_quantizer
-min_quantizer
)/6.)*(6-quality
);
90 VbrControl_update_1pass_vbr();
93 int VbrControl_init_2pass_vbr_analysis(const char *filename
, int quality
)
95 m_pFile
=fopen(filename
, "wb");
100 fprintf(m_pFile
, "##version 1\n");
101 fprintf(m_pFile
, "quality %d\n", quality
);
105 int VbrControl_init_2pass_vbr_encoding(const char *filename
, int bitrate
, double framerate
, int crispness
, int quality
)
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.;
118 int64_t desired_bits
;
119 int64_t non_text_bits
;
121 float average_complexity
;
123 m_pFile
=fopen(filename
, "rb");
129 fread(head
, 10, 1, m_pFile
);
130 if(!strncmp("##version ", head
, 10))
134 float old_qual
, new_qual
;
135 fscanf(m_pFile
, "%d\n", &version
);
136 fscanf(m_pFile
, "quality %d\n", &iOldQual
);
173 qual_multiplier
=new_qual
/old_qual
;
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);
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);
205 m_vFrames
= (entry
*)malloc(iNumFrames
*sizeof(entry
));
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
;
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
)
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++)
245 VbrControl_set_quant(m_fQuant);
250 desired_bits
-= non_text_bits
;
252 BRIEF EXPLANATION OF WHAT'S GOING ON HERE.
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
++)
275 if(m_vFrames
[i
].is_key_frame
)
277 if((i
+1<iNumFrames
) && (m_vFrames
[i
+1].is_key_frame
))
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)
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");
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
);
314 VbrControl_set_quant(m_fQuant
*m_vFrames
[0].mult
);
315 m_lEncodedBits
=m_lExpectedBits
=0;
319 int VbrControl_get_intra()
321 return m_vFrames
[m_iCount
].is_key_frame
;
324 short VbrControl_get_drop()
329 int VbrControl_get_quant()
334 void VbrControl_set_quant(float quant
)
337 if((rand() % 10)<((quant
-m_iQuant
) * 10))
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
);
349 void VbrControl_update_2pass_vbr_analysis(int is_key_frame
, int motion_bits
, int texture_bits
, int total_bits
, int quant
)
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
);
358 void VbrControl_update_2pass_vbr_encoding(int motion_bits
, int texture_bits
, int total_bits
)
363 if(m_iCount
>=iNumFrames
)
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
;
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
);
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
;
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
390 fprintf(m_pFile
, "Progress: expected %12lld, achieved %12lld, dq %f",
391 m_lExpectedBits
, m_lEncodedBits
, dq
);
393 VbrControl_set_quant(q
);
395 fprintf(m_pFile
, ", new quant %d\n", m_iQuant
);
398 void VbrControl_close()