Major oops. Reverts previous two check-ins, which ended up in tags/0.9.0 instead...
[HandBrake.git] / libhb / decmpeg2.c
blob77c6c0b9859dfd7673844a256b57bd0606c53619
1 /* $Id: decmpeg2.c,v 1.12 2005/03/03 16:30:42 titer Exp $
3 This file is part of the HandBrake source code.
4 Homepage: <http://handbrake.m0k.org/>.
5 It may be used under the terms of the GNU General Public License. */
7 #include "hb.h"
9 #include "mpeg2dec/mpeg2.h"
11 /* Cadence tracking */
12 #ifndef PIC_FLAG_REPEAT_FIRST_FIELD
13 #define PIC_FLAG_REPEAT_FIRST_FIELD 256
14 #endif
15 #define TOP_FIRST PIC_FLAG_TOP_FIELD_FIRST
16 #define PROGRESSIVE PIC_FLAG_PROGRESSIVE_FRAME
17 #define COMPOSITE PIC_FLAG_COMPOSITE_DISPLAY
18 #define SKIP PIC_FLAG_SKIP
19 #define TAGS PIC_FLAG_TAGS
20 #define REPEAT_FIRST PIC_FLAG_REPEAT_FIRST_FIELD
21 #define COMPOSITE_MASK PIC_MASK_COMPOSITE_DISPLAY
22 #define TB 8
23 #define BT 16
24 #define BT_PROG 32
25 #define BTB_PROG 64
26 #define TB_PROG 128
27 #define TBT_PROG 256
28 int cadence[6];
29 int flag = 0;
31 /**********************************************************************
32 * hb_libmpeg2_t
33 **********************************************************************
34 * A convenient libmpeg wrapper, used both here and in scan.c
35 *********************************************************************/
36 struct hb_libmpeg2_s
38 mpeg2dec_t * libmpeg2;
39 const mpeg2_info_t * info;
40 int width;
41 int height;
42 int rate;
43 int aspect_ratio;
44 int got_iframe;
45 int look_for_break;
46 int64_t last_pts;
49 /**********************************************************************
50 * hb_libmpeg2_init
51 **********************************************************************
53 *********************************************************************/
54 hb_libmpeg2_t * hb_libmpeg2_init()
56 hb_libmpeg2_t * m = calloc( sizeof( hb_libmpeg2_t ), 1 );
58 m->libmpeg2 = mpeg2_init();
59 m->info = mpeg2_info( m->libmpeg2 );
60 m->last_pts = -1;
61 m->look_for_break = 0;
63 return m;
66 /**********************************************************************
67 * hb_libmpeg2_decode
68 **********************************************************************
70 *********************************************************************/
71 int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
72 hb_list_t * list_raw )
74 mpeg2_state_t state;
75 hb_buffer_t * buf;
76 uint8_t * data;
77 int chap_break = 0;
79 /* Feed libmpeg2 */
80 if( buf_es->start > -1 )
82 mpeg2_tag_picture( m->libmpeg2, buf_es->start >> 32,
83 buf_es->start & 0xFFFFFFFF );
85 mpeg2_buffer( m->libmpeg2, buf_es->data,
86 buf_es->data + buf_es->size );
88 for( ;; )
90 state = mpeg2_parse( m->libmpeg2 );
91 if( state == STATE_BUFFER )
93 /* Require some more data */
94 break;
96 else if( state == STATE_SEQUENCE )
98 if( !( m->width && m->height && m->rate ) )
100 m->width = m->info->sequence->width;
101 m->height = m->info->sequence->height;
102 m->rate = m->info->sequence->frame_period;
104 if ( m->aspect_ratio <= 0 )
106 // We can parse out the aspect ratio from the Sequence Start Header data in buf_es->data
108 // Make sure we have the correct data in the buffer
109 if ((buf_es->data[0] == 0x00) && (buf_es->data[1] == 0x00) && (buf_es->data[2] == 0x01) && (buf_es->data[3] == 0xb3))
111 unsigned char ar_fr = buf_es->data[7]; // Top 4 bits == aspect ratio flag - bottom 4 bits == rate flags
112 switch ((ar_fr & 0xf0) >> 4)
114 case 2:
115 m->aspect_ratio = HB_ASPECT_BASE * 4 / 3; // 4:3
116 break;
117 case 3:
118 m->aspect_ratio = HB_ASPECT_BASE * 16 / 9; // 16:9
119 break;
120 default:
121 hb_log("hb_libmpeg2_decode - STATE_SEQUENCE unexpected aspect ratio/frame rate 0x%x\n", ar_fr);
122 break;
127 else if( state == STATE_GOP && m->look_for_break == 2)
129 printf("MPEG2: Group of pictures found, searching for I-Frame\n");
130 m->look_for_break = 1;
132 else if( ( state == STATE_SLICE || state == STATE_END ) &&
133 m->info->display_fbuf )
135 if( ( m->info->display_picture->flags &
136 PIC_MASK_CODING_TYPE ) == PIC_FLAG_CODING_TYPE_I )
138 m->got_iframe = 1;
140 // If we are looking for a break, insert the chapter break on an I-Frame
141 if( m->look_for_break == 1 )
143 printf("MPEG2: I-Frame Found\n");
144 m->look_for_break = 0;
145 chap_break = 1;
149 if( m->got_iframe )
151 buf = hb_buffer_init( m->width * m->height * 3 / 2 );
152 data = buf->data;
154 // Was a good break point found?
155 if( chap_break )
157 printf("MPEG2: Chapter Break Inserted\n");
158 chap_break = 0;
159 buf->new_chap = 1;
162 memcpy( data, m->info->display_fbuf->buf[0],
163 m->width * m->height );
164 data += m->width * m->height;
165 memcpy( data, m->info->display_fbuf->buf[1],
166 m->width * m->height / 4 );
167 data += m->width * m->height / 4;
168 memcpy( data, m->info->display_fbuf->buf[2],
169 m->width * m->height / 4 );
171 if( m->info->display_picture->flags & PIC_FLAG_TAGS )
173 buf->start =
174 ( (uint64_t) m->info->display_picture->tag << 32 ) |
175 ( (uint64_t) m->info->display_picture->tag2 );
177 * Add back in again to track PTS of MPEG2 frames
178 * hb_log("MPEG2: Normal buf->start = %lld", buf->start);
181 else if( m->last_pts > -1 )
183 /* For some reason nb_fields is sometimes 1 while it
184 should be 2 */
185 buf->start = m->last_pts +
186 MAX( 2, m->info->display_picture->nb_fields ) *
187 m->info->sequence->frame_period / 600;
189 else
191 buf->start = -1;
193 m->last_pts = buf->start;
195 flag = m->info->display_picture->flags;
197 /* Uncomment this block to see frame-by-frame picture flags, as the video encodes.
198 hb_log("***** MPEG 2 Picture Info for PTS %lld *****", buf->start);
199 if( flag & TOP_FIRST )
200 hb_log("MPEG2 Flag: Top field first");
201 if( flag & PROGRESSIVE )
202 hb_log("MPEG2 Flag: Progressive");
203 if( flag & COMPOSITE )
204 hb_log("MPEG2 Flag: Composite");
205 if( flag & SKIP )
206 hb_log("MPEG2 Flag: Skip!");
207 if( flag & TAGS )
208 hb_log("MPEG2 Flag: TAGS");
209 if(flag & REPEAT_FIRST )
210 hb_log("MPEG2 Flag: Repeat first field");
211 if( flag & COMPOSITE_MASK )
212 hb_log("MPEG2 Flag: Composite mask");
213 hb_log("fields: %d", m->info->display_picture->nb_fields);
215 /* Rotate the cadence tracking. */
216 cadence[5] = cadence[4];
217 cadence[4] = cadence[3];
218 cadence[3] = cadence[2];
219 cadence[2] = cadence[1];
220 cadence[1] = cadence[0];
222 if ( !(flag & PROGRESSIVE) && !(flag & TOP_FIRST) )
224 /* Not progressive, not top first...
225 That means it's probably bottom
226 first, 2 fields displayed.
228 //hb_log("MPEG2 Flag: Bottom field first, 2 fields displayed.");
229 cadence[0] = BT;
231 else if ( !(flag & PROGRESSIVE) && (flag & TOP_FIRST) )
233 /* Not progressive, top is first,
234 Two fields displayed.
236 //hb_log("MPEG2 Flag: Top field first, 2 fields displayed.");
237 cadence[0] = TB;
239 else if ( (flag & PROGRESSIVE) && !(flag & TOP_FIRST) && !( flag & REPEAT_FIRST ) )
241 /* Progressive, but noting else.
242 That means Bottom first,
243 2 fields displayed.
245 //hb_log("MPEG2 Flag: Progressive. Bottom field first, 2 fields displayed.");
246 cadence[0] = BT_PROG;
248 else if ( (flag & PROGRESSIVE) && !(flag & TOP_FIRST) && ( flag & REPEAT_FIRST ) )
250 /* Progressive, and repeat. .
251 That means Bottom first,
252 3 fields displayed.
254 //hb_log("MPEG2 Flag: Progressive repeat. Bottom field first, 3 fields displayed.");
255 cadence[0] = BTB_PROG;
257 else if ( (flag & PROGRESSIVE) && (flag & TOP_FIRST) && !( flag & REPEAT_FIRST ) )
259 /* Progressive, top first.
260 That means top first,
261 2 fields displayed.
263 //hb_log("MPEG2 Flag: Progressive. Top field first, 2 fields displayed.");
264 cadence[0] = TB_PROG;
266 else if ( (flag & PROGRESSIVE) && (flag & TOP_FIRST) && ( flag & REPEAT_FIRST ) )
268 /* Progressive, top, repeat.
269 That means top first,
270 3 fields displayed.
272 //hb_log("MPEG2 Flag: Progressive repeat. Top field first, 3 fields displayed.");
273 cadence[0] = TBT_PROG;
276 if ( (cadence[2] <= TB) && (cadence[1] <= TB) && (cadence[0] > TB) && (cadence[0]) && (cadence[1]) )
277 hb_log("PTS %lld: Interlaced -> Progressive", buf->start);
278 if ( (cadence[2] > TB) && (cadence[1] <= TB) && (cadence[0] <= TB) && (cadence[0]) && (cadence[1]) )
279 hb_log("PTS %lld: Progressive -> Interlaced", buf->start);
281 /* Store picture flags for later use by filters */
282 buf->flags = m->info->display_picture->flags;
284 hb_list_add( list_raw, buf );
287 else if( state == STATE_INVALID )
289 mpeg2_reset( m->libmpeg2, 0 );
292 return 1;
295 /**********************************************************************
296 * hb_libmpeg2_info
297 **********************************************************************
299 *********************************************************************/
300 void hb_libmpeg2_info( hb_libmpeg2_t * m, int * width, int * height,
301 int * rate, int *aspect_ratio )
303 *width = m->width;
304 *height = m->height;
305 if (m->info->display_fbuf)
307 if( (m->info->display_picture->flags & PROGRESSIVE) && (m->height == 480) )
309 /* The frame is progressive and it's NTSC DVD height, so change its FPS to 23.976.
310 This might not be correct for the title. It's really just for scan.c's benefit.
311 Scan.c will reset the fps to 29.97, until a simple majority of the preview
312 frames report at 23.976.
314 //hb_log("Detecting NTSC Progressive Frame");
315 m->rate = 1126125;
318 *rate = m->rate;
319 *aspect_ratio = m->aspect_ratio;
322 /**********************************************************************
323 * hb_libmpeg2_close
324 **********************************************************************
326 *********************************************************************/
327 void hb_libmpeg2_close( hb_libmpeg2_t ** _m )
329 hb_libmpeg2_t * m = *_m;
331 mpeg2_close( m->libmpeg2 );
333 free( m );
334 *_m = NULL;
337 /**********************************************************************
338 * The decmpeg2 work object
339 **********************************************************************
341 *********************************************************************/
342 struct hb_work_private_s
344 hb_libmpeg2_t * libmpeg2;
345 hb_list_t * list;
348 /**********************************************************************
349 * hb_work_decmpeg2_init
350 **********************************************************************
352 *********************************************************************/
353 int decmpeg2Init( hb_work_object_t * w, hb_job_t * job )
355 hb_work_private_t * pv;
357 pv = calloc( 1, sizeof( hb_work_private_t ) );
358 w->private_data = pv;
360 pv->libmpeg2 = hb_libmpeg2_init();
361 pv->list = hb_list_init();
363 return 0;
366 /**********************************************************************
367 * Work
368 **********************************************************************
370 *********************************************************************/
371 int decmpeg2Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
372 hb_buffer_t ** buf_out )
374 hb_work_private_t * pv = w->private_data;
375 hb_buffer_t * buf, * last = NULL;
377 // The reader found a chapter break, consume it completely, and remove it from the
378 // stream. We need to shift it.
379 if( (*buf_in)->new_chap )
381 printf("MPEG2: Chapter Break Cell Found, searching for GOP\n");
382 pv->libmpeg2->look_for_break = 2;
383 (*buf_in)->new_chap = 0;
386 hb_libmpeg2_decode( pv->libmpeg2, *buf_in, pv->list );
388 *buf_out = NULL;
389 while( ( buf = hb_list_item( pv->list, 0 ) ) )
391 hb_list_rem( pv->list, buf );
392 if( last )
394 last->next = buf;
395 last = buf;
397 else
399 *buf_out = buf;
400 last = buf;
404 return HB_WORK_OK;
407 /**********************************************************************
408 * Close
409 **********************************************************************
411 *********************************************************************/
412 void decmpeg2Close( hb_work_object_t * w )
414 hb_work_private_t * pv = w->private_data;
415 hb_list_close( &pv->list );
416 hb_libmpeg2_close( &pv->libmpeg2 );
417 free( pv );
420 hb_work_object_t hb_decmpeg2 =
422 WORK_DECMPEG2,
423 "MPEG-2 decoder (libmpeg2)",
424 decmpeg2Init,
425 decmpeg2Work,
426 decmpeg2Close