From 0ac869507784e807357b06b61fbb4b69f4191278 Mon Sep 17 00:00:00 2001
From: jstebbins <jstebbins.hb@gmail.com>
Date: Tue, 19 May 2009 22:27:11 +0000
Subject: mkv soft subtitle support - new libmkv 0.6.4 with subtitle track
 support - muxmkv supports vobsub and closed caption subtitles - added
 subtitle format, source, and dest initialization to dvdnav - moved
 subtitle_force flag into hb_subtitle_t struct as it needs to   be settable
 per subtitle - gtk ui added subtitle tab which allows selection of multiple
 subtitles - reorgainize subtitle sync code to prevent dropping of subtitles
 when   multiple subtitles are enabled

git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@2428 b64f7644-9d1e-0410-96f1-a4d463321fa5
---
 libhb/common.h    |   5 +-
 libhb/decvobsub.c | 102 ++++++++++++----------
 libhb/dvdnav.c    |   4 +
 libhb/encvobsub.c |  18 +++-
 libhb/fifo.c      |   1 +
 libhb/muxmkv.c    |  87 ++++++++++++++-----
 libhb/reader.c    |   2 +-
 libhb/sync.c      | 246 +++++++++++++++++++++++++++---------------------------
 libhb/work.c      |   8 +-
 9 files changed, 279 insertions(+), 194 deletions(-)

(limited to 'libhb')

diff --git a/libhb/common.h b/libhb/common.h
index 516318907..224b40c78 100644
--- a/libhb/common.h
+++ b/libhb/common.h
@@ -238,7 +238,6 @@ struct hb_job_s
 
     int indepth_scan;
     hb_subtitle_t ** select_subtitle;
-    int subtitle_force;
     char * native_language;
 
     int             angle;              // dvd angle to encode
@@ -445,6 +444,7 @@ struct hb_subtitle_s
     enum subtype { PICTURESUB, TEXTSUB } format;
     enum subsource { VOBSUB, SRTSUB, CC608SUB, CC708SUB } source;
     enum subdest { RENDERSUB, PASSTHRUSUB } dest;
+    int  force;
     char lang[1024];
     char iso639_2[4];
     uint8_t type; /* Closed Caption, Childrens, Directors etc */
@@ -639,6 +639,9 @@ struct hb_work_object_s
     /* Pointer hb_audio_t so we have access to the info in the audio worker threads. */
     hb_audio_t        * audio;
 
+    /* Pointer hb_subtitle_t so we have access to the info in the subtitle worker threads. */
+    hb_subtitle_t     * subtitle;
+
     hb_work_private_t * private_data;
 
     hb_thread_t       * thread;
diff --git a/libhb/decvobsub.c b/libhb/decvobsub.c
index fd1f89179..e5633d54d 100644
--- a/libhb/decvobsub.c
+++ b/libhb/decvobsub.c
@@ -8,27 +8,27 @@
 
 struct hb_work_private_s
 {
-    hb_job_t * job;
-
-    uint8_t    buf[0xFFFF];
-    int        size_sub;
-    int        size_got;
-    int        size_rle;
-    int64_t    pts;
-    int64_t    pts_start;
-    int64_t    pts_stop;
-    int        pts_forced;
-    int        x;
-    int        y;
-    int        width;
-    int        height;
-    int        stream_id;
-
-    int        offsets[2];
-    uint8_t    lum[4];
-    uint8_t    chromaU[4];
-    uint8_t    chromaV[4];
-    uint8_t    alpha[4];
+    hb_job_t    * job;
+
+    hb_buffer_t * buf;
+    int           size_sub;
+    int           size_got;
+    int           size_rle;
+    int64_t       pts;
+    int64_t       pts_start;
+    int64_t       pts_stop;
+    int           pts_forced;
+    int           x;
+    int           y;
+    int           width;
+    int           height;
+    int           stream_id;
+
+    int           offsets[2];
+    uint8_t       lum[4];
+    uint8_t       chromaU[4];
+    uint8_t       chromaV[4];
+    uint8_t       alpha[4];
 };
 
 static hb_buffer_t * Decode( hb_work_object_t * );
@@ -76,7 +76,10 @@ int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
             pv->size_sub = size_sub;
             pv->size_rle = size_rle;
 
