[vlc-devel] [PATCH] vobsub idx parsing in matroska track's CodecPrivate data added capability to avformat and mkv demuxers extract the original_frame_width, original_frame_height and palette from the tracks CodecPrivate data which libavformat supplies in AVCodecContext.extradata. Vobsubs in mkv were only using default values for these items.

John Stebbins john at stebbins.name
Thu May 14 02:08:36 CEST 2009


---
 modules/demux/avformat/demux.c         |   43 +++++++++++++++++++
 modules/demux/mkv/matroska_segment.cpp |   51 ++++++++++++++++------
 modules/demux/vobsub.c                 |   32 ++------------
 modules/demux/vobsub.h                 |   71 ++++++++++++++++++++++++++++++++
 4 files changed, 155 insertions(+), 42 deletions(-)
 create mode 100644 modules/demux/vobsub.h

diff --git a/modules/demux/avformat/demux.c b/modules/demux/avformat/demux.c
index dd0f7c9..0edb8a9 100644
--- a/modules/demux/avformat/demux.c
+++ b/modules/demux/avformat/demux.c
@@ -47,6 +47,7 @@
 
 #include "../../codec/avcodec/avcodec.h"
 #include "avformat.h"
+#include "../vobsub.h"
 
 //#define AVFORMAT_DEBUG 1
 
@@ -271,6 +272,48 @@ int OpenDemux( vlc_object_t *p_this )
 
         case CODEC_TYPE_SUBTITLE:
             es_format_Init( &fmt, SPU_ES, fcc );
+            if( strncmp( p_sys->ic->iformat->name, "matroska", 8 ) == 0 &&
+                cc->codec_id == CODEC_ID_DVD_SUBTITLE &&
+                cc->extradata != NULL &&
+                cc->extradata_size > 0 )
+            {
+                char *psz_start;
+                char *psz_buf = malloc( cc->extradata_size + 1);
+                if( psz_buf != NULL )
+                {
+                    memcpy( psz_buf, cc->extradata , cc->extradata_size );
+                    psz_buf[cc->extradata_size] = '\0';
+
+                    psz_start = strstr( psz_buf, "size:" );
+                    if( psz_start && 
+                        vobsub_size_parse( psz_start, 
+                                           &fmt.subs.spu.i_original_frame_width,
+                                           &fmt.subs.spu.i_original_frame_height ) == VLC_SUCCESS )
+                    {
+                        msg_Dbg( p_demux, "original frame size: %dx%d", 
+                                 fmt.subs.spu.i_original_frame_width, 
+                                 fmt.subs.spu.i_original_frame_height );
+                    }
+                    else
+                    {
+                        msg_Warn( p_demux, "reading original frame size failed" );
+                    }
+
+                    psz_start = strstr( psz_buf, "palette:" );
+                    if( psz_start && 
+                        vobsub_palette_parse( psz_start, &fmt.subs.spu.palette[1] ) == VLC_SUCCESS )
+                    {
+                        fmt.subs.spu.palette[0] =  0xBeef; 
+                        msg_Dbg( p_demux, "vobsub palette read" );
+                    }
+                    else
+                    {
+                        msg_Warn( p_demux, "reading original palette failed" );
+                    }
+                    free( psz_buf );
+                }
+            }
+
             psz_type = "subtitle";
             break;
 
diff --git a/modules/demux/mkv/matroska_segment.cpp b/modules/demux/mkv/matroska_segment.cpp
index 26d43b4..7dd11d5 100644
--- a/modules/demux/mkv/matroska_segment.cpp
+++ b/modules/demux/mkv/matroska_segment.cpp
@@ -28,6 +28,10 @@
 
 #include "demux.hpp"
 
+extern "C" {
+#include "../vobsub.h"
+}
+
 /* GetFourCC helper */
 #define GetFOURCC( p )  __GetFOURCC( (uint8_t*)p )
 static vlc_fourcc_t __GetFOURCC( uint8_t *p )
