OSDN Git Service

Another minor step on the way back to Solaris compiles - not linking as yet.
[handbrake-jp/handbrake-jp-git.git] / libhb / reader.c
index bdb1cf0..7b44a65 100644 (file)
@@ -11,6 +11,7 @@ typedef struct
     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
@@ -27,8 +28,9 @@ typedef struct
     hb_psdemux_t   demux;
     int            scr_changes;
     uint           sequence;
-    int            saw_video;
-    int            st_slots;            // size (in slots) of stream_timing array
+    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;
@@ -209,25 +229,49 @@ static void ReaderFunc( void * _r )
         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 / 11. );
+            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 ) / 11. );
+        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();
     hb_buffer_t *ps = hb_buffer_init( HB_DVD_READ_BUFFER_SIZE );
-    r->demux.flaky_clock = r->title->flaky_clock;
 
     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 )
         {
@@ -325,10 +369,11 @@ static void ReaderFunc( void * _r )
 
                         if ( st )
                         {
-                            // if this isn't the video stream or we don't
-                            // have audio yet then generate a new scr
-                            if ( st != r->stream_timing ||
-                                 r->stream_timing[1].id == -1 )
+                            // 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 );
                             }
@@ -336,11 +381,21 @@ static void ReaderFunc( void * _r )
                             {
                                 // defer the scr change until we get some
                                 // audio since audio has a timestamp per
-                                // frame but video doesn't. Clear the timestamps
-                                // so the decoder will regenerate them from
-                                // the frame durations.
-                                buf->start = -1;
-                                buf->renderOffset = -1;
+                                // 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