-            memcpy( pv->buf, in->data, in->size );
+            pv->buf      = hb_buffer_init( 0xFFFF );
+            memcpy( pv->buf->data, in->data, in->size );
+            pv->buf->id = in->id;
+            pv->buf->sequence = in->sequence;
             pv->size_got = in->size;
             pv->pts      = in->start;
         }
@@ -86,7 +89,9 @@ int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
         /* We are waiting for the end of the current subtitle */
         if( in->size <= pv->size_sub - pv->size_got )
         {
-            memcpy( pv->buf + pv->size_got, in->data, in->size );
+            memcpy( pv->buf->data + pv->size_got, in->data, in->size );
+            pv->buf->id = in->id;
+            pv->buf->sequence = in->sequence;
             pv->size_got += in->size;
             if( in->start >= 0 )
             {
@@ -99,11 +104,14 @@ int decsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
 
     if( pv->size_sub && pv->size_sub == pv->size_got )
     {
+        pv->buf->size = pv->size_sub;
+
         /* We got a complete subtitle, decode it */
         *buf_out = Decode( w );
 
         if( buf_out && *buf_out )
         {
+            (*buf_out)->id = in->id;
             (*buf_out)->sequence = in->sequence;
         }
 
@@ -145,6 +153,7 @@ static void ParseControls( hb_work_object_t * w )
     hb_job_t * job = pv->job;
     hb_title_t * title = job->title;
     hb_subtitle_t * subtitle;
+    uint8_t * buf = pv->buf->data;
 
     int i, n;
     int command;
@@ -161,12 +170,12 @@ static void ParseControls( hb_work_object_t * w )
 
     for( i = pv->size_rle; ; )
     {
-        date = ( pv->buf[i] << 8 ) | pv->buf[i+1]; i += 2;
-        next = ( pv->buf[i] << 8 ) | pv->buf[i+1]; i += 2;
+        date = ( buf[i] << 8 ) | buf[i+1]; i += 2;
+        next = ( buf[i] << 8 ) | buf[i+1]; i += 2;
 
         for( ;; )
         {
-            command = pv->buf[i++];
+            command = buf[i++];
 
             /*
              * There are eight commands available for
@@ -224,10 +233,10 @@ static void ParseControls( hb_work_object_t * w )
                     int colors[4];
                     int j;
 
-                    colors[0] = (pv->buf[i+0]>>4)&0x0f;
-                    colors[1] = (pv->buf[i+0])&0x0f;
-                    colors[2] = (pv->buf[i+1]>>4)&0x0f;
-                    colors[3] = (pv->buf[i+1])&0x0f;
+                    colors[0] = (buf[i+0]>>4)&0x0f;
+                    colors[1] = (buf[i+0])&0x0f;
+                    colors[2] = (buf[i+1]>>4)&0x0f;
+                    colors[3] = (buf[i+1])&0x0f;
 
                     for( j = 0; j < 4; j++ )
                     {
@@ -267,10 +276,10 @@ static void ParseControls( hb_work_object_t * w )
                      */
                     uint8_t    alpha[4];
 
-                    alpha[3] = (pv->buf[i+0]>>4)&0x0f;
-                    alpha[2] = (pv->buf[i+0])&0x0f;
-                    alpha[1] = (pv->buf[i+1]>>4)&0x0f;
-                    alpha[0] = (pv->buf[i+1])&0x0f;
+                    alpha[3] = (buf[i+0]>>4)&0x0f;
+                    alpha[2] = (buf[i+0])&0x0f;
+                    alpha[1] = (buf[i+1]>>4)&0x0f;
+                    alpha[0] = (buf[i+1])&0x0f;
 
 
                     int lastAlpha = pv->alpha[3] + pv->alpha[2] + pv->alpha[1] + pv->alpha[0];
@@ -296,17 +305,17 @@ static void ParseControls( hb_work_object_t * w )
                 }
                 case 0x05: // 0x05 - SET_DAREA - defines the display area
                 {
-                    pv->x     = (pv->buf[i+0]<<4) | ((pv->buf[i+1]>>4)&0x0f);
-                    pv->width = (((pv->buf[i+1]&0x0f)<<8)| pv->buf[i+2]) - pv->x + 1;
-                    pv->y     = (pv->buf[i+3]<<4)| ((pv->buf[i+4]>>4)&0x0f);
-                    pv->height = (((pv->buf[i+4]&0x0f)<<8)| pv->buf[i+5]) - pv->y + 1;
+                    pv->x     = (buf[i+0]<<4) | ((buf[i+1]>>4)&0x0f);
+                    pv->width = (((buf[i+1]&0x0f)<<8)| buf[i+2]) - pv->x + 1;
+                    pv->y     = (buf[i+3]<<4)| ((buf[i+4]>>4)&0x0f);
+                    pv->height = (((buf[i+4]&0x0f)<<8)| buf[i+5]) - pv->y + 1;
                     i += 6;
                     break;
                 }
                 case 0x06: // 0x06 - SET_DSPXA - defines the pixel data addresses
                 {
-                    pv->offsets[0] = ( pv->buf[i] << 8 ) | pv->buf[i+1]; i += 2;
-                    pv->offsets[1] = ( pv->buf[i] << 8 ) | pv->buf[i+1]; i += 2;
+                    pv->offsets[0] = ( buf[i] << 8 ) | buf[i+1]; i += 2;
+                    pv->offsets[1] = ( buf[i] << 8 ) | buf[i+1]; i += 2;
                     break;
                 }
             }
@@ -475,7 +484,7 @@ static hb_buffer_t * Decode( hb_work_object_t * w )
     /* Get infos about the subtitle */
     ParseControls( w );
 
-    if( job->indepth_scan || ( job->subtitle_force && pv->pts_forced == 0 ) )
+    if( job->indepth_scan || ( w->subtitle->force && pv->pts_forced == 0 ) )
     {
         /*
          * Don't encode subtitles when doing a scan.
@@ -486,11 +495,18 @@ static hb_buffer_t * Decode( hb_work_object_t * w )
         return NULL;
     }
 
+    if (w->subtitle->dest == PASSTHRUSUB)
+    {
+        pv->buf->start  = pv->pts_start;
+        pv->buf->stop   = pv->pts_stop;
+        return pv->buf;
+    }
+
     /* Do the actual decoding now */
     buf_raw = malloc( ( pv->width * pv->height ) * 4 );
 
 #define GET_NEXT_NIBBLE code = ( code << 4 ) | ( ( ( *offset & 1 ) ? \
-( pv->buf[((*offset)>>1)] & 0xF ) : ( pv->buf[((*offset)>>1)] >> 4 ) ) ); \
+( pv->buf->data[((*offset)>>1)] & 0xF ) : ( pv->buf->data[((*offset)>>1)] >> 4 ) ) ); \
 (*offset)++
 
     offsets[0] = pv->offsets[0] * 2;
