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. */
9 #include "mpeg2dec/mpeg2.h"
11 /* Cadence tracking */
12 #ifndef PIC_FLAG_REPEAT_FIRST_FIELD
13 #define PIC_FLAG_REPEAT_FIRST_FIELD 256
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
31 /**********************************************************************
33 **********************************************************************
34 * A convenient libmpeg wrapper, used both here and in scan.c
35 *********************************************************************/
38 mpeg2dec_t
* libmpeg2
;
39 const mpeg2_info_t
* info
;
49 /**********************************************************************
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
);
61 m
->look_for_break
= 0;
66 /**********************************************************************
68 **********************************************************************
70 *********************************************************************/
71 int hb_libmpeg2_decode( hb_libmpeg2_t
* m
, hb_buffer_t
* buf_es
,
72 hb_list_t
* list_raw
)
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
);
90 state
= mpeg2_parse( m
->libmpeg2
);
91 if( state
== STATE_BUFFER
)
93 /* Require some more data */
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)
115 m
->aspect_ratio
= HB_ASPECT_BASE
* 4 / 3; // 4:3
118 m
->aspect_ratio
= HB_ASPECT_BASE
* 16 / 9; // 16:9
121 hb_log("hb_libmpeg2_decode - STATE_SEQUENCE unexpected aspect ratio/frame rate 0x%x\n", ar_fr
);
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
)
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;
151 buf
= hb_buffer_init( m
->width
* m
->height
* 3 / 2 );
154 // Was a good break point found?
157 printf("MPEG2: Chapter Break Inserted\n");
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
)
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
185 buf
->start
= m
->last_pts
+
186 MAX( 2, m
->info
->display_picture
->nb_fields
) *
187 m
->info
->sequence
->frame_period
/ 600;
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");
206 hb_log("MPEG2 Flag: Skip!");
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.");
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.");
239 else if ( (flag
& PROGRESSIVE
) && !(flag
& TOP_FIRST
) && !( flag
& REPEAT_FIRST
) )
241 /* Progressive, but noting else.
242 That means Bottom first,
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,
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,
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,
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 );
295 /**********************************************************************
297 **********************************************************************
299 *********************************************************************/
300 void hb_libmpeg2_info( hb_libmpeg2_t
* m
, int * width
, int * height
,
301 int * rate
, int *aspect_ratio
)
305 if( (m
->info
->display_picture
->flags
& PROGRESSIVE
) && (m
->height
== 480) )
307 /* The frame is progressive and it's NTSC DVD height, so change its FPS to 23.976.
308 This might not be correct for the title. It's really just for scan.c's benefit.
309 Scan.c will reset the fps to 29.97, until a simple majority of the preview
310 frames report at 23.976.
312 //hb_log("Detecting NTSC Progressive Frame");
316 *aspect_ratio
= m
->aspect_ratio
;
319 /**********************************************************************
321 **********************************************************************
323 *********************************************************************/
324 void hb_libmpeg2_close( hb_libmpeg2_t
** _m
)
326 hb_libmpeg2_t
* m
= *_m
;
328 mpeg2_close( m
->libmpeg2
);
334 /**********************************************************************
335 * The decmpeg2 work object
336 **********************************************************************
338 *********************************************************************/
339 struct hb_work_private_s
341 hb_libmpeg2_t
* libmpeg2
;
345 /**********************************************************************
346 * hb_work_decmpeg2_init
347 **********************************************************************
349 *********************************************************************/
350 int decmpeg2Init( hb_work_object_t
* w
, hb_job_t
* job
)
352 hb_work_private_t
* pv
;
354 pv
= calloc( 1, sizeof( hb_work_private_t
) );
355 w
->private_data
= pv
;
357 pv
->libmpeg2
= hb_libmpeg2_init();
358 pv
->list
= hb_list_init();
363 /**********************************************************************
365 **********************************************************************
367 *********************************************************************/
368 int decmpeg2Work( hb_work_object_t
* w
, hb_buffer_t
** buf_in
,
369 hb_buffer_t
** buf_out
)
371 hb_work_private_t
* pv
= w
->private_data
;
372 hb_buffer_t
* buf
, * last
= NULL
;
374 // The reader found a chapter break, consume it completely, and remove it from the
375 // stream. We need to shift it.
376 if( (*buf_in
)->new_chap
)
378 printf("MPEG2: Chapter Break Cell Found, searching for GOP\n");
379 pv
->libmpeg2
->look_for_break
= 2;
380 (*buf_in
)->new_chap
= 0;
383 hb_libmpeg2_decode( pv
->libmpeg2
, *buf_in
, pv
->list
);
386 while( ( buf
= hb_list_item( pv
->list
, 0 ) ) )
388 hb_list_rem( pv
->list
, buf
);
404 /**********************************************************************
406 **********************************************************************
408 *********************************************************************/
409 void decmpeg2Close( hb_work_object_t
* w
)
411 hb_work_private_t
* pv
= w
->private_data
;
412 hb_list_close( &pv
->list
);
413 hb_libmpeg2_close( &pv
->libmpeg2
);
417 hb_work_object_t hb_decmpeg2
=
420 "MPEG-2 decoder (libmpeg2)",