OSDN Git Service

Push an EOF onto the subtitle fifos from the reader for DVD VOBSUBs and also from...
[handbrake-jp/handbrake-jp-git.git] / libhb / decmpeg2.c
1 /* $Id: decmpeg2.c,v 1.12 2005/03/03 16:30:42 titer Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.fr/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include "hb.h"
8 #include "hbffmpeg.h"
9 #include "mpeg2dec/mpeg2.h"
10 #include "deccc608sub.h"
11
12 /* Cadence tracking */
13 #ifndef PIC_FLAG_REPEAT_FIRST_FIELD
14 #define PIC_FLAG_REPEAT_FIRST_FIELD 256
15 #endif
16 #define TOP_FIRST PIC_FLAG_TOP_FIELD_FIRST
17 #define PROGRESSIVE PIC_FLAG_PROGRESSIVE_FRAME
18 #define COMPOSITE PIC_FLAG_COMPOSITE_DISPLAY
19 #define SKIP PIC_FLAG_SKIP
20 #define TAGS PIC_FLAG_TAGS
21 #define REPEAT_FIRST PIC_FLAG_REPEAT_FIRST_FIELD
22 #define COMPOSITE_MASK PIC_MASK_COMPOSITE_DISPLAY
23 #define TB 8
24 #define BT 16
25 #define BT_PROG 32
26 #define BTB_PROG 64
27 #define TB_PROG 128
28 #define TBT_PROG 256
29
30 /**********************************************************************
31  * hb_libmpeg2_t
32  *********************************************************************/
33 typedef struct hb_libmpeg2_s
34 {
35     mpeg2dec_t         * libmpeg2;
36     const mpeg2_info_t * info;
37     hb_job_t           * job;
38     hb_title_t         * title;
39     int                  width;
40     int                  height;
41     int                  rate;
42     double               aspect_ratio;
43     int                  got_iframe;        /* set when we get our first iframe */
44     int                  look_for_iframe;   /* need an iframe to add chap break */
45     int                  look_for_break;    /* need gop start to add chap break */
46     uint32_t             nframes;           /* number of frames we've decoded */
47     int64_t              last_pts;
48     int cadence[12];
49     int flag;
50     struct s_write       cc608;             /* Closed Captions */
51     hb_subtitle_t      * subtitle;
52 } hb_libmpeg2_t;
53
54 /**********************************************************************
55  * hb_libmpeg2_init
56  **********************************************************************
57  *
58  *********************************************************************/
59 static hb_libmpeg2_t * hb_libmpeg2_init()
60 {
61     hb_libmpeg2_t * m = calloc( sizeof( hb_libmpeg2_t ), 1 );
62
63     m->libmpeg2 = mpeg2_init();
64     m->info     = mpeg2_info( m->libmpeg2 );
65     m->last_pts = -1;
66
67    /* Closed Captions init, whether needed or not */
68     general_608_init( &m->cc608 );
69     m->cc608.data608 = calloc(1, sizeof(struct eia608));
70     return m;
71 }
72
73 static void hb_mpeg2_cc( hb_libmpeg2_t * m, uint8_t *cc_block )
74 {
75     uint8_t cc_valid = (*cc_block & 4) >>2;
76     uint8_t cc_type = *cc_block & 3;
77     
78     if( !m->job )
79     {
80         /*
81          * Ignore CC decoding during scanning.
82          */
83         return;
84     }
85
86     if (cc_valid || cc_type==3)
87     {
88         switch (cc_type)
89         {
90         case 0:
91             // CC1 stream
92             process608( cc_block+1, 2, &m->cc608 );
93             break;
94         case 1:
95             // CC2 stream
96             //process608( cc_block+1, 2, &m->cc608 );
97             break;
98         case 2: //EIA-708
99             // DTVCC packet data
100             // Fall through
101         case 3: //EIA-708
102         {
103             uint8_t temp[4];
104             temp[0]=cc_valid;
105             temp[1]=cc_type;
106             temp[2]=cc_block[1];
107             temp[3]=cc_block[2];
108             //do_708 ((const unsigned char *) temp, 4);
109         }
110         break;
111         default:
112             break;
113         } 
114     } 
115     else
116     {
117         hb_log("Ignoring invalid CC block");
118     }
119 }
120
121 static hb_buffer_t *hb_copy_frame( hb_job_t *job, int width, int height,
122                                    uint8_t* y, uint8_t *u, uint8_t *v )
123 {
124     int dst_w = width, dst_h = height;
125     if ( job )
126     {
127         dst_w = job->title->width;
128         dst_h = job->title->height;
129     }
130     int dst_wh = dst_w * dst_h;
131     hb_buffer_t *buf  = hb_video_buffer_init( dst_w, dst_h );
132
133     if ( dst_w != width || dst_h != height )
134     {
135         // we're encoding and the frame dimensions don't match the title dimensions -
136         // rescale & matte Y, U, V into our output buf.
137         AVPicture in, out;
138         avpicture_alloc(&in,  PIX_FMT_YUV420P, width, height );
139         avpicture_alloc(&out, PIX_FMT_YUV420P, dst_w, dst_h );
140
141         int src_wh = width * height;
142         memcpy( in.data[0], y, src_wh );
143         memcpy( in.data[1], u, src_wh >> 2 );
144         memcpy( in.data[2], v, src_wh >> 2 );
145         struct SwsContext *context = sws_getContext( width, height, PIX_FMT_YUV420P,
146                                                      dst_w, dst_h, PIX_FMT_YUV420P,
147                                                      SWS_LANCZOS|SWS_ACCURATE_RND,
148                                                      NULL, NULL, NULL );
149         sws_scale( context, in.data, in.linesize, 0, height, out.data, out.linesize );
150         sws_freeContext( context );
151
152         uint8_t *data = buf->data;
153         memcpy( data, out.data[0], dst_wh );
154         data += dst_wh;
155         // U & V planes are 1/4 the size of Y plane.
156         dst_wh >>= 2;
157         memcpy( data, out.data[1], dst_wh );
158         data += dst_wh;
159         memcpy( data, out.data[2], dst_wh );
160
161         avpicture_free( &out );
162         avpicture_free( &in );
163     }
164     else
165     {
166         // we're scanning or the frame dimensions match the title's dimensions
167         // so we can do a straight copy.
168         uint8_t *data = buf->data;
169         memcpy( data, y, dst_wh );
170         data += dst_wh;
171         // U & V planes are 1/4 the size of Y plane.
172         dst_wh >>= 2;
173         memcpy( data, u, dst_wh );
174         data += dst_wh;
175         memcpy( data, v, dst_wh );
176     }
177     return buf;
178 }
179
180 /**********************************************************************
181  * hb_libmpeg2_decode
182  **********************************************************************
183  *
184  *********************************************************************/
185 static int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
186                                hb_list_t * list_raw )
187 {
188     mpeg2_state_t   state;
189     hb_buffer_t   * buf;
190
191     if ( buf_es->size )
192     {
193         /* Feed libmpeg2 */
194         if( buf_es->start > -1 )
195         {
196             mpeg2_tag_picture( m->libmpeg2, buf_es->start >> 32,
197                                buf_es->start & 0xFFFFFFFF );
198         }
199         mpeg2_buffer( m->libmpeg2, buf_es->data,
200                       buf_es->data + buf_es->size );
201     }
202
203     for( ;; )
204     {
205         state = mpeg2_parse( m->libmpeg2 );
206         if( state == STATE_BUFFER )
207         {
208             /* Require some more data */
209             break;
210         }
211         else if( state == STATE_SEQUENCE )
212         {
213             if( !( m->width && m->height && m->rate ) )
214             {
215                 m->width  = m->info->sequence->width;
216                 m->height = m->info->sequence->height;
217                 m->rate   = m->info->sequence->frame_period;
218                 if ( m->aspect_ratio <= 0 && m->height &&
219                      m->info->sequence->pixel_height )
220                 {
221                     /* mpeg2_parse doesn't store the aspect ratio. Instead
222                      * it keeps the pixel width & height that would cause
223                      * the storage width & height to come out in the correct
224                      * aspect ratio. Convert these back to aspect ratio.
225                      */
226                     double ar_numer = m->width * m->info->sequence->pixel_width;
227                     double ar_denom = m->height * m->info->sequence->pixel_height;
228                     m->aspect_ratio = ar_numer / ar_denom;
229                 }
230             }
231         }
232         else if( state == STATE_GOP && m->look_for_break)
233         {
234             // we were looking for a gop to add a chapter break - we found it
235             // so now start looking for an iframe.
236             m->look_for_iframe = m->look_for_break;
237             m->look_for_break = 0;
238         }
239         else if( ( state == STATE_SLICE || state == STATE_END ) &&
240                  m->info->display_fbuf )
241         {
242             if( ( m->info->display_picture->flags &
243                   PIC_MASK_CODING_TYPE ) == PIC_FLAG_CODING_TYPE_I )
244             {
245                 // we got an iframe so we can start decoding video now
246                 m->got_iframe = 1;
247             }
248
249             if( m->got_iframe )
250             {
251                 buf  = hb_copy_frame( m->job, m->info->sequence->width,
252                                       m->info->sequence->height,
253                                       m->info->display_fbuf->buf[0],
254                                       m->info->display_fbuf->buf[1],
255                                       m->info->display_fbuf->buf[2] );
256                 buf->sequence = buf_es->sequence;
257
258                 if( m->info->display_picture->flags & PIC_FLAG_TAGS )
259                 {
260                     buf->start =
261                         ( (uint64_t) m->info->display_picture->tag << 32 ) |
262                         ( (uint64_t) m->info->display_picture->tag2 );
263                 }
264                 else if( m->last_pts > -1 )
265                 {
266                     /* For some reason nb_fields is sometimes 1 while it
267                        should be 2 */
268                     buf->start = m->last_pts +
269                         MAX( 2, m->info->display_picture->nb_fields ) *
270                         m->info->sequence->frame_period / 600;
271                 }
272                 else
273                 {
274                     buf->start = -1;
275                 }
276                 m->last_pts = buf->start;
277
278                 if( m->look_for_iframe && ( m->info->display_picture->flags &
279                       PIC_MASK_CODING_TYPE ) == PIC_FLAG_CODING_TYPE_I )
280                 {
281                     // we were waiting for an iframe to insert a chapter mark
282                     // and we have one.
283                     buf->new_chap = m->look_for_iframe;
284                     m->look_for_iframe = 0;
285                     const char *chap_name = "";
286                     if ( m->job && buf->new_chap > 0 &&
287                          hb_list_item( m->job->title->list_chapter,
288                                        buf->new_chap - 1 ) )
289                     {
290                         hb_chapter_t * c = hb_list_item( m->job->title->list_chapter,
291                                                          buf->new_chap - 1 );
292                         chap_name = c->title;
293                     }
294                     hb_log( "mpeg2: \"%s\" (%d) at frame %u time %lld",
295                             chap_name, buf->new_chap, m->nframes, buf->start );
296                 } else if ( m->nframes == 0 && m->job &&
297                             hb_list_item( m->job->title->list_chapter,
298                                           m->job->chapter_start - 1 ) )
299                 {
300                     hb_chapter_t * c = hb_list_item( m->job->title->list_chapter,
301                                                      m->job->chapter_start - 1 );
302                     hb_log( "mpeg2: \"%s\" (%d) at frame %u time %lld", c->title,
303                             m->job->chapter_start, m->nframes, buf->start );
304                 }
305                 ++m->nframes;
306
307                 m->flag = m->info->display_picture->flags;
308
309 /*  Uncomment this block to see frame-by-frame picture flags, as the video encodes.
310                hb_log("***** MPEG 2 Picture Info for PTS %lld *****", buf->start);
311                 if( m->flag & TOP_FIRST )
312                     hb_log("MPEG2 Flag: Top field first");
313                 if( m->flag & PROGRESSIVE )
314                     hb_log("MPEG2 Flag: Progressive");
315                 if( m->flag & COMPOSITE )
316                     hb_log("MPEG2 Flag: Composite");
317                 if( m->flag & SKIP )
318                     hb_log("MPEG2 Flag: Skip!");
319                 if( m->flag & TAGS )
320                     hb_log("MPEG2 Flag: TAGS");
321                 if(fm->lag & REPEAT_FIRST )
322                     hb_log("MPEG2 Flag: Repeat first field");
323                 if( m->flag & COMPOSITE_MASK )
324                     hb_log("MPEG2 Flag: Composite mask");
325                 hb_log("fields: %d", m->info->display_picture->nb_fields);
326 */
327                 /*  Rotate the cadence tracking. */
328                 int i = 0;
329                 for(i=11; i > 0; i--)
330                 {
331                     m->cadence[i] = m->cadence[i-1];
332                 }
333
334                 if ( !(m->flag & PROGRESSIVE) && !(m->flag & TOP_FIRST) )
335                 {
336                     /* Not progressive, not top first...
337                        That means it's probably bottom
338                        first, 2 fields displayed.
339                     */
340                     //hb_log("MPEG2 Flag: Bottom field first, 2 fields displayed.");
341                     m->cadence[0] = BT;
342                 }
343                 else if ( !(m->flag & PROGRESSIVE) && (m->flag & TOP_FIRST) )
344                 {
345                     /* Not progressive, top is first,
346                        Two fields displayed.
347                     */
348                     //hb_log("MPEG2 Flag: Top field first, 2 fields displayed.");
349                     m->cadence[0] = TB;
350                 }
351                 else if ( (m->flag & PROGRESSIVE) && !(m->flag & TOP_FIRST) && !( m->flag & REPEAT_FIRST )  )
352                 {
353                     /* Progressive, but noting else.
354                        That means Bottom first,
355                        2 fields displayed.
356                     */
357                     //hb_log("MPEG2 Flag: Progressive. Bottom field first, 2 fields displayed.");
358                     m->cadence[0] = BT_PROG;
359                 }
360                 else if ( (m->flag & PROGRESSIVE) && !(m->flag & TOP_FIRST) && ( m->flag & REPEAT_FIRST )  )
361                 {
362                     /* Progressive, and repeat. .
363                        That means Bottom first,
364                        3 fields displayed.
365                     */
366                     //hb_log("MPEG2 Flag: Progressive repeat. Bottom field first, 3 fields displayed.");
367                     m->cadence[0] = BTB_PROG;
368                 }
369                 else if ( (m->flag & PROGRESSIVE) && (m->flag & TOP_FIRST) && !( m->flag & REPEAT_FIRST )  )
370                 {
371                     /* Progressive, top first.
372                        That means top first,
373                        2 fields displayed.
374                     */
375                     //hb_log("MPEG2 Flag: Progressive. Top field first, 2 fields displayed.");
376                     m->cadence[0] = TB_PROG;
377                 }
378                 else if ( (m->flag & PROGRESSIVE) && (m->flag & TOP_FIRST) && ( m->flag & REPEAT_FIRST )  )
379                 {
380                     /* Progressive, top, repeat.
381                        That means top first,
382                        3 fields displayed.
383                     */
384                     //hb_log("MPEG2 Flag: Progressive repeat. Top field first, 3 fields displayed.");
385                     m->cadence[0] = TBT_PROG;
386                 }
387
388                 if ( (m->cadence[2] <= TB) && (m->cadence[1] <= TB) && (m->cadence[0] > TB) && (m->cadence[11]) )
389                     hb_log("%fs: Video -> Film", (float)buf->start / 90000);
390                 if ( (m->cadence[2] > TB) && (m->cadence[1] <= TB) && (m->cadence[0] <= TB) && (m->cadence[11]) )
391                     hb_log("%fs: Film -> Video", (float)buf->start / 90000);
392
393                 /* Store picture flags for later use by filters */
394                 buf->flags = m->info->display_picture->flags;
395
396                 hb_list_add( list_raw, buf );
397             }
398         }
399         else if( state == STATE_INVALID )
400         {
401             mpeg2_reset( m->libmpeg2, 0 );
402         }
403
404         /*
405          * Look for Closed Captions if scanning (!job) or if closed captions have been requested.
406          */
407         if( ( !m->job || m->subtitle) &&
408             ( m->info->user_data_len != 0 &&
409               m->info->user_data[0] == 0x43 &&
410               m->info->user_data[1] == 0x43 ) ) 
411         {
412             int i, j;
413             const uint8_t *header = &m->info->user_data[4];
414             uint8_t pattern=header[0] & 0x80;
415             int field1packet = 0; /* expect Field 1 first */
416             if (pattern==0x00) 
417                 field1packet=1; /* expect Field 1 second */
418             int capcount=(header[0] & 0x1e) / 2;
419             header++;
420             
421             m->cc608.last_pts = m->last_pts;
422
423             /*
424              * Add closed captions to the title if we are scanning (no job).
425              *
426              * Just because we don't add this doesn't mean that there aren't any when 
427              * we scan, just that noone said anything. So you should be able to add
428              * closed captions some other way (See decmpeg2Init() for alternative
429              * approach of assuming that there are always CC, which is probably
430              * safer - however I want to leave the autodetect in here for now to
431              * see how it goes).
432              */
433             if( !m->job && m->title )
434             {
435                 hb_subtitle_t * subtitle;
436                 int found = 0;
437                 int i;
438                 
439                 for( i = 0; i < hb_list_count( m->title->list_subtitle ); i++ )
440                 {
441                     subtitle = hb_list_item( m->title->list_subtitle, i);
442                     if( subtitle && subtitle->source == CCSUB ) 
443                     {
444                         found = 1;
445                         break;
446                     }
447                 }
448                 
449                 if( !found )
450                 {
451                     subtitle = calloc( sizeof( hb_subtitle_t ), 1 );
452                     subtitle->track = 0;
453                     subtitle->id = 0x0;
454                     snprintf( subtitle->lang, sizeof( subtitle->lang ), "Closed Captions");
455                     snprintf( subtitle->iso639_2, sizeof( subtitle->iso639_2 ), "und");
456                     subtitle->format = TEXTSUB;
457                     subtitle->source = CCSUB;
458                     subtitle->dest   = PASSTHRUSUB;
459                     subtitle->type = 5; 
460                     
461                     hb_list_add( m->title->list_subtitle, subtitle );
462                 }
463             }
464
465             for( i=0; i<capcount; i++ )
466             {
467                 for( j=0; j<2; j++ )
468                 {
469                     uint8_t data[3];
470                     data[0] = header[0];
471                     data[1] = header[1];
472                     data[2] = header[2];
473                     header += 3;
474                     /* Field 1 and 2 data can be in either order,
475                        with marker bytes of \xff and \xfe
476                        Since markers can be repeated, use pattern as well */
477                     if( data[0] == 0xff && j == field1packet )
478                     {
479                         data[0] = 0x04; // Field 1
480                     }   
481                     else
482                     {
483                         data[0] = 0x05; // Field 2
484                     }
485                     hb_mpeg2_cc( m, data );
486                 }
487             }
488             // Deal with extra closed captions some DVD have.
489             while( header[0]==0xfe || header[0]==0xff )
490             {
491                 for( j=0; j<2; j++ )
492                 {
493                     uint8_t data[3];
494                     data[0] = header[0];
495                     data[1] = header[1];
496                     data[2] = header[2];
497                     header += 3;
498                     /* Field 1 and 2 data can be in either order,
499                        with marker bytes of \xff and \xfe
500                        Since markers can be repeated, use pattern as well */
501                     if( data[0] == 0xff && j == field1packet )
502                     {
503                         data[0] = 0x04; // Field 1
504                     }   
505                     else
506                     {
507                         data[0] = 0x05; // Field 2
508                     } 
509                     hb_mpeg2_cc( m, data );
510                 }
511             }   
512         }
513     }
514     return 1;
515 }
516
517 /**********************************************************************
518  * hb_libmpeg2_close
519  **********************************************************************
520  *
521  *********************************************************************/
522 static void hb_libmpeg2_close( hb_libmpeg2_t ** _m )
523 {
524     hb_libmpeg2_t * m = *_m;
525
526     mpeg2_close( m->libmpeg2 );
527
528     free( m->cc608.data608 );
529     general_608_close( &m->cc608 );
530
531     free( m );
532     *_m = NULL;
533 }
534
535 /**********************************************************************
536  * The decmpeg2 work object
537  **********************************************************************
538  *
539  *********************************************************************/
540 struct hb_work_private_s
541 {
542     hb_libmpeg2_t * libmpeg2;
543     hb_list_t     * list;
544 };
545
546 /**********************************************************************
547  * hb_work_decmpeg2_init
548  **********************************************************************
549  *
550  *********************************************************************/
551 static int decmpeg2Init( hb_work_object_t * w, hb_job_t * job )
552 {
553     hb_work_private_t * pv;
554
555     pv              = calloc( 1, sizeof( hb_work_private_t ) );
556     w->private_data = pv;
557
558     pv->libmpeg2 = hb_libmpeg2_init();
559     pv->list     = hb_list_init();
560
561     pv->libmpeg2->job = job;
562
563     if( job && job->title ) {
564         pv->libmpeg2->title = job->title;
565     }
566
567     /*
568      * If not scanning, then are we supposed to extract Closed Captions?
569      */
570     if( job )
571     {
572         hb_subtitle_t * subtitle;
573         int i;
574         
575         for( i = 0; i < hb_list_count( job->list_subtitle ); i++ )
576         {
577             subtitle = hb_list_item( job->list_subtitle, i);
578             if( subtitle && subtitle->source == CCSUB ) 
579             {
580                 pv->libmpeg2->subtitle = subtitle;
581                 pv->libmpeg2->cc608.subtitle = subtitle;
582                 break;
583             }
584         }
585
586     }
587
588     /*
589      * During a scan add a Closed Caption subtitle track to the title, 
590      * since we may have CC. Don't bother actually trying to detect CC
591      * since we'd have to go through too much of the source.
592      *
593     if( !job && w->title )
594     {
595         hb_subtitle_t * subtitle;
596         int found = 0;
597         int i;
598
599         for( i = 0; i < hb_list_count( w->title->list_subtitle ); i++ )
600         {
601             subtitle = hb_list_item( w->title->list_subtitle, i);
602             if( subtitle && subtitle->source == CCSUB ) 
603             {
604                 found = 1;
605                 break;
606             }
607         }
608
609         if( !found )
610         {
611             subtitle = calloc( sizeof( hb_subtitle_t ), 1 );
612             subtitle->track = 0;
613             subtitle->id = 0x0;
614             snprintf( subtitle->lang, sizeof( subtitle->lang ), "Closed Captions");
615             snprintf( subtitle->iso639_2, sizeof( subtitle->iso639_2 ), "und");
616             subtitle->format = TEXTSUB;
617             subtitle->source = CCSUB;
618             subtitle->dest   = PASSTHRUSUB;
619             subtitle->type = 5; 
620
621             hb_list_add( w->title->list_subtitle, subtitle );
622         }
623     }
624     */
625
626     return 0;
627 }
628
629 /**********************************************************************
630  * Work
631  **********************************************************************
632  *
633  *********************************************************************/
634 static int decmpeg2Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
635                          hb_buffer_t ** buf_out )
636 {
637     hb_work_private_t * pv = w->private_data;
638     hb_buffer_t * buf, * last = NULL;
639     int status = HB_WORK_OK;
640
641     if( w->title && pv && pv->libmpeg2 && !pv->libmpeg2->title ) {
642         pv->libmpeg2->title = w->title;
643     }
644
645     // The reader found a chapter break, consume it completely, and remove it from the
646     // stream. We need to shift it.
647     if( (*buf_in)->new_chap )
648     {
649         pv->libmpeg2->look_for_break = (*buf_in)->new_chap;
650         (*buf_in)->new_chap = 0;
651     }
652
653     hb_libmpeg2_decode( pv->libmpeg2, *buf_in, pv->list );
654
655     /* if we got an empty buffer signaling end-of-stream send it downstream */
656     if ( (*buf_in)->size == 0 )
657     {
658         hb_list_add( pv->list, *buf_in );
659         *buf_in = NULL;
660         status = HB_WORK_DONE;
661         /*
662          * Let the Closed Captions know that it is the end of the data.
663          */
664         if( pv->libmpeg2->subtitle )
665         {
666             handle_end_of_data( &pv->libmpeg2->cc608 );
667         }
668     }
669
670     *buf_out = NULL;
671     while( ( buf = hb_list_item( pv->list, 0 ) ) )
672     {
673         hb_list_rem( pv->list, buf );
674         if( last )
675         {
676             last->next = buf;
677             last       = buf;
678         }
679         else
680         {
681             *buf_out = buf;
682             last     = buf;
683         }
684     }
685
686     return status;
687 }
688
689 /**********************************************************************
690  * Close
691  **********************************************************************
692  *
693  *********************************************************************/
694 static void decmpeg2Close( hb_work_object_t * w )
695 {
696     hb_work_private_t * pv = w->private_data;
697
698     // don't log during scan
699     if ( pv->libmpeg2->job )
700     {
701         hb_log( "mpeg2 done: %d frames", pv->libmpeg2->nframes );
702     }
703     hb_list_close( &pv->list );
704     hb_libmpeg2_close( &pv->libmpeg2 );
705     free( pv );
706 }
707
708 static int decmpeg2Info( hb_work_object_t *w, hb_work_info_t *info )
709 {
710     hb_work_private_t *pv = w->private_data;
711
712     memset( info, 0, sizeof(*info) );
713
714     if ( pv && pv->libmpeg2 && pv->libmpeg2->info && pv->libmpeg2->info->sequence )
715     {
716         hb_libmpeg2_t *m = pv->libmpeg2;
717
718         info->width = m->width;
719         info->height = m->height;
720         info->pixel_aspect_width = m->info->sequence->pixel_width;
721         info->pixel_aspect_height = m->info->sequence->pixel_height;
722         info->aspect = m->aspect_ratio;
723
724         // if the frame is progressive & NTSC DVD height report it as 23.976 FPS
725         // so that scan can autodetect NTSC film
726         info->rate = 27000000;
727         info->rate_base = ( m->info->display_fbuf && m->info->display_picture &&
728                             (m->info->display_picture->flags & PROGRESSIVE) &&
729                             (m->height == 480 ) ) ?  1126125 : m->rate;
730
731         info->bitrate = m->info->sequence->byte_rate * 8;
732         info->profile = m->info->sequence->profile_level_id >> 4;
733         info->level = m->info->sequence->profile_level_id & 0xf;
734         info->name = "mpeg2";
735         return 1;
736     }
737     return 0;
738 }
739
740 hb_work_object_t hb_decmpeg2 =
741 {
742     WORK_DECMPEG2,
743     "MPEG-2 decoder (libmpeg2)",
744     decmpeg2Init,
745     decmpeg2Work,
746     decmpeg2Close,
747     decmpeg2Info
748 };
749