@@ -547,6 +563,8 @@ static hb_buffer_t * Decode( hb_work_object_t * w )
         }
     }
 
+    hb_buffer_close( &pv->buf );
+
     /* Crop subtitle (remove transparent borders) */
     buf = CropSubtitle( w, buf_raw );
 
diff --git a/libhb/dvdnav.c b/libhb/dvdnav.c
index 5fde4cba7..515de1ee0 100644
--- a/libhb/dvdnav.c
+++ b/libhb/dvdnav.c
@@ -619,11 +619,15 @@ static hb_title_t * hb_dvdnav_title_scan( hb_dvd_t * e, int t )
         lang = lang_for_code( ifo->vtsi_mat->vts_subp_attr[i].lang_code );
 
         subtitle = calloc( sizeof( hb_subtitle_t ), 1 );
+        subtitle->track = i+1;
         subtitle->id = ( ( 0x20 + position ) << 8 ) | 0xbd;
         snprintf( subtitle->lang, sizeof( subtitle->lang ), "%s",
              strlen(lang->native_name) ? lang->native_name : lang->eng_name);
         snprintf( subtitle->iso639_2, sizeof( subtitle->iso639_2 ), "%s",
                   lang->iso639_2);
+        subtitle->format = PICTURESUB;
+        subtitle->source = VOBSUB;
+        subtitle->dest   = RENDERSUB;  // By default render (burn-in) the VOBSUB.
 
         subtitle->type = lang_extension;
 
