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;
28 /**********************************************************************
30 **********************************************************************
32 *********************************************************************/
33 hb_libmpeg2_t * hb_libmpeg2_init()
35 hb_libmpeg2_t * m = calloc( sizeof( hb_libmpeg2_t ), 1 );
37 m->libmpeg2 = mpeg2_init();
38 m->info = mpeg2_info( m->libmpeg2 );
40 m->look_for_break = 0;
45 /**********************************************************************
47 **********************************************************************
49 *********************************************************************/
50 int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
51 hb_list_t * list_raw )
59 if( buf_es->start > -1 )
61 mpeg2_tag_picture( m->libmpeg2, buf_es->start >> 32,
62 buf_es->start & 0xFFFFFFFF );
64 mpeg2_buffer( m->libmpeg2, buf_es->data,
65 buf_es->data + buf_es->size );
69 state = mpeg2_parse( m->libmpeg2 );
70 if( state == STATE_BUFFER )
72 /* Require some more data */
75 else if( state == STATE_SEQUENCE )
77 if( !( m->width && m->height && m->rate ) )
79 m->width = m->info->sequence->width;
80 m->height = m->info->sequence->height;
81 m->rate = m->info->sequence->frame_period;
83 if( m->rate == 900900 )
85 /* 29.97 fps. 3:2 pulldown might, or might not be
86 used. I can't find a way to know, so we always
92 else if( state == STATE_GOP && m->look_for_break == 2)
94 printf("MPEG2: Group of pictures found, searching for I-Frame\n");
95 m->look_for_break = 1;
97 else if( ( state == STATE_SLICE || state == STATE_END ) &&
98 m->info->display_fbuf )
100 if( ( m->info->display_picture->flags &
101 PIC_MASK_CODING_TYPE ) == PIC_FLAG_CODING_TYPE_I )
105 // If we are looking for a break, insert the chapter break on an I-Frame
106 if( m->look_for_break == 1 )
108 printf("MPEG2: I-Frame Found\n");
109 m->look_for_break = 0;
116 buf = hb_buffer_init( m->width * m->height * 3 / 2 );
119 // Was a good break point found?
122 printf("MPEG2: Chapter Break Inserted\n");
127 memcpy( data, m->info->display_fbuf->buf[0],
128 m->width * m->height );
129 data += m->width * m->height;
130 memcpy( data, m->info->display_fbuf->buf[1],
131 m->width * m->height / 4 );
132 data += m->width * m->height / 4;
133 memcpy( data, m->info->display_fbuf->buf[2],
134 m->width * m->height / 4 );
136 if( m->info->display_picture->flags & PIC_FLAG_TAGS )
139 ( (uint64_t) m->info->display_picture->tag << 32 ) |
140 ( (uint64_t) m->info->display_picture->tag2 );
142 else if( m->last_pts > -1 )
144 /* For some reason nb_fields is sometimes 1 while it
146 buf->start = m->last_pts +
147 MAX( 2, m->info->display_picture->nb_fields ) *
148 m->info->sequence->frame_period / 600;
154 m->last_pts = buf->start;
156 hb_list_add( list_raw, buf );
159 else if( state == STATE_INVALID )
161 mpeg2_reset( m->libmpeg2, 0 );
167 /**********************************************************************
169 **********************************************************************
171 *********************************************************************/
172 void hb_libmpeg2_info( hb_libmpeg2_t * m, int * width, int * height,
180 /**********************************************************************
182 **********************************************************************
184 *********************************************************************/
185 void hb_libmpeg2_close( hb_libmpeg2_t ** _m )
187 hb_libmpeg2_t * m = *_m;
189 mpeg2_close( m->libmpeg2 );
195 /**********************************************************************
196 * The decmpeg2 work object
197 **********************************************************************
199 *********************************************************************/
200 struct hb_work_private_s
202 hb_libmpeg2_t * libmpeg2;
206 /**********************************************************************
207 * hb_work_decmpeg2_init
208 **********************************************************************
210 *********************************************************************/
211 int decmpeg2Init( hb_work_object_t * w, hb_job_t * job )
213 hb_work_private_t * pv;
215 pv = calloc( 1, sizeof( hb_work_private_t ) );
216 w->private_data = pv;
218 pv->libmpeg2 = hb_libmpeg2_init();
219 pv->list = hb_list_init();
224 /**********************************************************************
226 **********************************************************************
228 *********************************************************************/
229 int decmpeg2Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
230 hb_buffer_t ** buf_out )
232 hb_work_private_t * pv = w->private_data;
233 hb_buffer_t * buf, * last = NULL;
235 // The reader found a chapter break, consume it completely, and remove it from the
236 // stream. We need to shift it.
237 if( (*buf_in)->new_chap )
239 printf("MPEG2: Chapter Break Cell Found, searching for GOP\n");
240 pv->libmpeg2->look_for_break = 2;
241 (*buf_in)->new_chap = 0;
244 hb_libmpeg2_decode( pv->libmpeg2, *buf_in, pv->list );
247 while( ( buf = hb_list_item( pv->list, 0 ) ) )
249 hb_list_rem( pv->list, buf );
265 /**********************************************************************
267 **********************************************************************
269 *********************************************************************/
270 void decmpeg2Close( hb_work_object_t * w )
272 hb_work_private_t * pv = w->private_data;
273 hb_list_close( &pv->list );
274 hb_libmpeg2_close( &pv->libmpeg2 );
278 hb_work_object_t hb_decmpeg2 =
281 "MPEG-2 decoder (libmpeg2)",