OSDN Git Service

Removed double EOF for CC's (one from dvd and one from cc), fixed compiler warnings...
[handbrake-jp/handbrake-jp-git.git] / libhb / reader.c
index 75fd1b4..dd47815 100644 (file)
@@ -8,9 +8,10 @@
 
 typedef struct
 {
-    int64_t last;   // last timestamp seen on this stream
     double average; // average time between packets
+    int64_t last;   // last timestamp seen on this stream
     int id;         // stream id
+    int is_audio;   // != 0 if this is an audio stream
 } stream_timing_t;
 
 typedef struct
@@ -26,9 +27,10 @@ typedef struct
     int64_t        scr_offset;
     hb_psdemux_t   demux;
     int            scr_changes;
-    uint           sequence;
-    int            saw_video;
-    int            st_slots;            // size (in slots) of stream_timing array
+    uint32_t       sequence;
+    uint8_t        st_slots;        // size (in slots) of stream_timing array
+    uint8_t        saw_video;       // != 0 if we've seen video
+    uint8_t        saw_audio;       // != 0 if we've seen audio
 } hb_reader_t;
 
 /***********************************************************************
@@ -78,6 +80,21 @@ static void push_buf( const hb_reader_t *r, hb_fifo_t *fifo, hb_buffer_t *buf )
     hb_fifo_push( fifo, buf );
 }
 
+static int is_audio( hb_reader_t *r, int id )
+{
+    int i;
+    hb_audio_t *audio;
+
+    for( i = 0; ( audio = hb_list_item( r->title->list_audio, i ) ); ++i )
+    {
+        if ( audio->id == id )
+        {
+            return 1;
+        }
+    }
+    return 0;
+}
+
 // The MPEG STD (Standard Target Decoder) essentially requires that we keep
 // per-stream timing so that when there's a timing discontinuity we can
 // seemlessly join packets on either side of the discontinuity. This join
@@ -125,7 +142,10 @@ static stream_timing_t *id_to_st( hb_reader_t *r, const hb_buffer_t *buf )
         st->id = buf->id;
         st->average = 30.*90.;
         st->last = buf->renderOffset - st->average;
-
+        if ( ( st->is_audio = is_audio( r, buf->id ) ) != 0 )
+        {
+            r->saw_audio = 1;
+        }
         st[1].id = -1;
     }
     return st;
@@ -138,7 +158,7 @@ static void update_ipt( hb_reader_t *r, const hb_buffer_t *buf )
 {
     stream_timing_t *st = id_to_st( r, buf );
     double dt = buf->renderOffset - st->last;
-    st->average += ( dt - st->average ) * (1./16.);
+    st->average += ( dt - st->average ) * (1./32.);
     st->last = buf->renderOffset;
 }
 
@@ -181,30 +201,70 @@ static void ReaderFunc( void * _r )
 
     if (r->dvd)
     {
-      /*
-       * XXX this code is a temporary hack that should go away if/when
-       *     chapter merging goes away in libhb/dvd.c
-       * map the start and end chapter numbers to on-media chapter
-       * numbers since chapter merging could cause the handbrake numbers
-       * to diverge from the media numbers and, if our chapter_end is after
-       * a media chapter that got merged, we'll stop ripping too early.
-       */
-      int start = r->job->chapter_start;
-      hb_chapter_t * chap = hb_list_item( r->title->list_chapter, chapter_end - 1 );
-
-      chapter_end = chap->index;
-      if (start > 1)
-      {
-         chap = hb_list_item( r->title->list_chapter, start - 1 );
-         start = chap->index;
-      }
-      /* end chapter mapping XXX */
-
-      if( !hb_dvd_start( r->dvd, r->title->index, start ) )
-      {
-          hb_dvd_close( &r->dvd );
-          return;
-      }
+        /*
+         * XXX this code is a temporary hack that should go away if/when
+         *     chapter merging goes away in libhb/dvd.c
+         * map the start and end chapter numbers to on-media chapter
+         * numbers since chapter merging could cause the handbrake numbers
+         * to diverge from the media numbers and, if our chapter_end is after
+         * a media chapter that got merged, we'll stop ripping too early.
+         */
+        int start = r->job->chapter_start;
+        hb_chapter_t *chap = hb_list_item( r->title->list_chapter, chapter_end - 1 );
+
+        chapter_end = chap->index;
+        if (start > 1)
+        {
+           chap = hb_list_item( r->title->list_chapter, start - 1 );
+           start = chap->index;
+        }
+        /* end chapter mapping XXX */
+
+        if( !hb_dvd_start( r->dvd, r->title, start ) )
+        {
+            hb_dvd_close( &r->dvd );
+            return;
+        }
+        if (r->job->angle)
+        {
+            hb_dvd_set_angle( r->dvd, r->job->angle );
+        }
+
+        if ( r->job->start_at_preview )
+        {
+            // XXX code from DecodePreviews - should go into its own routine
+            hb_dvd_seek( r->dvd, (float)r->job->start_at_preview /
+                         ( r->job->seek_points ? ( r->job->seek_points + 1.0 ) : 11.0 ) );
+        }
+    }
+    else if ( r->stream && r->job->start_at_preview )
+    {
+        
+        // XXX code from DecodePreviews - should go into its own routine
+        hb_stream_seek( r->stream, (float)( r->job->start_at_preview - 1 ) /
+                        ( r->job->seek_points ? ( r->job->seek_points + 1.0 ) : 11.0 ) );
+
+    } 
+    else if( r->stream )
+    {
+        /*
+         * Standard stream, seek to the starting chapter, if set, and track the
+         * end chapter so that we end at the right time.
+         */
+        int start = r->job->chapter_start;
+        hb_chapter_t *chap = hb_list_item( r->title->list_chapter, chapter_end - 1 );
+        
+        chapter_end = chap->index;
+        if (start > 1)
+        {
+            chap = hb_list_item( r->title->list_chapter, start - 1 );
+            start = chap->index;
+        }
+        
+        /*
+         * Seek to the start chapter.
+         */
+        hb_stream_seek_chapter( r->stream, start );
     }
 
     list  = hb_list_init();