diff --git a/libhb/encvobsub.c b/libhb/encvobsub.c
index ee49d7ad6..20a9879d6 100644
--- a/libhb/encvobsub.c
+++ b/libhb/encvobsub.c
@@ -26,9 +26,15 @@ int encsubInit( hb_work_object_t * w, hb_job_t * job )
 int encsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
                 hb_buffer_t ** buf_out )
 {
-    hb_work_private_t * pv = w->private_data;
     hb_buffer_t * in = *buf_in;
 
+    if (w->subtitle->source != VOBSUB)
+    {
+        // Invalid source, send EOF, this shouldn't ever happen
+        hb_log("encvobsub: invalid subtitle source");
+        hb_buffer_close( buf_in );
+        *buf_out = hb_buffer_init(0);
+    }
     if ( in->size <= 0 )
     {
         /* EOF on input stream - send it downstream & say that we're done */
@@ -38,10 +44,14 @@ int encsubWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
     }
 
     /*
-     * Don't do anything at present, just pass the buffer on.
+     * Not much to do, just pass the buffer on.
+     * Some day, we may re-encode bd subtitles here ;)
      */
-    *buf_out = in;
-    *buf_in = NULL;
+    if (buf_out)
+    {
+        *buf_out = in;
+        *buf_in = NULL;
+    }
 
     return HB_WORK_OK; 
 }
diff --git a/libhb/fifo.c b/libhb/fifo.c
index c756f5673..7337874bf 100644
--- a/libhb/fifo.c
+++ b/libhb/fifo.c
@@ -191,6 +191,7 @@ void hb_buffer_close( hb_buffer_t ** _b )
     if( buffer_pool && b->data && !hb_fifo_is_full( buffer_pool ) )
     {
         hb_fifo_push_head( buffer_pool, b );
+        *_b = NULL;
         return;
     }
     /* either the pool is full or this size doesn't use a pool - free the buf */
diff --git a/libhb/muxmkv.c b/libhb/muxmkv.c
index c3d627979..04f9ae595 100644
--- a/libhb/muxmkv.c
+++ b/libhb/muxmkv.c
@@ -34,6 +34,27 @@ struct hb_mux_data_s
     int       sub_format;
 };
 
