Mercurial > mplayer.hg
annotate divx4_vbr.c @ 4218:3931c41f740a
Added new syncengine thanks to a new previously undocumented feature of the em8300, this might fix playback on both slow and fast machines (more testing needed). This also requires users to get the em8300 driver from cvs until the next version is released (will probably happen this weekend)
Added lots of comments, should be pretty easy to understand most of the internals now
Added lots of brackets to if's for's while's etc, this is not a cosmetical thing but rather due to the fact I got some very odd bugs with else's since I didn't properly use brackets (and it's the K&R standard to have brackets everywhere)
Fixed some bugs that would occur when disabling libmp1e
Switched to default to the new naming scheme of device nodes, the driver will slowly switch over to this state, if it can't find devices under the new name it will try the old naming scheme
I stopped opening devices in non-blocking mode, it would break the new syncengine which tries to burst data to the device (alot of times meaning it will fill the fifo pretty fast which would previously result in jerkyness on fast machines)
The device now sets the initial state of the pts and speed (probably not needed, but assumption is the mother of all fuckups =)
Keep the control interface open during the entire duration of the libvo device, we might need this to flush video buffers on seeking (currently not implemented, therefore seeking is broken)
This is beta stuff to the driver, I will get some users to test it for me and do my best to fix seeking as soon as possible...
author | mswitch |
---|---|
date | Thu, 17 Jan 2002 10:33:47 +0000 |
parents | 92c59012249d |
children | d1cbcf738db1 |
rev | line source |
---|---|
2641 | 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> | |
2642 | 39 #include <string.h> |
2641 | 40 #include <sys/stat.h> |
41 #include <unistd.h> | |
42 #include <fcntl.h> | |
43 #include <dlfcn.h> | |
44 #include <math.h> | |
4003
92c59012249d
stdint.h replaced by inttypes.h (used more frequently in the sources)
pl
parents:
3919
diff
changeset
|
45 #include <inttypes.h> |
2642 | 46 |
47 #include "divx4_vbr.h" | |
48 | |
49 //#include "transcode.h" | |
2641 | 50 |
51 #define FALSE 0 | |
52 #define TRUE 1 | |
53 | |
54 /* Absolute maximum and minimum quantizers used in VBR modes */ | |
55 static const int min_quantizer=1; | |
56 static const int max_quantizer=31; | |
57 | |
58 /* Limits on frame-level deviation of quantizer ( higher values | |
59 correspond to frames with more changes and vice versa ) */ | |
60 static const float min_quant_delta=-10.f; | |
61 static const float max_quant_delta=5.f; | |
62 /* Limits on stream-level deviation of quantizer ( used to make | |
63 overall bitrate of stream close to requested value ) */ | |
64 static const float min_rc_quant_delta=.6f; | |
65 static const float max_rc_quant_delta=1.5f; | |
66 | |
67 /* Crispness parameter controls threshold for decision whether | |
68 to skip the frame or to code it. */ | |
69 //static const float max_crispness=100.f; | |
70 /* Maximum allowed number of skipped frames in a line. */ | |
71 //static const int max_drops_line=0; // CHL We don't drop frames at the moment! | |
72 | |
73 | |
74 typedef struct entry_s | |
75 /* max 28 bytes/frame or 5 Mb for 2-hour movie */ | |
76 { | |
77 int quant; | |
78 int text_bits; | |
79 int motion_bits; | |
80 int total_bits; | |
81 float mult; | |
82 short is_key_frame; | |
83 short drop; | |
84 } entry; | |
85 | |
2642 | 86 static int m_iCount; |
87 static int m_iQuant; | |
88 static int m_iCrispness; | |
89 static short m_bDrop; | |
90 static float m_fQuant; | |
2641 | 91 |
2642 | 92 static int64_t m_lEncodedBits; |
93 static int64_t m_lExpectedBits; | |
2641 | 94 |
2642 | 95 static FILE *m_pFile; |
2641 | 96 |
2642 | 97 static entry vFrame; |
98 static entry *m_vFrames; | |
99 static long lFrameStart; | |
2641 | 100 |
2642 | 101 static int iNumFrames; |
102 static int dummy; | |
2641 | 103 |
104 | |
105 void VbrControl_init_1pass_vbr(int quality, int crispness) | |
106 { | |
107 m_fQuant=min_quantizer+((max_quantizer-min_quantizer)/6.)*(6-quality); | |
108 m_iCount=0; | |
109 m_bDrop=FALSE; | |
110 VbrControl_update_1pass_vbr(); | |
111 } | |
112 | |
113 int VbrControl_init_2pass_vbr_analysis(const char *filename, int quality) | |
114 { | |
115 m_pFile=fopen(filename, "wb"); | |
116 if(m_pFile==0) | |
117 return -1; | |
118 m_iCount=0; | |
119 m_bDrop=FALSE; | |
120 fprintf(m_pFile, "##version 1\n"); | |
121 fprintf(m_pFile, "quality %d\n", quality); | |
122 return 0; | |
123 } | |
124 | |
125 int VbrControl_init_2pass_vbr_encoding(const char *filename, int bitrate, double framerate, int crispness, int quality) | |
126 { | |
127 int i; | |
128 | |
129 int64_t text_bits=0; | |
130 int64_t total_bits=0; | |
131 int64_t complexity=0; | |
132 int64_t new_complexity=0; | |
133 int64_t motion_bits=0; | |
134 int64_t denominator=0; | |
135 float qual_multiplier=1.; | |
136 char head[20]; | |
137 | |
138 int64_t desired_bits; | |
139 int64_t non_text_bits; | |
140 | |
141 float average_complexity; | |
142 | |
143 m_pFile=fopen(filename, "rb"); | |
144 if(m_pFile==0) | |
145 return -1; | |
146 m_bDrop=FALSE; | |
147 m_iCount=0; | |
148 | |
149 fread(head, 10, 1, m_pFile); | |
150 if(!strncmp("##version ", head, 10)) | |
151 { | |
152 int version; | |
153 int iOldQual; | |
154 float old_qual, new_qual; | |
155 fscanf(m_pFile, "%d\n", &version); | |
156 fscanf(m_pFile, "quality %d\n", &iOldQual); | |
157 switch(iOldQual) | |
158 { | |
159 case 5: | |
160 old_qual=1.f; | |
161 break; | |
162 case 4: | |
163 old_qual=1.1f; | |
164 break; | |
165 case 3: | |
166 old_qual=1.25f; | |
167 break; | |
168 case 2: | |
169 old_qual=1.4f; | |
170 break; | |
171 case 1: | |
172 old_qual=2.f; | |
173 break; | |
174 } | |
175 switch(quality) | |
176 { | |
177 case 5: | |
178 new_qual=1.f; | |
179 break; | |
180 case 4: | |
181 new_qual=1.1f; | |
182 break; | |
183 case 3: | |
184 new_qual=1.25f; | |
185 break; | |
186 case 2: | |
187 new_qual=1.4f; | |
188 break; | |
189 case 1: | |
190 new_qual=2.f; | |
191 break; | |
192 } | |
193 qual_multiplier=new_qual/old_qual; | |
194 } | |
195 else | |
196 fseek(m_pFile, 0, SEEK_SET); | |
197 | |
198 lFrameStart=ftell(m_pFile); // save current position | |
199 | |
200 /* removed C++ dependencies, now read file twice :-( */ | |
201 | |
202 | |
203 while(!feof(m_pFile)) | |
204 { fscanf(m_pFile, "Frame %d: intra %d, quant %d, texture %d, motion %d, total %d\n", | |
205 &iNumFrames, &(vFrame.is_key_frame), &(vFrame.quant), &(vFrame.text_bits), &(vFrame.motion_bits), &(vFrame.total_bits)); | |
206 | |
207 vFrame.total_bits+=vFrame.text_bits*(qual_multiplier-1); | |
208 vFrame.text_bits*=qual_multiplier; | |
209 text_bits +=(int64_t)vFrame.text_bits; | |
210 motion_bits += (int64_t)vFrame.motion_bits; | |
211 total_bits +=(int64_t)vFrame.total_bits; | |
212 complexity +=(int64_t)vFrame.text_bits*vFrame.quant; | |
213 | |
214 // printf("Frames %d, texture %d, motion %d, quant %d total %d ", | |
215 // iNumFrames, vFrame.text_bits, vFrame.motion_bits, vFrame.quant, vFrame.total_bits); | |
216 // printf("texture %d, total %d, complexity %lld \n",vFrame.text_bits,vFrame.total_bits, complexity); | |
217 } | |
218 iNumFrames++; | |
219 average_complexity=complexity/iNumFrames; | |
220 | |
2642 | 221 // if (verbose & TC_DEBUG) { |
222 // fprintf(stderr, "(%s) frames %d, texture %lld, motion %lld, total %lld, complexity %lld\n", __FILE__, iNumFrames, text_bits, motion_bits, total_bits, complexity); | |
223 // } | |
2641 | 224 |
225 m_vFrames = (entry*)malloc(iNumFrames*sizeof(entry)); | |
226 if (!m_vFrames) | |
227 { printf("out of memory"); | |
2642 | 228 return -2; //TC_EXPORT_ERROR; |
2641 | 229 } |
230 | |
231 fseek(m_pFile, lFrameStart, SEEK_SET); // start again | |
232 | |
233 for (i=0;i<iNumFrames;i++) | |
234 { fscanf(m_pFile, "Frame %d: intra %d, quant %d, texture %d, motion %d, total %d\n", | |
235 &dummy, &(m_vFrames[i].is_key_frame), &(m_vFrames[i].quant), | |
236 &(m_vFrames[i].text_bits), &(m_vFrames[i].motion_bits), | |
237 &(m_vFrames[i].total_bits)); | |
238 | |
239 m_vFrames[i].total_bits += m_vFrames[i].text_bits*(qual_multiplier-1); | |
240 m_vFrames[i].text_bits *= qual_multiplier; | |
241 } | |
242 | |
243 if (m_pFile) | |
244 { fclose(m_pFile); | |
245 m_pFile=NULL; | |
246 } | |
247 | |
248 desired_bits=(int64_t)bitrate*(int64_t)iNumFrames/framerate; | |
249 non_text_bits=total_bits-text_bits; | |
250 | |
251 if(desired_bits<=non_text_bits) | |
252 { | |
253 char s[200]; | |
254 printf("Specified bitrate is too low for this clip.\n" | |
255 "Minimum possible bitrate for the clip is %.0f kbps. Overriding\n" | |
256 "user-specified value.\n", | |
257 (float)(non_text_bits*framerate/(int64_t)iNumFrames)); | |
258 | |
259 desired_bits=non_text_bits*3/2; | |
260 /* | |
261 m_fQuant=max_quantizer; | |
262 for(int i=0; i<iNumFrames; i++) | |
263 { | |
264 m_vFrames[i].drop=0; | |
265 m_vFrames[i].mult=1; | |
266 } | |
267 VbrControl_set_quant(m_fQuant); | |
268 return 0; | |
269 */ | |
270 } | |
271 | |
272 desired_bits -= non_text_bits; | |
273 /** | |
274 BRIEF EXPLANATION OF WHAT'S GOING ON HERE. | |
275 We assume that | |
276 text_bits=complexity / quantizer | |
277 total_bits-text_bits = const(complexity) | |
278 where 'complexity' is a characteristic of the frame | |
279 and does not depend much on quantizer dynamics. | |
280 Using this equation, we calculate 'average' quantizer | |
281 to be used for encoding ( 1st order effect ). | |
282 Having constant quantizer for the entire stream is not | |
283 very convenient - reconstruction errors are | |
284 more noticeable in low-motion scenes. To compensate | |
285 this effect, we multiply quantizer for each frame by | |
286 (complexity/average_complexity)^k, | |
287 ( k - parameter of adjustment ). k=0 means 'no compensation' | |
288 and k=1 is 'constant bitrate mode'. We choose something in | |
289 between, like 0.5 ( 2nd order effect ). | |
290 **/ | |
291 | |
292 average_complexity=complexity/iNumFrames; | |
293 | |
294 for(i=0; i<iNumFrames; i++) | |
295 { | |
296 float mult; | |
297 if(m_vFrames[i].is_key_frame) | |
298 { | |
299 if((i+1<iNumFrames) && (m_vFrames[i+1].is_key_frame)) | |
300 mult=1.25; | |
301 else | |
302 mult=.75; | |
303 } | |
304 else | |
305 { | |
306 mult=m_vFrames[i].text_bits*m_vFrames[i].quant; | |
307 mult=(float)sqrt(mult/average_complexity); | |
308 | |
309 // if(i && m_vFrames[i-1].is_key_frame) | |
310 // mult *= 0.75; | |
311 if(mult<0.5) | |
312 mult=0.5; | |
313 if(mult>1.5) | |
314 mult=1.5; | |
315 } | |
316 | |
317 m_vFrames[i].mult=mult; | |
318 m_vFrames[i].drop=FALSE; | |
319 new_complexity+=m_vFrames[i].text_bits*m_vFrames[i].quant; | |
320 | |
321 denominator+=desired_bits*m_vFrames[i].mult/iNumFrames; | |
322 } | |
323 | |
324 m_fQuant=((double)new_complexity)/(double)denominator; | |
325 | |
326 if(m_fQuant<min_quantizer) m_fQuant=min_quantizer; | |
327 if(m_fQuant>max_quantizer) m_fQuant=max_quantizer; | |
328 m_pFile=fopen("analyse.log", "wb"); | |
329 if(m_pFile) | |
330 { | |
331 fprintf(m_pFile, "Total frames: %d Avg quantizer: %f\n", | |
332 iNumFrames, m_fQuant); | |
333 fprintf(m_pFile, "Expecting %12lld bits\n", desired_bits+non_text_bits); | |
334 fflush(m_pFile); | |
335 } | |
336 VbrControl_set_quant(m_fQuant*m_vFrames[0].mult); | |
337 m_lEncodedBits=m_lExpectedBits=0; | |
338 return 0; | |
339 } | |
340 | |
341 int VbrControl_get_intra() | |
342 { | |
343 return m_vFrames[m_iCount].is_key_frame; | |
344 } | |
345 | |
346 short VbrControl_get_drop() | |
347 { | |
348 return m_bDrop; | |
349 } | |
350 | |
351 int VbrControl_get_quant() | |
352 { | |
353 return m_iQuant; | |
354 } | |
355 | |
356 void VbrControl_set_quant(float quant) | |
357 { | |
358 m_iQuant=quant; | |
359 if((rand() % 10)<((quant-m_iQuant) * 10)) | |
360 m_iQuant++; | |
361 if(m_iQuant<min_quantizer) m_iQuant=min_quantizer; | |
362 if(m_iQuant>max_quantizer) m_iQuant=max_quantizer; | |
363 } | |
364 | |
365 void VbrControl_update_1pass_vbr() | |
366 { | |
367 VbrControl_set_quant(m_fQuant); | |
368 m_iCount++; | |
369 } | |
370 | |
371 void VbrControl_update_2pass_vbr_analysis(int is_key_frame, int motion_bits, int texture_bits, int total_bits, int quant) | |
372 { | |
373 if(!m_pFile) | |
374 return; | |
375 fprintf(m_pFile, "Frame %d: intra %d, quant %d, texture %d, motion %d, total %d\n", | |
376 m_iCount, is_key_frame, quant, texture_bits, motion_bits, total_bits); | |
377 m_iCount++; | |
378 } | |
379 | |
380 void VbrControl_update_2pass_vbr_encoding(int motion_bits, int texture_bits, int total_bits) | |
381 { | |
382 double q; | |
383 double dq; | |
384 | |
385 if(m_iCount>=iNumFrames) | |
386 return; | |
387 | |
388 m_lExpectedBits+=(m_vFrames[m_iCount].total_bits-m_vFrames[m_iCount].text_bits) | |
389 + m_vFrames[m_iCount].text_bits*m_vFrames[m_iCount].quant/m_fQuant; | |
390 m_lEncodedBits+=(int64_t)total_bits; | |
391 | |
392 if(m_pFile) | |
393 fprintf(m_pFile, "Frame %d: PRESENT, complexity %d, quant multiplier %f, texture %d, total %d ", | |
394 m_iCount, m_vFrames[m_iCount].text_bits*m_vFrames[m_iCount].quant, | |
395 m_vFrames[m_iCount].mult, texture_bits, total_bits); | |
396 | |
397 m_iCount++; | |
398 | |
399 q = m_fQuant * m_vFrames[m_iCount].mult; | |
400 if(q<m_fQuant+min_quant_delta) q=m_fQuant+min_quant_delta; | |
401 if(q>m_fQuant+max_quant_delta) q=m_fQuant+max_quant_delta; | |
402 | |
403 dq = (double)m_lEncodedBits/(double)m_lExpectedBits; | |
404 dq*=dq; | |
405 if(dq<min_rc_quant_delta) | |
406 dq=min_rc_quant_delta; | |
407 if(dq>max_rc_quant_delta) | |
408 dq=max_rc_quant_delta; | |
409 if(m_iCount<20) // no framerate corrections in first frames | |
410 dq=1; | |
411 if(m_pFile) | |
412 fprintf(m_pFile, "Progress: expected %12lld, achieved %12lld, dq %f", | |
413 m_lExpectedBits, m_lEncodedBits, dq); | |
414 q *= dq; | |
415 VbrControl_set_quant(q); | |
416 if(m_pFile) | |
417 fprintf(m_pFile, ", new quant %d\n", m_iQuant); | |
418 } | |
419 | |
420 void VbrControl_close() | |
421 { | |
422 if(m_pFile) | |
423 { | |
424 fclose(m_pFile); | |
425 m_pFile=NULL; | |
426 } | |
427 free(m_vFrames); | |
428 } |