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 /**********************************************************************
13 **********************************************************************
14 * A convenient libmpeg wrapper, used both here and in scan.c
15 *********************************************************************/
18 mpeg2dec_t
* libmpeg2
;
19 const mpeg2_info_t
* info
;
29 /**********************************************************************
31 **********************************************************************
33 *********************************************************************/
34 hb_libmpeg2_t
* hb_libmpeg2_init()
36 hb_libmpeg2_t
* m
= calloc( sizeof( hb_libmpeg2_t
), 1 );
38 m
->libmpeg2
= mpeg2_init();
39 m
->info
= mpeg2_info( m
->libmpeg2
);
41 m
->look_for_break
= 0;
46 /**********************************************************************
48 **********************************************************************
50 *********************************************************************/
51 int hb_libmpeg2_decode( hb_libmpeg2_t
* m
, hb_buffer_t
* buf_es
,
52 hb_list_t
* list_raw
)
60 if( buf_es
->start
> -1 )
62 mpeg2_tag_picture( m
->libmpeg2
, buf_es
->start
>> 32,
63 buf_es
->start
& 0xFFFFFFFF );
65 mpeg2_buffer( m
->libmpeg2
, buf_es
->data
,
66 buf_es
->data
+ buf_es
->size
);
70 state
= mpeg2_parse( m
->libmpeg2
);
71 if( state
== STATE_BUFFER
)
73 /* Require some more data */
76 else if( state
== STATE_SEQUENCE
)
78 if( !( m
->width
&& m
->height
&& m
->rate
) )
80 m
->width
= m
->info
->sequence
->width
;
81 m
->height
= m
->info
->sequence
->height
;
82 m
->rate
= m
->info
->sequence
->frame_period
;
84 if( m
->rate
== 900900 )
86 /* 29.97 fps. 3:2 pulldown might, or might not be
87 used. I can't find a way to know, so we always
92 if ( m
->aspect_ratio
<= 0 )
94 // We can parse out the aspect ratio from the Sequence Start Header data in buf_es->data
96 // Make sure we have the correct data in the buffer
97 if ((buf_es
->data
[0] == 0x00) && (buf_es
->data
[1] == 0x00) && (buf_es
->data
[2] == 0x01) && (buf_es
->data
[3] == 0xb3))
99 unsigned char ar_fr
= buf_es
->data
[7]; // Top 4 bits == aspect ratio flag - bottom 4 bits == rate flags
100 switch ((ar_fr
& 0xf0) >> 4)
103 m
->aspect_ratio
= HB_ASPECT_BASE
* 4 / 3; // 4:3
106 m
->aspect_ratio
= HB_ASPECT_BASE
* 16 / 9; // 16:9
109 hb_log("hb_libmpeg2_decode - STATE_SEQUENCE unexpected aspect ratio/frame rate 0x%x\n", ar_fr
);
115 else if( state
== STATE_GOP
&& m
->look_for_break
== 2)
117 printf("MPEG2: Group of pictures found, searching for I-Frame\n");
118 m
->look_for_break
= 1;
120 else if( ( state
== STATE_SLICE
|| state
== STATE_END
) &&
121 m
->info
->display_fbuf
)
123 if( ( m
->info
->display_picture
->flags
&
124 PIC_MASK_CODING_TYPE
) == PIC_FLAG_CODING_TYPE_I
)
128 // If we are looking for a break, insert the chapter break on an I-Frame
129 if( m
->look_for_break
== 1 )
131 printf("MPEG2: I-Frame Found\n");
132 m
->look_for_break
= 0;
139 buf
= hb_buffer_init( m
->width
* m
->height
* 3 / 2 );
142 // Was a good break point found?
145 printf("MPEG2: Chapter Break Inserted\n");
150 memcpy( data
, m
->info
->display_fbuf
->buf
[0],
151 m
->width
* m
->height
);
152 data
+= m
->width
* m
->height
;
153 memcpy( data
, m
->info
->display_fbuf
->buf
[1],
154 m
->width
* m
->height
/ 4 );
155 data
+= m
->width
* m
->height
/ 4;
156 memcpy( data
, m
->info
->display_fbuf
->buf
[2],
157 m
->width
* m
->height
/ 4 );
159 if( m
->info
->display_picture
->flags
& PIC_FLAG_TAGS
)
162 ( (uint64_t) m
->info
->display_picture
->tag
<< 32 ) |
163 ( (uint64_t) m
->info
->display_picture
->tag2
);
165 else if( m
->last_pts
> -1 )
167 /* For some reason nb_fields is sometimes 1 while it
169 buf
->start
= m
->last_pts
+
170 MAX( 2, m
->info
->display_picture
->nb_fields
) *
171 m
->info
->sequence
->frame_period
/ 600;
177 m
->last_pts
= buf
->start
;
179 hb_list_add( list_raw
, buf
);
182 else if( state
== STATE_INVALID
)
184 mpeg2_reset( m
->libmpeg2
, 0 );
190 /**********************************************************************
192 **********************************************************************
194 *********************************************************************/
195 void hb_libmpeg2_info( hb_libmpeg2_t
* m
, int * width
, int * height
,
196 int * rate
, int *aspect_ratio
)
201 *aspect_ratio
= m
->aspect_ratio
;
204 /**********************************************************************
206 **********************************************************************
208 *********************************************************************/
209 void hb_libmpeg2_close( hb_libmpeg2_t
** _m
)
211 hb_libmpeg2_t
* m
= *_m
;
213 mpeg2_close( m
->libmpeg2
);
219 /**********************************************************************
220 * The decmpeg2 work object
221 **********************************************************************
223 *********************************************************************/
224 struct hb_work_private_s
226 hb_libmpeg2_t
* libmpeg2
;
230 /**********************************************************************
231 * hb_work_decmpeg2_init
232 **********************************************************************
234 *********************************************************************/
235 int decmpeg2Init( hb_work_object_t
* w
, hb_job_t
* job
)
237 hb_work_private_t
* pv
;
239 pv
= calloc( 1, sizeof( hb_work_private_t
) );
240 w
->private_data
= pv
;
242 pv
->libmpeg2
= hb_libmpeg2_init();
243 pv
->list
= hb_list_init();
248 /**********************************************************************
250 **********************************************************************
252 *********************************************************************/
253 int decmpeg2Work( hb_work_object_t
* w
, hb_buffer_t
** buf_in
,
254 hb_buffer_t
** buf_out
)
256 hb_work_private_t
* pv
= w
->private_data
;
257 hb_buffer_t
* buf
, * last
= NULL
;
259 // The reader found a chapter break, consume it completely, and remove it from the
260 // stream. We need to shift it.
261 if( (*buf_in
)->new_chap
)
263 printf("MPEG2: Chapter Break Cell Found, searching for GOP\n");
264 pv
->libmpeg2
->look_for_break
= 2;
265 (*buf_in
)->new_chap
= 0;
268 hb_libmpeg2_decode( pv
->libmpeg2
, *buf_in
, pv
->list
);
271 while( ( buf
= hb_list_item( pv
->list
, 0 ) ) )
273 hb_list_rem( pv
->list
, buf
);
289 /**********************************************************************
291 **********************************************************************
293 *********************************************************************/
294 void decmpeg2Close( hb_work_object_t
* w
)
296 hb_work_private_t
* pv
= w
->private_data
;
297 hb_list_close( &pv
->list
);
298 hb_libmpeg2_close( &pv
->libmpeg2
);
302 hb_work_object_t hb_decmpeg2
=
305 "MPEG-2 decoder (libmpeg2)",