+static int yuv2rgb(int yuv)
+{
+    double y, Cr, Cb;
+    int r, g, b;
+
+    y =  (yuv >> 16) & 0xff;
+    Cr = (yuv >>  8) & 0xff;
+    Cb = (yuv)       & 0xff;
+
+    r = 1.164 * (y - 16)                      + 2.018 * (Cb - 128);
+    g = 1.164 * (y - 16) - 0.813 * (Cr - 128) - 0.391 * (Cb - 128);
+    b = 1.164 * (y - 16) + 1.596 * (Cr - 128);
+    r = (r < 0) ? 0 : r;
+    g = (g < 0) ? 0 : g;
+    b = (b < 0) ? 0 : b;
+    r = (r > 255) ? 255 : r;
+    g = (g > 255) ? 255 : g;
+    b = (b > 255) ? 255 : b;
+    return (r << 16) | (g << 8) | b;
+}
+
 /**********************************************************************
  * MKVInit
  **********************************************************************
@@ -48,7 +69,7 @@ static int MKVInit( hb_mux_object_t * m )
 
     uint8_t         *avcC = NULL;
     uint8_t         default_track_flag = 1;
-    int             avcC_len, i;
+    int             avcC_len, i, j;
     ogg_packet      *ogg_headers[3];
     mk_TrackConfig *track;
 
@@ -261,7 +282,7 @@ static int MKVInit( hb_mux_object_t * m )
     for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
     {
         hb_subtitle_t * subtitle;
-        uint32_t      * palette;
+        uint32_t        rgb[16];
         char            subidx[2048];
         int             len;
 
@@ -270,28 +291,39 @@ static int MKVInit( hb_mux_object_t * m )
             continue;
 
         memset(track, 0, sizeof(mk_TrackConfig));
+        switch (subtitle->format)
+        {
+            case PICTURESUB:
+                track->codecID = MK_SUBTITLE_VOBSUB;
+                for (j = 0; j < 16; j++)
+                    rgb[j] = yuv2rgb(title->palette[j]);
+                len = snprintf(subidx, 2048, subidx_fmt, 
+                        title->width, title->height,
+                        0, 0, "OFF",
+                        rgb[0], rgb[1], rgb[2], rgb[3],
+                        rgb[4], rgb[5], rgb[6], rgb[7],
+                        rgb[8], rgb[9], rgb[10], rgb[11],
+                        rgb[12], rgb[13], rgb[14], rgb[15]);
+                track->codecPrivate = subidx;
+                track->codecPrivateSize = len + 1;
+                break;
+            case TEXTSUB:
+                track->codecID = MK_SUBTITLE_UTF8;
+                break;
+            default:
+                continue;
+        }
 
         mux_data = calloc(1, sizeof( hb_mux_data_t ) );
         subtitle->mux_data = mux_data;
         mux_data->subtitle = 1;
         mux_data->sub_format = subtitle->format;
         
-        palette = title->palette;
-        len = snprintf(subidx, 2048, subidx_fmt, title->width, title->height,
-                 0, 0, "OFF",
-                 palette[0], palette[1], palette[2], palette[3],
-                 palette[4], palette[5], palette[6], palette[7],
-                 palette[8], palette[9], palette[10], palette[11],
-                 palette[12], palette[13], palette[14], palette[15]);
-        track->codecPrivate = subidx;
-        track->codecPrivateSize = len + 1;
-        track->codecID = MK_SUBTITLE_VOBSUB;
         track->flagEnabled = 1;
         track->trackType = MK_TRACK_SUBTITLE;
         track->language = subtitle->iso639_2;
 
         mux_data->track = mk_createTrack(m->file, track);
-
     }
 
     if( mk_writeHeader( m->file, "HandBrake " HB_PROJECT_VERSION) < 0 )
@@ -362,19 +394,33 @@ static int MKVMux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
                 *job->die = 1;
             }
             mk_addFrameData(m->file, mux_data->track, op->packet, op->bytes);
-            mk_setFrameFlags(m->file, mux_data->track, timecode, 1);
+            mk_setFrameFlags(m->file, mux_data->track, timecode, 1, 0);
             return 0;
         }
     }
     else if ( mux_data->subtitle )
     {
         timecode = buf->start * TIMECODE_SCALE;
+        if( mk_startFrame(m->file, mux_data->track) < 0)
+        {
+            hb_error( "Failed to write frame to output file, Disk Full?" );
+            *job->die = 1;
+        }
         if( mux_data->sub_format == TEXTSUB )
         {
-            hb_log("MuxMKV: Text Sub:%lld: %s", buf->start, buf->data);
-            // TODO: add CC data to track
-            return 0;
+            uint64_t   duration;
+
+            duration = buf->stop * TIMECODE_SCALE - timecode;
+            mk_addFrameData(m->file, mux_data->track, buf->data, buf->size);
+            mk_setFrameFlags(m->file, mux_data->track, timecode, 1, duration);
         }
+        else
+        {
+            mk_addFrameData(m->file, mux_data->track, buf->data, buf->size);
+            mk_setFrameFlags(m->file, mux_data->track, timecode, 1, 0);
+        }
+        mk_flushFrame(m->file, mux_data->track);
+        return 0;
     }
     else
     {
@@ -391,7 +437,7 @@ static int MKVMux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
                 *job->die = 1;
             }
             mk_addFrameData(m->file, mux_data->track, op->packet, op->bytes);
-            mk_setFrameFlags(m->file, mux_data->track, timecode, 1);
+            mk_setFrameFlags(m->file, mux_data->track, timecode, 1, 0);
             return 0;
         }
     }
@@ -403,7 +449,10 @@ static int MKVMux( hb_mux_object_t * m, hb_mux_data_t * mux_data,
     }
     mk_addFrameData(m->file, mux_data->track, buf->data, buf->size);
     mk_setFrameFlags(m->file, mux_data->track, timecode,
-                     ((job->vcodec == HB_VCODEC_X264 && mux_data == job->mux_data) ? (buf->frametype == HB_FRAME_IDR) : ((buf->frametype & HB_FRAME_KEY) != 0)) );
+                     ((job->vcodec == HB_VCODEC_X264 && 
+                       mux_data == job->mux_data) ? 
+                            (buf->frametype == HB_FRAME_IDR) : 
+                            ((buf->frametype & HB_FRAME_KEY) != 0)), 0 );
     return 0;
 }
 
diff --git a/libhb/reader.c b/libhb/reader.c
index dd478151b..c865ea85f 100644
--- a/libhb/reader.c
+++ b/libhb/reader.c
@@ -527,7 +527,7 @@ static hb_fifo_t ** GetFifoForId( hb_job_t * job, int id )
         subtitle =  hb_list_item( title->list_subtitle, i );
         if (id == subtitle->id) {
             subtitle->hits++;
-            if( !job->indepth_scan || job->subtitle_force )
+            if( !job->indepth_scan || subtitle->force )
             {
                 /*
                  * Pass the subtitles to be processed if we are not scanning, or if
diff --git a/libhb/sync.c b/libhb/sync.c
index 1001ed50c..d76907987 100644
--- a/libhb/sync.c
+++ b/libhb/sync.c
@@ -485,7 +485,9 @@ static void SyncVideo( hb_work_object_t * w )
                        when the second one starts */
                     sub2 = hb_fifo_see2( subtitle->fifo_raw );
                     if( sub2 && sub->stop > sub2->start )