@@ -213,9 +273,9 @@ static void ReaderFunc( void * _r )
     while( !*r->die && !r->job->done )
     {
         if (r->dvd)
-          chapter = hb_dvd_chapter( r->dvd );
+            chapter = hb_dvd_chapter( r->dvd );
         else if (r->stream)
-          chapter = 1;
+            chapter = hb_stream_chapter( r->stream );
 
         if( chapter < 0 )
         {
@@ -266,14 +326,7 @@ static void ReaderFunc( void * _r )
             hb_set_state( r->job->h, &state );
         }
 
-        if ( r->title->demuxer == HB_NULL_DEMUXER )
-        {
-            hb_demux_null( ps, list, &r->demux );
-        }
-        else
-        {
-            hb_demux_ps( ps, list, &r->demux );
-        }
+        (hb_demux[r->title->demuxer])( ps, list, &r->demux );
 
         while( ( buf = hb_list_item( list, 0 ) ) )
         {
@@ -287,6 +340,8 @@ static void ReaderFunc( void * _r )
                 if ( buf->id == r->title->video_id && buf->start != -1 &&
                      buf->renderOffset != -1 )
                 {
+                    // force a new scr offset computation
+                    r->scr_changes = r->demux.scr_changes - 1;
                     r->saw_video = 1;
                     hb_log( "reader: first SCR %lld", r->demux.last_scr );
                 }
@@ -314,9 +369,38 @@ static void ReaderFunc( void * _r )
                         // change. Compute a new scr offset that would make this
                         // packet follow the last of this stream with the correct
                         // average spacing.
-                        if ( find_st( r, buf ) )
+                        stream_timing_t *st = find_st( r, buf );
+
+                        if ( st )
                         {
-                            new_scr_offset( r, buf );
+                            // if this is the video stream and we don't have
+                            // audio yet or this is an audio stream
+                            // generate a new scr
+                            if ( st->is_audio ||
+                                 ( st == r->stream_timing && !r->saw_audio ) )
+                            {
+                                new_scr_offset( r, buf );
+                            }
+                            else
+                            {
+                                // defer the scr change until we get some
+                                // audio since audio has a timestamp per
+                                // frame but video & subtitles don't. Clear
+                                // the timestamps so the decoder will generate
+                                // them from the frame durations.
+                                if ( st != r->stream_timing )
+                                {
+                                    // not a video stream so it's probably
+                                    // subtitles - the best we can do is to
+                                    // line it up with the last video packet.
+                                    buf->start = r->stream_timing->last;
+                                }
+                                else
+                                {
+                                    buf->start = -1;
+                                    buf->renderOffset = -1;
+                                }
+                            }
                         }
                         else
                         {
@@ -330,7 +414,16 @@ static void ReaderFunc( void * _r )
                     }
                 }
                 if ( buf->start != -1 )
+                {
                     buf->start -= r->scr_offset;
+                    if ( r->job->pts_to_stop && buf->start > r->job->pts_to_stop )
+                    {
+                        // we're doing a subset of the input and we've hit the
+                        // stopping point.
+                        hb_buffer_close( &buf );
+                        goto done;
+                    }
+                }
 
                 buf->sequence = r->sequence++;
                 /* if there are mutiple output fifos, send a copy of the
@@ -353,6 +446,7 @@ static void ReaderFunc( void * _r )
         }
     }
 
+  done:
     // send empty buffers downstream to video & audio decoders to signal we're done.
     push_buf( r, r->job->fifo_mpeg2, hb_buffer_init(0) );
 
@@ -363,6 +457,13 @@ static void ReaderFunc( void * _r )
             push_buf( r, audio->priv.fifo_in, hb_buffer_init(0) );
     }
 
+    hb_subtitle_t *subtitle;
+    for( n = 0; ( subtitle = hb_list_item( r->job->title->list_subtitle, n ) ); ++n )
+    {
+        if ( subtitle->fifo_in && subtitle->source == VOBSUB)
+            push_buf( r, subtitle->fifo_in, hb_buffer_init(0) );
+    }
+
     hb_list_empty( &list );
     hb_buffer_close( &ps );
     if (r->dvd)
@@ -381,6 +482,10 @@ static void ReaderFunc( void * _r )
     }
 
     hb_log( "reader: done. %d scr changes", r->demux.scr_changes );
+    if ( r->demux.dts_drops )
+    {
+        hb_log( "reader: %d drops because DTS out of range", r->demux.dts_drops );
+    }
 
     free( r );
     _r = NULL;
@@ -418,37 +523,24 @@ static hb_fifo_t ** GetFifoForId( hb_job_t * job, int id )
         }
     }
 
-    if( job->indepth_scan ) {
-        /*
-         * Count the occurances of the subtitles, don't actually
-         * return any to encode unless we are looking fro forced
-         * subtitles in which case we need to look in the sub picture
-         * to see if it has the forced flag enabled.
-         */
-        for (i=0; i < hb_list_count(title->list_subtitle); i++) {
-            subtitle =  hb_list_item( title->list_subtitle, i);
-            if (id == subtitle->id) {
+    for( i=0; i < hb_list_count( title->list_subtitle ); i++ ) {
+        subtitle =  hb_list_item( title->list_subtitle, i );
+        if (id == subtitle->id) {
+            subtitle->hits++;
+            if( !job->indepth_scan || job->subtitle_force )
+            {
                 /*
-                 * A hit, count it.
+                 * Pass the subtitles to be processed if we are not scanning, or if
+                 * we are scanning and looking for forced subs, then pass them up
+                 * to decode whether the sub is a forced one.
                  */
-                subtitle->hits++;
-                if( job->subtitle_force )
-                {
-
-                    fifos[0] = subtitle->fifo_in;
-                    return fifos;
-                }
-                break;
+                fifos[0] = subtitle->fifo_in;
+                return fifos;
             }
-        }
-    } else {
-        if( ( subtitle = hb_list_item( title->list_subtitle, 0 ) ) &&
-            id == subtitle->id )
-        {
-            fifos[0] = subtitle->fifo_in;
-            return fifos;
+            break;
         }
     }
+    
     if( !job->indepth_scan )
     {
         n = 0;