@@ -1095,22 +1099,41 @@ bool matroska_segment_c::Select( mtime_t i_start_time )
             tracks[i_track]->fmt.i_codec = VLC_FOURCC( 's','p','u',' ' );
             if( tracks[i_track]->i_extra_data )
             {
-                char *p_start;
-                char *p_buf = (char *)malloc( tracks[i_track]->i_extra_data + 1);
-                memcpy( p_buf, tracks[i_track]->p_extra_data , tracks[i_track]->i_extra_data );
-                p_buf[tracks[i_track]->i_extra_data] = '\0';
- 
-                p_start = strstr( p_buf, "size:" );
-                if( sscanf( p_start, "size: %dx%d",
-                        &tracks[i_track]->fmt.subs.spu.i_original_frame_width, &tracks[i_track]->fmt.subs.spu.i_original_frame_height ) == 2 )
+                char *psz_start;
+                char *psz_buf = (char *)malloc( tracks[i_track]->i_extra_data + 1);
+                if( psz_buf != NULL )
                 {
-                    msg_Dbg( &sys.demuxer, "original frame size vobsubs: %dx%d", tracks[i_track]->fmt.subs.spu.i_original_frame_width, tracks[i_track]->fmt.subs.spu.i_original_frame_height );
-                }
-                else
-                {
-                    msg_Warn( &sys.demuxer, "reading original frame size for vobsub failed" );
+                    memcpy( psz_buf, tracks[i_track]->p_extra_data , tracks[i_track]->i_extra_data );
+                    psz_buf[tracks[i_track]->i_extra_data] = '\0';
+ 
+                    psz_start = strstr( psz_buf, "size:" );
+                    if( psz_start && 
+                        vobsub_size_parse( psz_start, 
+                                           &tracks[i_track]->fmt.subs.spu.i_original_frame_width,
+                                           &tracks[i_track]->fmt.subs.spu.i_original_frame_height ) == VLC_SUCCESS )
+                    {
+                        msg_Dbg( &sys.demuxer, "original frame size vobsubs: %dx%d", 
+                                 tracks[i_track]->fmt.subs.spu.i_original_frame_width, 
+                                 tracks[i_track]->fmt.subs.spu.i_original_frame_height );
+                    }
+                    else
+                    {
+                        msg_Warn( &sys.demuxer, "reading original frame size for vobsub failed" );
+                    }
+
+                    psz_start = strstr( psz_buf, "palette:" );
+                    if( psz_start && 
+                        vobsub_palette_parse( psz_start, &tracks[i_track]->fmt.subs.spu.palette[1] ) == VLC_SUCCESS )
+                    {
+                        tracks[i_track]->fmt.subs.spu.palette[0] =  0xBeef;
+                        msg_Dbg( &sys.demuxer, "vobsub palette read" );
+                    }
+                    else
+                    {
+                        msg_Warn( &sys.demuxer, "reading original palette failed" );
+                    }
+                    free( psz_buf );
                 }
-                free( p_buf );
             }
         }
         else if( !strcmp( tracks[i_track]->psz_codec, "B_VOBBTN" ) )
diff --git a/modules/demux/vobsub.c b/modules/demux/vobsub.c
index 3b90e2d..aba7d3b 100644
--- a/modules/demux/vobsub.c
+++ b/modules/demux/vobsub.c
@@ -40,6 +40,7 @@
 #include <vlc_charset.h>
 
 #include "ps.h"
+#include "vobsub.h"
 
 #define MAX_LINE 8192
 