+                    {
                         sub->stop = sub2->start;
+                    }
                     
                     // hb_log("0x%x: video seq: %lld  subtitle sequence: %lld",
                     //       sub, cur->sequence, sub->sequence);
@@ -508,120 +510,160 @@ static void SyncVideo( hb_work_object_t * w )
                          * and we'll deal with it in the next block of
                          * code.
                          */
-                        break;
-                    }
-                    
-                    /*
-                     * The subtitle is older than this picture, trash it
-                     */
-                    sub = hb_fifo_get( subtitle->fifo_raw );
-                    hb_buffer_close( &sub );
-                }
-                
-                if( sub && sub->size == 0 )
-                {
-                    /* 
-                     * Continue immediately on subtitle EOF
-                     */
-                    break;
-                }
 
-                /*
-                 * There is a valid subtitle, is it time to display it?
-                 */
-                if( sub )
-                {
-                    if( sub->stop > sub->start)
-                    {
                         /*
-                         * Normal subtitle which ends after it starts, check to
-                         * see that the current video is between the start and end.
+                         * There is a valid subtitle, is it time to display it?
                          */
-                        if( cur->start > sub->start &&
-                            cur->start < sub->stop )
+                        if( sub->stop > sub->start)
                         {
                             /*
-                             * We should be playing this, so leave the
-                             * subtitle in place.
-                             *
-                             * fall through to display
+                             * Normal subtitle which ends after it starts, 
+                             * check to see that the current video is between 
+                             * the start and end.
                              */
-                            if( ( sub->stop - sub->start ) < ( 3 * 90000 ) )
+                            if( cur->start > sub->start &&
+                                cur->start < sub->stop )
                             {
                                 /*
-                                 * Subtitle is on for less than three seconds, extend
-                                 * the time that it is displayed to make it easier
-                                 * to read. Make it 3 seconds or until the next
-                                 * subtitle is displayed.
-                                 *
-                                 * This is in response to Indochine which only
-                                 * displays subs for 1 second - too fast to read.
-                                 */
-                                sub->stop = sub->start + ( 3 * 90000 );
+                                * We should be playing this, so leave the
+                                * subtitle in place.
+                                *
+                                * fall through to display
+                                */
+                                if( ( sub->stop - sub->start ) < ( 3 * 90000 ) )
+                                {
+                                    /*
+                                     * Subtitle is on for less than three 
+                                     * seconds, extend the time that it is 
+                                     * displayed to make it easier to read. 
+                                     * Make it 3 seconds or until the next
+                                     * subtitle is displayed.
+                                     *
+                                     * This is in response to Indochine which 
+                                     * only displays subs for 1 second - 
+                                     * too fast to read.
+                                     */
+                                    sub->stop = sub->start + ( 3 * 90000 );
                                 
-                                sub2 = hb_fifo_see2( subtitle->fifo_raw );
+                                    sub2 = hb_fifo_see2( subtitle->fifo_raw );
                                 
-                                if( sub2 && sub->stop > sub2->start )
-                                {
-                                    sub->stop = sub2->start;
+                                    if( sub2 && sub->stop > sub2->start )
+                                    {
+                                        sub->stop = sub2->start;
+                                    }
                                 }
                             }
+                            else
+                            {
+                                /*
+                                 * Defer until the play point is within 
+                                 * the subtitle
+                                 */
+                                sub = NULL;
+                            }
                         }
                         else
                         {
                             /*
-                             * Defer until the play point is within the subtitle
+                             * The end of the subtitle is less than the start, 
+                             * this is a sign of a PTS discontinuity.
                              */
-                            sub = NULL;
+                            if( sub->start > cur->start )
+                            {
+                                /*
+                                 * we haven't reached the start time yet, or
+                                 * we have jumped backwards after having
+                                 * already started this subtitle.
+                                 */
+                                if( cur->start < sub->stop )
+                                {
+                                    /*
+                                     * We have jumped backwards and so should
+                                     * continue displaying this subtitle.
+                                     *
+                                     * fall through to display.
+                                     */
+                                }
+                                else
+                                {
+                                    /*
+                                     * Defer until the play point is 
+                                     * within the subtitle
+                                     */
+                                    sub = NULL;
+                                }
+                            } else {
+                                /*
+                                * Play this subtitle as the start is 
+                                * greater than our video point.
+                                *
+                                * fall through to display/
+                                */
+                            }
                         }
+                    	break;
                     }
                     else
                     {
+                    
                         /*
-                         * The end of the subtitle is less than the start, this is a
-                         * sign of a PTS discontinuity.
+                         * The subtitle is older than this picture, trash it
                          */
-                        if( sub->start > cur->start )
+                        sub = hb_fifo_get( subtitle->fifo_raw );
+                        hb_buffer_close( &sub );
+                    }
+                }
+                
+                /* If we have a subtitle for this picture, copy it */
+                /* FIXME: we should avoid this memcpy */
+                if( sub )
+                {
+                    if( sub->size > 0 )
+                    {
+                        if( subtitle->dest == RENDERSUB )
                         {
-                            /*
-                             * we haven't reached the start time yet, or
-                             * we have jumped backwards after having
-                             * already started this subtitle.
-                             */
-                            if( cur->start < sub->stop )
-                            {
-                                /*
-                                 * We have jumped backwards and so should
-                                 * continue displaying this subtitle.
-                                 *
-                                 * fall through to display.
-                                 */
-                            }
-                            else
+                            if ( cur->sub == NULL )
                             {
                                 /*
-                                 * Defer until the play point is within the subtitle
+                                 * Tack onto the video buffer for rendering
                                  */
-                                sub = NULL;
+                                cur->sub         = hb_buffer_init( sub->size );
+                                cur->sub->x      = sub->x;
+                                cur->sub->y      = sub->y;
+                                cur->sub->width  = sub->width;
+                                cur->sub->height = sub->height;
+                                memcpy( cur->sub->data, sub->data, sub->size ); 
                             }
                         } else {
                             /*
-                             * Play this subtitle as the start is greater than our
-                             * video point.
-                             *
-                             * fall through to display/
+                             * Pass-Through, pop it off of the raw queue, 
+                             * rewrite times and make it available to be 
+                             * reencoded.
                              */
+                            uint64_t sub_duration;
+                            sub = hb_fifo_get( subtitle->fifo_raw );
+                            sub_duration = sub->stop - sub->start;
+                            sub->start = cur->start;
+                            buf_tmp = hb_fifo_see( job->fifo_raw );
+                            int64_t duration = buf_tmp->start - cur->start;
+                            sub->stop = sub->start + duration;
+                            hb_fifo_push( subtitle->fifo_sync, sub );
+                        }
+                    } else {
+                        /*
+                        * EOF - consume for rendered, else pass through
+                        */
+                        if( subtitle->dest == RENDERSUB )
+                        {
+                            sub = hb_fifo_get( subtitle->fifo_raw );
+                            hb_buffer_close( &sub );
+                        } else {
+                            sub = hb_fifo_get( subtitle->fifo_raw );
+                            hb_fifo_push( subtitle->fifo_out, sub );
                         }
                     }
                 }
             }
