OSDN Git Service

LinGui: make Help->Guide work on windows/mingw
[handbrake-jp/handbrake-jp-git.git] / libhb / stream.c
index 4b1bd98..24093e6 100644 (file)
@@ -2831,6 +2831,128 @@ static void add_ffmpeg_audio( hb_title_t *title, hb_stream_t *stream, int id )
     }
 }
 
+/*
+ * Format:
+ *   MkvVobSubtitlePrivateData = ( Line )*
+ *   Line = FieldName ':' ' ' FieldValue '\n'
+ *   FieldName = [^:]+
+ *   FieldValue = [^\n]+
+ * 
+ * The line of interest is:
+ *   PaletteLine = "palette" ':' ' ' RRGGBB ( ',' ' ' RRGGBB )*
+ * 
+ * More information on the format at:
+ *   http://www.matroska.org/technical/specs/subtitles/images.html
+ */
+static int ffmpeg_parse_vobsub_extradata_mkv( AVCodecContext *codec, hb_subtitle_t *subtitle )
+{
+    // lines = (string) codec->extradata;
+    char *lines = malloc( codec->extradata_size + 1 );
+    if ( lines == NULL )
+        return 1;
+    memcpy( lines, codec->extradata, codec->extradata_size );
+    lines[codec->extradata_size] = '\0';
+    
+    uint32_t rgb[16];
+    int gotPalette = 0;
+    int gotDimensions = 0;
+    
+    char *curLine, *curLine_parserData;
+    for ( curLine = strtok_r( lines, "\n", &curLine_parserData );
+          curLine;
+          curLine = strtok_r( NULL, "\n", &curLine_parserData ) )
+    {
+        if (!gotPalette)
+        {
+            int numElementsRead = sscanf(curLine, "palette: "
+                "%06x, %06x, %06x, %06x, "
+                "%06x, %06x, %06x, %06x, "
+                "%06x, %06x, %06x, %06x, "
+                "%06x, %06x, %06x, %06x",
+                &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]);
+
+            if (numElementsRead == 16) {
+                gotPalette = 1;
+            }
+        }
+        if (!gotDimensions)
+        {
+            int numElementsRead = sscanf(curLine, "size: %dx%d",
+                &subtitle->width, &subtitle->height);
+
+            if (numElementsRead == 2) {
+                gotDimensions = 1;
+            }
+        }
+        if (gotPalette && gotDimensions)
+            break;
+    }
+
+    if (subtitle->width == 0 || subtitle->height == 0)
+    {
+        subtitle->width = 720;
+        subtitle->height = 480;
+    }
+    
+    free( lines );
+    
+    if ( gotPalette )
+    {
+        int i;
+        for (i=0; i<16; i++)
+            subtitle->palette[i] = hb_rgb2yuv(rgb[i]);
+        return 0;
+    }
+    else
+    {
+        return 1;
+    }
+}
+
+/*
+ * Format: 8-bit {0,Y,Cb,Cr} x 16
+ */
+static int ffmpeg_parse_vobsub_extradata_mp4( AVCodecContext *codec, hb_subtitle_t *subtitle )
+{
+    if ( codec->extradata_size != 4*16 )
+        return 1;
+    
+    int i, j;
+    for ( i=0, j=0; i<16; i++, j+=4 )
+    {
+        subtitle->palette[i] = 
+            codec->extradata[j+1] << 16 |   // Y
+            codec->extradata[j+2] << 8  |   // Cb
+            codec->extradata[j+3] << 0;     // Cr
+    }
+    if (codec->width <= 0 || codec->height <= 0)
+    {
+        subtitle->width = 720;
+        subtitle->height = 480;
+    }
+    else
+    {
+        subtitle->width = codec->width;
+        subtitle->height = codec->height;
+    }
+    return 0;
+}
+
+/*
+ * Parses the 'subtitle->palette' information from the specific VOB subtitle track's private data.
+ * Returns 0 if successful or 1 if parsing failed or was incomplete.
+ */
+static int ffmpeg_parse_vobsub_extradata( AVCodecContext *codec, hb_subtitle_t *subtitle )
+{
+    // XXX: Better if we actually chose the correct parser based on the input container
+    return
+        ffmpeg_parse_vobsub_extradata_mkv( codec, subtitle ) &&
+        ffmpeg_parse_vobsub_extradata_mp4( codec, subtitle );
+}
+
 static void add_ffmpeg_subtitle( hb_title_t *title, hb_stream_t *stream, int id )
 {
     AVStream *st = stream->ffmpeg_ic->streams[id];
@@ -2842,14 +2964,14 @@ static void add_ffmpeg_subtitle( hb_title_t *title, hb_stream_t *stream, int id
     
     switch ( codec->codec_id )
     {
-        // TODO(davidfstr): get universal VOB sub input working
-        /*
         case CODEC_ID_DVD_SUBTITLE:
             subtitle->format = PICTURESUB;
             subtitle->source = VOBSUB;
             subtitle->config.dest = RENDERSUB;  // By default render (burn-in) the VOBSUB.
+            if ( ffmpeg_parse_vobsub_extradata( codec, subtitle ) )
+                hb_log( "add_ffmpeg_subtitle: malformed extradata for VOB subtitle track; "
+                        "subtitle colors likely to be wrong" );
             break;
-        */
         case CODEC_ID_TEXT:
             subtitle->format = TEXTSUB;
             subtitle->source = UTF8SUB;
@@ -2860,16 +2982,13 @@ static void add_ffmpeg_subtitle( hb_title_t *title, hb_stream_t *stream, int id
             subtitle->source = TX3GSUB;
             subtitle->config.dest = PASSTHRUSUB;
             break;
-        // TODO(davidfstr): implement SSA subtitle support
-        /*
         case CODEC_ID_SSA:
             subtitle->format = TEXTSUB;
             subtitle->source = SSASUB;
             subtitle->config.dest = PASSTHRUSUB;
             break;
-        */
         default:
-            hb_log("add_ffmpeg_subtitle: unknown subtitle stream type: 0x%x", (int) codec->codec_id);
+            hb_log( "add_ffmpeg_subtitle: unknown subtitle stream type: 0x%x", (int) codec->codec_id );
             free(subtitle);
             return;
     }
@@ -3132,10 +3251,18 @@ static int ffmpeg_read( hb_stream_t *stream, hb_buffer_t *buf )
     /* 
      * Fill out buf->stop for subtitle packets
      * 
-     * libavcodec's MKV demuxer stores the duration of UTF-8 (TEXT) subtitles
+     * libavcodec's MKV demuxer stores the duration of UTF-8 subtitles (CODEC_ID_TEXT)
      * in the 'convergence_duration' field for some reason.
      * 
      * Other subtitles' durations are stored in the 'duration' field.
+     * 
+     * VOB subtitles (CODEC_ID_DVD_SUBTITLE) do not have their duration stored in
+     * either field. This is not a problem because the VOB decoder can extract this
+     * information from the packet payload itself.
+     * 
+     * SSA subtitles (CODEC_ID_SSA) do not have their duration stored in
+     * either field. This is not a problem because the SSA decoder can extract this
+     * information from the packet payload itself.
      */
     enum CodecID ffmpeg_pkt_codec = stream->ffmpeg_ic->streams[stream->ffmpeg_pkt->stream_index]->codec->codec_id;
     if ( ffmpeg_pkt_codec == CODEC_ID_TEXT ) {