@@ -488,8 +489,8 @@ static int ParseVobSubIDX( demux_t *p_demux )
         else if( !strncmp( "size:", line, 5 ) )
         {
             /* Store the original size of the video */
-            if( sscanf( line, "size: %dx%d",
-                        &p_sys->i_original_frame_width, &p_sys->i_original_frame_height ) == 2 )
+            if( vobsub_size_parse( line, &p_sys->i_original_frame_width,
+                                   &p_sys->i_original_frame_height ) == VLC_SUCCESS )
             {
                 msg_Dbg( p_demux, "original frame size: %dx%d", p_sys->i_original_frame_width, p_sys->i_original_frame_height );
             }
@@ -500,33 +501,8 @@ static int ParseVobSubIDX( demux_t *p_demux )
         }
         else if( !strncmp( "palette:", line, 8 ) )
         {
-            int i;
-
-            /* Store the palette of the subs */
-            if( sscanf( line, "palette: %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x",
-                        &p_sys->palette[0], &p_sys->palette[1], &p_sys->palette[2], &p_sys->palette[3],
-                        &p_sys->palette[4], &p_sys->palette[5], &p_sys->palette[6], &p_sys->palette[7],
-                        &p_sys->palette[8], &p_sys->palette[9], &p_sys->palette[10], &p_sys->palette[11],
-                        &p_sys->palette[12], &p_sys->palette[13], &p_sys->palette[14], &p_sys->palette[15] ) == 16 )
+            if( vobsub_palette_parse( line, p_sys->palette ) == VLC_SUCCESS )
             {
-                for( i = 0; i < 16; i++ )
-                {
-                    uint8_t r = 0, g = 0, b = 0;
-                    uint8_t y = 0, u = 0, v = 0;
-                    r = (p_sys->palette[i] >> 16) & 0xff;
-                    g = (p_sys->palette[i] >> 8) & 0xff;
-                    b = (p_sys->palette[i] >> 0) & 0xff;
-                    /* msg_Dbg( p_demux, "palette %d: R=%x, G=%x, B=%x", i, r, g, b ); */
-                    y = (uint8_t) __MIN(abs(r * 2104 + g * 4130 + b * 802 + 4096 + 131072) >> 13, 235);
-                    u = (uint8_t) __MIN(abs(r * -1214 + g * -2384 + b * 3598 + 4096 + 1048576) >> 13, 240);
-                    v = (uint8_t) __MIN(abs(r * 3598 + g * -3013 + b * -585 + 4096 + 1048576) >> 13, 240);
-                    p_sys->palette[i] = 0;
-                    p_sys->palette[i] |= (y&0xff)<<16;
-                    p_sys->palette[i] |= (u&0xff);
-                    p_sys->palette[i] |= (v&0xff)<<8;
-                    /* msg_Dbg( p_demux, "palette %d: y=%x, u=%x, v=%x", i, y, u, v ); */
-
-                }
                 p_sys->b_palette = true;
                 msg_Dbg( p_demux, "vobsub palette read" );
             }
diff --git a/modules/demux/vobsub.h b/modules/demux/vobsub.h
new file mode 100644
index 0000000..c5faee1
--- /dev/null
+++ b/modules/demux/vobsub.h
@@ -0,0 +1,71 @@
+/*****************************************************************************
+ * vobsub.h: Vobsub support
+ *****************************************************************************
+ * Copyright (C) 2008 the VideoLAN team
+ * $Id$
+ *
+ * Authors: John Stebbins
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+static inline void vobsub_palette_rgb2yuv( uint32_t *pu_palette )
+{
+    int i;
+    for( i = 0; i < 16; i++ )
+    {
+        uint8_t r, g, b, y, u, v;
+        r = (pu_palette[i] >> 16) & 0xff;
+        g = (pu_palette[i] >> 8) & 0xff;
+        b = (pu_palette[i] >> 0) & 0xff;
+        y = (uint8_t) __MIN(abs(r * 2104 + g * 4130 + b * 802 + 4096 + 131072) >> 13, 235);
+        u = (uint8_t) __MIN(abs(r * -1214 + g * -2384 + b * 3598 + 4096 + 1048576) >> 13, 240);
+        v = (uint8_t) __MIN(abs(r * 3598 + g * -3013 + b * -585 + 4096 + 1048576) >> 13, 240);
+        pu_palette[i] = (y&0xff)<<16 | (v&0xff)<<8 | (u&0xff);
+    }
+}
+
+static inline int vobsub_palette_parse( const char *psz_buf, uint32_t *pu_palette )
+{
+    if( sscanf( psz_buf, "palette: "
+                "%"PRIx32", %"PRIx32", %"PRIx32", %"PRIx32", %"PRIx32", %"PRIx32", %"PRIx32", %"PRIx32", "
+                "%"PRIx32", %"PRIx32", %"PRIx32", %"PRIx32", %"PRIx32", %"PRIx32", %"PRIx32", %"PRIx32"",
+                &pu_palette[0], &pu_palette[1], &pu_palette[2], &pu_palette[3],
+                &pu_palette[4], &pu_palette[5], &pu_palette[6], &pu_palette[7],
+                &pu_palette[8], &pu_palette[9], &pu_palette[10], &pu_palette[11],
+                &pu_palette[12], &pu_palette[13], &pu_palette[14], &pu_palette[15] ) == 16 )
+    {
+        vobsub_palette_rgb2yuv( pu_palette );
+        return VLC_SUCCESS;
+    }
+    else
+    {
+        return VLC_EGENERIC;
+    }
+}
+
+static inline int vobsub_size_parse( const char *psz_buf, int *pi_original_frame_width, int *pi_original_frame_height )
+{
+    if( sscanf( psz_buf, "size: %dx%d",
+                pi_original_frame_width, pi_original_frame_height ) == 2 )
+    {
+        return VLC_SUCCESS;
+    }
+    else
+    {
+        return VLC_EGENERIC;
+    }
+}
+
-- 
1.6.2.2




More information about the vlc-devel mailing list