-            if( sub )
-            {
-                /*
-                 * Got a sub to display...
-                 */
-                break;
-            }
         } // end subtitles
 
         /*
@@ -639,6 +681,7 @@ static void SyncVideo( hb_work_object_t * w )
          */
         buf_tmp = cur;
         pv->cur = cur = hb_fifo_get( job->fifo_raw );
+        cur->sub = NULL;
         pv->next_pts = cur->start;
         int64_t duration = cur->start - buf_tmp->start;
         if ( duration <= 0 )
@@ -659,51 +702,6 @@ static void SyncVideo( hb_work_object_t * w )
             pv->chap_mark = 0;
         }
 
-        /* If we have a subtitle for this picture, copy it */
-        /* FIXME: we should avoid this memcpy */
-        if( sub && subtitle && 
-            subtitle->format == PICTURESUB )
-        {
-            if( sub->size > 0 )
-            {
-                if( subtitle->dest == RENDERSUB )
-                {
-                    /*
-                     * Tack onto the video buffer for rendering
-                     */
-                    buf_tmp->sub         = hb_buffer_init( sub->size );
-                    buf_tmp->sub->x      = sub->x;
-                    buf_tmp->sub->y      = sub->y;
-                    buf_tmp->sub->width  = sub->width;
-                    buf_tmp->sub->height = sub->height;
-                    memcpy( buf_tmp->sub->data, sub->data, sub->size ); 
-                } else {
-                    /*
-                     * Pass-Through, pop it off of the raw queue, rewrite times and
-                     * make it available to be reencoded.
-                     */
-                    uint64_t sub_duration;
-                    sub = hb_fifo_get( subtitle->fifo_raw );
-                    sub_duration = sub->stop - sub->start;
-                    sub->start = buf_tmp->start;
-                    sub->stop = sub->start + duration;
-                    hb_fifo_push( subtitle->fifo_sync, sub );
-                }
-            } else {
-                /*
-                 * EOF - consume for rendered, else pass through
-                 */
-                if( subtitle->dest == RENDERSUB )
-                {
-                    sub = hb_fifo_get( subtitle->fifo_raw );
-                    hb_buffer_close( &sub );
-                } else {
-                    sub = hb_fifo_get( subtitle->fifo_raw );
-                    hb_fifo_push( subtitle->fifo_out, sub );
-                }
-            }
-        }
-
         /* Push the frame to the renderer */
         hb_fifo_push( job->fifo_sync, buf_tmp );
 
