OSDN Git Service

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