comparison divx4_vbr.c @ 2641:41b67e5e5d38

initial import from transcode
author arpi
date Fri, 02 Nov 2001 23:53:44 +0000
parents
children 0e6e13261d79
comparison
equal deleted inserted replaced
2640:a6c378d5ed3a 2641:41b67e5e5d38
1 /*
2 * divx4_vbr.c
3 *
4 * Copyright (C) Thomas Östreich - June 2001
5 *
6 * 2-pass code OpenDivX port:
7 * Copyright (C) 2001 Christoph Lampert <gruel@gmx.de>
8 *
9 * This file is part of transcode, a linux video stream processing tool
10 *
11 * transcode is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * transcode is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with GNU Make; see the file COPYING. If not, write to
23 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 */
26
27
28 /**********************************************************
29 * Two-pass-code from OpenDivX *
30 * *
31 * Large parts of this code were taken from VbrControl() *
32 * from the OpenDivX project, (C) divxnetworks, *
33 * this code is published under DivX Open license, which *
34 * can be found... somewhere... oh, whatever... *
35 **********************************************************/
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <sys/stat.h>
40 #include <unistd.h>
41 #include <fcntl.h>
42 #include <dlfcn.h>
43 #include <math.h>
44
45 #include <stdint.h>
46
47 #include "config.h"
48 #include "transcode.h"
49
50 #define FALSE 0
51 #define TRUE 1
52
53 /* Absolute maximum and minimum quantizers used in VBR modes */
54 static const int min_quantizer=1;
55 static const int max_quantizer=31;
56
57 /* Limits on frame-level deviation of quantizer ( higher values
58 correspond to frames with more changes and vice versa ) */
59 static const float min_quant_delta=-10.f;
60 static const float max_quant_delta=5.f;
61 /* Limits on stream-level deviation of quantizer ( used to make
62 overall bitrate of stream close to requested value ) */
63 static const float min_rc_quant_delta=.6f;
64 static const float max_rc_quant_delta=1.5f;
65
66 /* Crispness parameter controls threshold for decision whether
67 to skip the frame or to code it. */
68 //static const float max_crispness=100.f;
69 /* Maximum allowed number of skipped frames in a line. */
70 //static const int max_drops_line=0; // CHL We don't drop frames at the moment!
71
72
73 typedef struct entry_s
74 /* max 28 bytes/frame or 5 Mb for 2-hour movie */
75 {
76 int quant;
77 int text_bits;
78 int motion_bits;
79 int total_bits;
80 float mult;
81 short is_key_frame;
82 short drop;
83 } entry;
84
85 int m_iCount;
86 int m_iQuant;
87 int m_iCrispness;
88 short m_bDrop;
89 float m_fQuant;
90
91 int64_t m_lEncodedBits;
92 int64_t m_lExpectedBits;
93
94 FILE *m_pFile;
95
96 entry vFrame;
97 entry *m_vFrames;
98 long lFrameStart;
99
100 int iNumFrames;
101 int dummy;
102
103 // methods from class VbrControl
104
105 void VbrControl_init_1pass_vbr(int quality, int crispness);
106 int VbrControl_init_2pass_vbr_encoding(const char* filename, int bitrate, double framerate, int crispness, int quality);
107 int VbrControl_init_2pass_vbr_analysis(const char* filename, int quality);
108
109 void VbrControl_update_1pass_vbr();
110 void VbrControl_update_2pass_vbr_encoding(int motion_bits, int texture_bits, int total_bits);
111 void VbrControl_update_2pass_vbr_analysis(int is_key_frame, int motion_bits, int texture_bits, int total_bits, int quant);
112
113 int VbrControl_get_quant();
114 void VbrControl_set_quant(float q);
115 int VbrControl_get_intra();
116 short VbrControl_get_drop();
117 void VbrControl_close();
118
119
120 void VbrControl_init_1pass_vbr(int quality, int crispness)
121 {
122 m_fQuant=min_quantizer+((max_quantizer-min_quantizer)/6.)*(6-quality);
123 m_iCount=0;
124 m_bDrop=FALSE;
125 VbrControl_update_1pass_vbr();
126 }
127
128 int VbrControl_init_2pass_vbr_analysis(const char *filename, int quality)
129 {
130 m_pFile=fopen(filename, "wb");
131 if(m_pFile==0)
132 return -1;
133 m_iCount=0;
134 m_bDrop=FALSE;
135 fprintf(m_pFile, "##version 1\n");
136 fprintf(m_pFile, "quality %d\n", quality);
137 return 0;
138 }
139
140 int VbrControl_init_2pass_vbr_encoding(const char *filename, int bitrate, double framerate, int crispness, int quality)
141 {
142 int i;
143
144 int64_t text_bits=0;
145 int64_t total_bits=0;
146 int64_t complexity=0;
147 int64_t new_complexity=0;
148 int64_t motion_bits=0;
149 int64_t denominator=0;
150 float qual_multiplier=1.;
151 char head[20];
152
153 int64_t desired_bits;
154 int64_t non_text_bits;
155
156 float average_complexity;
157
158 m_pFile=fopen(filename, "rb");
159 if(m_pFile==0)
160 return -1;
161 m_bDrop=FALSE;
162 m_iCount=0;
163
164 fread(head, 10, 1, m_pFile);
165 if(!strncmp("##version ", head, 10))
166 {
167 int version;
168 int iOldQual;
169 float old_qual, new_qual;
170 fscanf(m_pFile, "%d\n", &version);
171 fscanf(m_pFile, "quality %d\n", &iOldQual);
172 switch(iOldQual)
173 {
174 case 5:
175 old_qual=1.f;
176 break;
177 case 4:
178 old_qual=1.1f;
179 break;
180 case 3:
181 old_qual=1.25f;
182 break;
183 case 2:
184 old_qual=1.4f;
185 break;
186 case 1:
187 old_qual=2.f;
188 break;
189 }
190 switch(quality)
191 {
192 case 5:
193 new_qual=1.f;
194 break;
195 case 4:
196 new_qual=1.1f;
197 break;
198 case 3:
199 new_qual=1.25f;
200 break;
201 case 2:
202 new_qual=1.4f;
203 break;
204 case 1:
205 new_qual=2.f;
206 break;
207 }
208 qual_multiplier=new_qual/old_qual;
209 }
210 else
211 fseek(m_pFile, 0, SEEK_SET);
212
213 lFrameStart=ftell(m_pFile); // save current position
214
215 /* removed C++ dependencies, now read file twice :-( */
216
217
218 while(!feof(m_pFile))
219 { fscanf(m_pFile, "Frame %d: intra %d, quant %d, texture %d, motion %d, total %d\n",
220 &iNumFrames, &(vFrame.is_key_frame), &(vFrame.quant), &(vFrame.text_bits), &(vFrame.motion_bits), &(vFrame.total_bits));
221
222 vFrame.total_bits+=vFrame.text_bits*(qual_multiplier-1);
223 vFrame.text_bits*=qual_multiplier;
224 text_bits +=(int64_t)vFrame.text_bits;
225 motion_bits += (int64_t)vFrame.motion_bits;
226 total_bits +=(int64_t)vFrame.total_bits;
227 complexity +=(int64_t)vFrame.text_bits*vFrame.quant;
228
229 // printf("Frames %d, texture %d, motion %d, quant %d total %d ",
230 // iNumFrames, vFrame.text_bits, vFrame.motion_bits, vFrame.quant, vFrame.total_bits);
231 // printf("texture %d, total %d, complexity %lld \n",vFrame.text_bits,vFrame.total_bits, complexity);
232 }
233 iNumFrames++;
234 average_complexity=complexity/iNumFrames;
235
236 if (verbose & TC_DEBUG) {
237 fprintf(stderr, "(%s) frames %d, texture %lld, motion %lld, total %lld, complexity %lld\n", __FILE__, iNumFrames, text_bits, motion_bits, total_bits, complexity);
238 }
239
240 m_vFrames = (entry*)malloc(iNumFrames*sizeof(entry));
241 if (!m_vFrames)
242 { printf("out of memory");
243 return TC_EXPORT_ERROR;
244 }
245
246 fseek(m_pFile, lFrameStart, SEEK_SET); // start again
247
248 for (i=0;i<iNumFrames;i++)
249 { fscanf(m_pFile, "Frame %d: intra %d, quant %d, texture %d, motion %d, total %d\n",
250 &dummy, &(m_vFrames[i].is_key_frame), &(m_vFrames[i].quant),
251 &(m_vFrames[i].text_bits), &(m_vFrames[i].motion_bits),
252 &(m_vFrames[i].total_bits));
253
254 m_vFrames[i].total_bits += m_vFrames[i].text_bits*(qual_multiplier-1);
255 m_vFrames[i].text_bits *= qual_multiplier;
256 }
257
258 if (m_pFile)
259 { fclose(m_pFile);
260 m_pFile=NULL;
261 }
262
263 desired_bits=(int64_t)bitrate*(int64_t)iNumFrames/framerate;
264 non_text_bits=total_bits-text_bits;
265
266 if(desired_bits<=non_text_bits)
267 {
268 char s[200];
269 printf("Specified bitrate is too low for this clip.\n"
270 "Minimum possible bitrate for the clip is %.0f kbps. Overriding\n"
271 "user-specified value.\n",
272 (float)(non_text_bits*framerate/(int64_t)iNumFrames));
273
274 desired_bits=non_text_bits*3/2;
275 /*
276 m_fQuant=max_quantizer;
277 for(int i=0; i<iNumFrames; i++)
278 {
279 m_vFrames[i].drop=0;
280 m_vFrames[i].mult=1;
281 }
282 VbrControl_set_quant(m_fQuant);
283 return 0;
284 */
285 }
286
287 desired_bits -= non_text_bits;
288 /**
289 BRIEF EXPLANATION OF WHAT'S GOING ON HERE.
290 We assume that
291 text_bits=complexity / quantizer
292 total_bits-text_bits = const(complexity)
293 where 'complexity' is a characteristic of the frame
294 and does not depend much on quantizer dynamics.
295 Using this equation, we calculate 'average' quantizer
296 to be used for encoding ( 1st order effect ).
297 Having constant quantizer for the entire stream is not
298 very convenient - reconstruction errors are
299 more noticeable in low-motion scenes. To compensate
300 this effect, we multiply quantizer for each frame by
301 (complexity/average_complexity)^k,
302 ( k - parameter of adjustment ). k=0 means 'no compensation'
303 and k=1 is 'constant bitrate mode'. We choose something in
304 between, like 0.5 ( 2nd order effect ).
305 **/
306
307 average_complexity=complexity/iNumFrames;
308
309 for(i=0; i<iNumFrames; i++)
310 {
311 float mult;
312 if(m_vFrames[i].is_key_frame)
313 {
314 if((i+1<iNumFrames) && (m_vFrames[i+1].is_key_frame))
315 mult=1.25;
316 else
317 mult=.75;
318 }
319 else
320 {
321 mult=m_vFrames[i].text_bits*m_vFrames[i].quant;
322 mult=(float)sqrt(mult/average_complexity);
323
324 // if(i && m_vFrames[i-1].is_key_frame)
325 // mult *= 0.75;
326 if(mult<0.5)
327 mult=0.5;
328 if(mult>1.5)
329 mult=1.5;
330 }
331
332 m_vFrames[i].mult=mult;
333 m_vFrames[i].drop=FALSE;
334 new_complexity+=m_vFrames[i].text_bits*m_vFrames[i].quant;
335
336 denominator+=desired_bits*m_vFrames[i].mult/iNumFrames;
337 }
338
339 m_fQuant=((double)new_complexity)/(double)denominator;
340
341 if(m_fQuant<min_quantizer) m_fQuant=min_quantizer;
342 if(m_fQuant>max_quantizer) m_fQuant=max_quantizer;
343 m_pFile=fopen("analyse.log", "wb");
344 if(m_pFile)
345 {
346 fprintf(m_pFile, "Total frames: %d Avg quantizer: %f\n",
347 iNumFrames, m_fQuant);
348 fprintf(m_pFile, "Expecting %12lld bits\n", desired_bits+non_text_bits);
349 fflush(m_pFile);
350 }
351 VbrControl_set_quant(m_fQuant*m_vFrames[0].mult);
352 m_lEncodedBits=m_lExpectedBits=0;
353 return 0;
354 }
355
356 int VbrControl_get_intra()
357 {
358 return m_vFrames[m_iCount].is_key_frame;
359 }
360
361 short VbrControl_get_drop()
362 {
363 return m_bDrop;
364 }
365
366 int VbrControl_get_quant()
367 {
368 return m_iQuant;
369 }
370
371 void VbrControl_set_quant(float quant)
372 {
373 m_iQuant=quant;
374 if((rand() % 10)<((quant-m_iQuant) * 10))
375 m_iQuant++;
376 if(m_iQuant<min_quantizer) m_iQuant=min_quantizer;
377 if(m_iQuant>max_quantizer) m_iQuant=max_quantizer;
378 }
379
380 void VbrControl_update_1pass_vbr()
381 {
382 VbrControl_set_quant(m_fQuant);
383 m_iCount++;
384 }
385
386 void VbrControl_update_2pass_vbr_analysis(int is_key_frame, int motion_bits, int texture_bits, int total_bits, int quant)
387 {
388 if(!m_pFile)
389 return;
390 fprintf(m_pFile, "Frame %d: intra %d, quant %d, texture %d, motion %d, total %d\n",
391 m_iCount, is_key_frame, quant, texture_bits, motion_bits, total_bits);
392 m_iCount++;
393 }
394
395 void VbrControl_update_2pass_vbr_encoding(int motion_bits, int texture_bits, int total_bits)
396 {
397 double q;
398 double dq;
399
400 if(m_iCount>=iNumFrames)
401 return;
402
403 m_lExpectedBits+=(m_vFrames[m_iCount].total_bits-m_vFrames[m_iCount].text_bits)
404 + m_vFrames[m_iCount].text_bits*m_vFrames[m_iCount].quant/m_fQuant;
405 m_lEncodedBits+=(int64_t)total_bits;
406
407 if(m_pFile)
408 fprintf(m_pFile, "Frame %d: PRESENT, complexity %d, quant multiplier %f, texture %d, total %d ",
409 m_iCount, m_vFrames[m_iCount].text_bits*m_vFrames[m_iCount].quant,
410 m_vFrames[m_iCount].mult, texture_bits, total_bits);
411
412 m_iCount++;
413
414 q = m_fQuant * m_vFrames[m_iCount].mult;
415 if(q<m_fQuant+min_quant_delta) q=m_fQuant+min_quant_delta;
416 if(q>m_fQuant+max_quant_delta) q=m_fQuant+max_quant_delta;
417
418 dq = (double)m_lEncodedBits/(double)m_lExpectedBits;
419 dq*=dq;
420 if(dq<min_rc_quant_delta)
421 dq=min_rc_quant_delta;
422 if(dq>max_rc_quant_delta)
423 dq=max_rc_quant_delta;
424 if(m_iCount<20) // no framerate corrections in first frames
425 dq=1;
426 if(m_pFile)
427 fprintf(m_pFile, "Progress: expected %12lld, achieved %12lld, dq %f",
428 m_lExpectedBits, m_lEncodedBits, dq);
429 q *= dq;
430 VbrControl_set_quant(q);
431 if(m_pFile)
432 fprintf(m_pFile, ", new quant %d\n", m_iQuant);
433 }
434
435 void VbrControl_close()
436 {
437 if(m_pFile)
438 {
439 fclose(m_pFile);
440 m_pFile=NULL;
441 }
442 free(m_vFrames);
443 }