diff --git a/libhb/work.c b/libhb/work.c
index 7b270ca70..59dea5dfe 100644
--- a/libhb/work.c
+++ b/libhb/work.c
@@ -501,16 +501,16 @@ static void do_job( hb_job_t * job, int cpu_count )
              *
              * select_subtitle implies that we did a scan.
              */
-            if( !job->indepth_scan && job->subtitle_force &&
+            if( !job->indepth_scan && subtitle->force &&
                 job->select_subtitle )
             {
                 if( subtitle->forced_hits == 0 )
                 {
-                    job->subtitle_force = 0;
+                    subtitle->force = 0;
                 }
             }
 
-            if( (!job->indepth_scan || job->subtitle_force) && 
+            if( (!job->indepth_scan || subtitle->force) && 
                 subtitle->source == VOBSUB ) {
                 /*
                  * Don't add threads for subtitles when we are scanning, unless
@@ -519,6 +519,7 @@ static void do_job( hb_job_t * job, int cpu_count )
                 w = hb_get_work( WORK_DECVOBSUB );
                 w->fifo_in  = subtitle->fifo_in;
                 w->fifo_out = subtitle->fifo_raw;
+                w->subtitle = subtitle;
                 hb_list_add( job->list_work, w );
             }
 
@@ -541,6 +542,7 @@ static void do_job( hb_job_t * job, int cpu_count )
                 w = hb_get_work( WORK_ENCVOBSUB );
                 w->fifo_in  = subtitle->fifo_sync;
                 w->fifo_out = subtitle->fifo_out;
+                w->subtitle = subtitle;
                 hb_list_add( job->list_work, w );
             }
         }
-- 
cgit v1.2.3