OSDN Git Service

Don't crash in decmpeg2Info if we failed to get a preview due to not finding a sequen...
[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
9 #include "mpeg2dec/mpeg2.h"
10
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 static int cadence[12];
29 static int flag = 0;
30
31 /**********************************************************************
32  * hb_libmpeg2_t
33  *********************************************************************/
34 typedef struct hb_libmpeg2_s
35 {
36     mpeg2dec_t         * libmpeg2;
37     const mpeg2_info_t * info;
38     hb_job_t           * job;
39     int                  width;
40     int                  height;
41     int                  rate;
42     int                  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 } hb_libmpeg2_t;
49
50 /**********************************************************************
51  * hb_libmpeg2_init
52  **********************************************************************
53  *
54  *********************************************************************/
55 static hb_libmpeg2_t * hb_libmpeg2_init()
56 {
57     hb_libmpeg2_t * m = calloc( sizeof( hb_libmpeg2_t ), 1 );
58
59     m->libmpeg2 = mpeg2_init();
60     m->info     = mpeg2_info( m->libmpeg2 );
61     m->last_pts = -1;
62
63     return m;
64 }
65
66 /**********************************************************************
67  * hb_libmpeg2_decode
68  **********************************************************************
69  *
70  *********************************************************************/
71 static int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
72                         hb_list_t * list_raw )
73 {
74     mpeg2_state_t   state;
75     hb_buffer_t   * buf;
76     uint8_t       * data;
77
78     if ( buf_es->size )
79     {
80         /* Feed libmpeg2 */
81         if( buf_es->start > -1 )
82         {
83             mpeg2_tag_picture( m->libmpeg2, buf_es->start >> 32,
84                                buf_es->start & 0xFFFFFFFF );
85         }
86         mpeg2_buffer( m->libmpeg2, buf_es->data,
87                       buf_es->data + buf_es->size );
88     }
89
90     for( ;; )
91     {
92         state = mpeg2_parse( m->libmpeg2 );
93         if( state == STATE_BUFFER )
94         {
95             /* Require some more data */
96             break;
97         }
98         else if( state == STATE_SEQUENCE )
99         {
100             if( !( m->width && m->height && m->rate ) )
101             {
102                 m->width  = m->info->sequence->width;
103                 m->height = m->info->sequence->height;
104                 m->rate   = m->info->sequence->frame_period;
105                 if ( m->aspect_ratio <= 0 && m->height &&
106                      m->info->sequence->pixel_height )
107                 {
108                     /* mpeg2_parse doesn't store the aspect ratio. Instead
109                      * it keeps the pixel width & height that would cause
110                      * the storage width & height to come out in the correct
111                      * aspect ratio. Convert these back to aspect ratio.
112                      * We do the calc in floating point to get the rounding right.
113                      * We round in the second decimal digit because we scale
114                      * the (integer) aspect by 9 to preserve the 1st digit.
115                      */
116                     double ar_numer = m->width * m->info->sequence->pixel_width;
117                     double ar_denom = m->height * m->info->sequence->pixel_height;
118                     m->aspect_ratio = ( ar_numer / ar_denom + .05 ) * HB_ASPECT_BASE;
119                 }
120             }
121         }
122         else if( state == STATE_GOP && m->look_for_break)
123         {
124             // we were looking for a gop to add a chapter break - we found it
125             // so now start looking for an iframe.
126             m->look_for_iframe = m->look_for_break;
127             m->look_for_break = 0;
128         }
129         else if( ( state == STATE_SLICE || state == STATE_END ) &&
130                  m->info->display_fbuf )
131         {
132             if( ( m->info->display_picture->flags &
133                   PIC_MASK_CODING_TYPE ) == PIC_FLAG_CODING_TYPE_I )
134             {
135                 // we got an iframe so we can start decoding video now
136                 m->got_iframe = 1;
137             }
138
139             if( m->got_iframe )
140             {
141                 buf  = hb_buffer_init( m->width * m->height * 3 / 2 );
142                 data = buf->data;
143
144                 buf->sequence = buf_es->sequence;
145
146                 memcpy( data, m->info->display_fbuf->buf[0],
147                         m->width * m->height );
148                 data += m->width * m->height;
149                 memcpy( data, m->info->display_fbuf->buf[1],
150                         m->width * m->height / 4 );
151                 data += m->width * m->height / 4;
152                 memcpy( data, m->info->display_fbuf->buf[2],
153                         m->width * m->height / 4 );
154
155                 if( m->info->display_picture->flags & PIC_FLAG_TAGS )
156                 {
157                     buf->start =
158                         ( (uint64_t) m->info->display_picture->tag << 32 ) |
159                         ( (uint64_t) m->info->display_picture->tag2 );
160                     /*
161                       * Add back in again to track PTS of MPEG2 frames
162                       * hb_log("MPEG2: Normal buf->start = %lld", buf->start);
163                     */
164                 }
165                 else if( m->last_pts > -1 )
166                 {
167                     /* For some reason nb_fields is sometimes 1 while it
168                        should be 2 */
169                     buf->start = m->last_pts +
170                         MAX( 2, m->info->display_picture->nb_fields ) *
171                         m->info->sequence->frame_period / 600;
172                 }
173                 else
174                 {
175                     buf->start = -1;
176                 }
177                 m->last_pts = buf->start;
178
179                 if( m->look_for_iframe && ( m->info->display_picture->flags &
180                       PIC_MASK_CODING_TYPE ) == PIC_FLAG_CODING_TYPE_I )
181                 {
182                     // we were waiting for an iframe to insert a chapter mark
183                     // and we have one.
184                     buf->new_chap = m->look_for_iframe;
185                     m->look_for_iframe = 0;
186                     const char *chap_name = "";
187                     if ( m->job && buf->new_chap > 0 &&
188                          hb_list_item( m->job->title->list_chapter,
189                                        buf->new_chap - 1 ) )
190                     {
191                         hb_chapter_t * c = hb_list_item( m->job->title->list_chapter,
192                                                          buf->new_chap - 1 );
193                         chap_name = c->title;
194                     }
195                     hb_log( "mpeg2: \"%s\" (%d) at frame %u time %lld",
196                             chap_name, buf->new_chap, m->nframes, buf->start );
197                 } else if ( m->nframes == 0 && m->job &&
198                             hb_list_item( m->job->title->list_chapter,
199                                           m->job->chapter_start - 1 ) )
200                 {
201                     hb_chapter_t * c = hb_list_item( m->job->title->list_chapter,
202                                                      m->job->chapter_start - 1 );
203                     hb_log( "mpeg2: \"%s\" (%d) at frame %u time %lld", c->title,
204                             m->job->chapter_start, m->nframes, buf->start );
205                 }
206                 ++m->nframes;
207
208                 flag = m->info->display_picture->flags;
209
210 /*  Uncomment this block to see frame-by-frame picture flags, as the video encodes.
211                hb_log("***** MPEG 2 Picture Info for PTS %lld *****", buf->start);
212                 if( flag & TOP_FIRST )
213                     hb_log("MPEG2 Flag: Top field first");
214                 if( flag & PROGRESSIVE )
215                     hb_log("MPEG2 Flag: Progressive");
216                 if( flag & COMPOSITE )
217                     hb_log("MPEG2 Flag: Composite");
218                 if( flag & SKIP )
219                     hb_log("MPEG2 Flag: Skip!");
220                 if( flag & TAGS )
221                     hb_log("MPEG2 Flag: TAGS");
222                 if(flag & REPEAT_FIRST )
223                     hb_log("MPEG2 Flag: Repeat first field");
224                 if( flag & COMPOSITE_MASK )
225                     hb_log("MPEG2 Flag: Composite mask");
226                 hb_log("fields: %d", m->info->display_picture->nb_fields);
227 */
228                 /*  Rotate the cadence tracking. */
229                 int i = 0;
230                 for(i=11; i > 0; i--)
231                 {
232                     cadence[i] = cadence[i-1];
233                 }
234
235                 if ( !(flag & PROGRESSIVE) && !(flag & TOP_FIRST) )
236                 {
237                     /* Not progressive, not top first...
238                        That means it's probably bottom
239                        first, 2 fields displayed.
240                     */
241                     //hb_log("MPEG2 Flag: Bottom field first, 2 fields displayed.");
242                     cadence[0] = BT;
243                 }
244                 else if ( !(flag & PROGRESSIVE) && (flag & TOP_FIRST) )
245                 {
246                     /* Not progressive, top is first,
247                        Two fields displayed.
248                     */
249                     //hb_log("MPEG2 Flag: Top field first, 2 fields displayed.");
250                     cadence[0] = TB;
251                 }
252                 else if ( (flag & PROGRESSIVE) && !(flag & TOP_FIRST) && !( flag & REPEAT_FIRST )  )
253                 {
254                     /* Progressive, but noting else.
255                        That means Bottom first,
256                        2 fields displayed.
257                     */
258                     //hb_log("MPEG2 Flag: Progressive. Bottom field first, 2 fields displayed.");
259                     cadence[0] = BT_PROG;
260                 }
261                 else if ( (flag & PROGRESSIVE) && !(flag & TOP_FIRST) && ( flag & REPEAT_FIRST )  )
262                 {
263                     /* Progressive, and repeat. .
264                        That means Bottom first,
265                        3 fields displayed.
266                     */
267                     //hb_log("MPEG2 Flag: Progressive repeat. Bottom field first, 3 fields displayed.");
268                     cadence[0] = BTB_PROG;
269                 }
270                 else if ( (flag & PROGRESSIVE) && (flag & TOP_FIRST) && !( flag & REPEAT_FIRST )  )
271                 {
272                     /* Progressive, top first.
273                        That means top first,
274                        2 fields displayed.
275                     */
276                     //hb_log("MPEG2 Flag: Progressive. Top field first, 2 fields displayed.");
277                     cadence[0] = TB_PROG;
278                 }
279                 else if ( (flag & PROGRESSIVE) && (flag & TOP_FIRST) && ( flag & REPEAT_FIRST )  )
280                 {
281                     /* Progressive, top, repeat.
282                        That means top first,
283                        3 fields displayed.
284                     */
285                     //hb_log("MPEG2 Flag: Progressive repeat. Top field first, 3 fields displayed.");
286                     cadence[0] = TBT_PROG;
287                 }
288
289                 if ( (cadence[2] <= TB) && (cadence[1] <= TB) && (cadence[0] > TB) && (cadence[11]) )
290                     hb_log("%fs: Video -> Film", (float)buf->start / 90000);
291                 if ( (cadence[2] > TB) && (cadence[1] <= TB) && (cadence[0] <= TB) && (cadence[11]) )
292                     hb_log("%fs: Film -> Video", (float)buf->start / 90000);
293
294                 /* Store picture flags for later use by filters */
295                 buf->flags = m->info->display_picture->flags;
296
297                 hb_list_add( list_raw, buf );
298             }
299         }
300         else if( state == STATE_INVALID )
301         {
302             mpeg2_reset( m->libmpeg2, 0 );
303         }
304     }
305     return 1;
306 }
307
308 /**********************************************************************
309  * hb_libmpeg2_info
310  **********************************************************************
311  *
312  *********************************************************************/
313 static void hb_libmpeg2_info( hb_libmpeg2_t * m, int * width, int * height,
314                         int * rate, int *aspect_ratio )
315 {
316     *width  = m->width;
317     *height = m->height;
318     if (m->info->display_fbuf)
319     {
320         if( (m->info->display_picture->flags & PROGRESSIVE) && (m->height == 480) )
321         {
322             /* The frame is progressive and it's NTSC DVD height, so change its FPS to 23.976.
323                This might not be correct for the title. It's really just for scan.c's benefit.
324                Scan.c will reset the fps to 29.97, until a simple majority of the preview
325                frames report at 23.976.
326             */
327             //hb_log("Detecting NTSC Progressive Frame");
328             m->rate = 1126125;
329         }
330     }
331     *rate   = m->rate;
332     *aspect_ratio = m->aspect_ratio;
333 }
334
335 /**********************************************************************
336  * hb_libmpeg2_close
337  **********************************************************************
338  *
339  *********************************************************************/
340 static void hb_libmpeg2_close( hb_libmpeg2_t ** _m )
341 {
342     hb_libmpeg2_t * m = *_m;
343
344     mpeg2_close( m->libmpeg2 );
345
346     free( m );
347     *_m = NULL;
348 }
349
350 /**********************************************************************
351  * The decmpeg2 work object
352  **********************************************************************
353  *
354  *********************************************************************/
355 struct hb_work_private_s
356 {
357     hb_libmpeg2_t * libmpeg2;
358     hb_list_t     * list;
359 };
360
361 /**********************************************************************
362  * hb_work_decmpeg2_init
363  **********************************************************************
364  *
365  *********************************************************************/
366 static int decmpeg2Init( hb_work_object_t * w, hb_job_t * job )
367 {
368     hb_work_private_t * pv;
369
370     pv              = calloc( 1, sizeof( hb_work_private_t ) );
371     w->private_data = pv;
372
373     pv->libmpeg2 = hb_libmpeg2_init();
374     pv->list     = hb_list_init();
375
376     pv->libmpeg2->job = job;
377
378     return 0;
379 }
380
381 /**********************************************************************
382  * Work
383  **********************************************************************
384  *
385  *********************************************************************/
386 static int decmpeg2Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
387                    hb_buffer_t ** buf_out )
388 {
389     hb_work_private_t * pv = w->private_data;
390     hb_buffer_t * buf, * last = NULL;
391     int status = HB_WORK_OK;
392
393     // The reader found a chapter break, consume it completely, and remove it from the
394     // stream. We need to shift it.
395     if( (*buf_in)->new_chap )
396     {
397         pv->libmpeg2->look_for_break = (*buf_in)->new_chap;
398         (*buf_in)->new_chap = 0;
399     }
400
401     hb_libmpeg2_decode( pv->libmpeg2, *buf_in, pv->list );
402
403     /* if we got an empty buffer signaling end-of-stream send it downstream */
404     if ( (*buf_in)->size == 0 )
405     {
406         hb_list_add( pv->list, *buf_in );
407         *buf_in = NULL;
408         status = HB_WORK_DONE;
409     }
410
411     *buf_out = NULL;
412     while( ( buf = hb_list_item( pv->list, 0 ) ) )
413     {
414         hb_list_rem( pv->list, buf );
415         if( last )
416         {
417             last->next = buf;
418             last       = buf;
419         }
420         else
421         {
422             *buf_out = buf;
423             last     = buf;
424         }
425     }
426
427     return status;
428 }
429
430 /**********************************************************************
431  * Close
432  **********************************************************************
433  *
434  *********************************************************************/
435 static void decmpeg2Close( hb_work_object_t * w )
436 {
437     hb_work_private_t * pv = w->private_data;
438
439     // don't log during scan
440     if ( pv->libmpeg2->job )
441     {
442         hb_log( "mpeg2 done: %d frames", pv->libmpeg2->nframes );
443     }
444     hb_list_close( &pv->list );
445     hb_libmpeg2_close( &pv->libmpeg2 );
446     free( pv );
447 }
448
449 static int decmpeg2Info( hb_work_object_t *w, hb_work_info_t *info )
450 {
451     hb_work_private_t *pv = w->private_data;
452
453     if ( pv && pv->libmpeg2 && pv->libmpeg2->info && pv->libmpeg2->info->sequence )
454     {
455         int aspect;
456         hb_libmpeg2_t *m = pv->libmpeg2;
457
458         hb_libmpeg2_info( m, &info->width, &info->height, &info->rate_base,
459                           &aspect );
460
461         info->aspect = (double)aspect;
462         info->rate = 27000000;
463
464         info->bitrate = m->info->sequence->byte_rate * 8;
465         info->profile = m->info->sequence->profile_level_id >> 4;
466         info->level = m->info->sequence->profile_level_id & 0xf;
467         info->name = "mpeg2";
468         return 1;
469     }
470     return 0;
471 }
472
473 hb_work_object_t hb_decmpeg2 =
474 {
475     WORK_DECMPEG2,
476     "MPEG-2 decoder (libmpeg2)",
477     decmpeg2Init,
478     decmpeg2Work,
479     decmpeg2Close,
480     decmpeg2Info
481 };
482