[FFmpeg-devel] [PATCH] Add support for parsing the Display Definition Segment in dvbsubdec.c

Janne Grunau janne-ffmpeg
Thu May 6 01:11:58 CEST 2010


On Fri, Apr 23, 2010 at 03:41:09PM +0200, Michael Niedermayer wrote:
> On Fri, Apr 23, 2010 at 09:05:03AM +0100, Ian Caulfield wrote:
> > On 23 April 2010 05:05, Mark Kendall <mark.kendall at gmail.com> wrote:
> > > The attached patch parses the Display Definition Segment in DVB
> > > subtitle packets (see EN 300 743 V1.3.1).
> > >
> > > The Display Definition Segment explicitly indicates to the decoder the
> > > display size for which the subtitles were generated, allowing standard
> > > definition subtitles to be displayed on high definition streams.
> > >
> > > This extends AVSubtitleRect to hold the new display information and,
> > > if a Display Definition Segment is not seen, defaults to 720x576 (per
> > > the standard).
> > 
> > Would it be more appropriate to fill in the width and height fields of
> > AVCodecContext?
> 
> agree, 
> with documentation added to width/height and where the x/y position is
> documented

modified patch attached. Also moved display_x/y to AVSubtitle since it's
at least in the case of dvb subtitles for all rects identical. If we
expect it to change per rect we can't store the size in AVCodecContext.
Also bumped minor version, removed whitespace only changes and fixed
off-by-one errors in the width/height calculation.

Janne

-------------- next part --------------
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index b643747..0abd53f 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -30,7 +30,7 @@
 #include "libavutil/avutil.h"
 
 #define LIBAVCODEC_VERSION_MAJOR 52
-#define LIBAVCODEC_VERSION_MINOR 66
+#define LIBAVCODEC_VERSION_MINOR 67
 #define LIBAVCODEC_VERSION_MICRO  0
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
@@ -1097,6 +1097,9 @@ typedef struct AVCodecContext {
      * picture width / height.
      * - encoding: MUST be set by user.
      * - decoding: Set by libavcodec.
+     * If set for subtitles width / height of the display region. The top
+     * left corner of the display region is specified in AVSubtitle as
+     * display_x, display_y.
      * Note: For compatibility it is possible to set this instead of
      * coded_width/height before decoding.
      */
@@ -2863,6 +2866,11 @@ typedef struct AVSubtitle {
     unsigned num_rects;
     AVSubtitleRect **rects;
     int64_t pts;    ///< Same as packet pts, in AV_TIME_BASE
+    /**
+     * top left corner of region into which rects are displayed.
+     * display width and height are in AVCodecContext
+     */
+    int display_x, display_y;
 } AVSubtitle;
 
 /* packet functions */
diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c
index 54c74b5..9c46621 100644
--- a/libavcodec/dvbsubdec.c
+++ b/libavcodec/dvbsubdec.c
@@ -22,6 +22,7 @@
 #include "dsputil.h"
 #include "get_bits.h"
 #include "colorspace.h"
+#include "bytestream.h"
 
 //#define DEBUG
 //#define DEBUG_PACKET_CONTENTS
@@ -31,6 +32,7 @@
 #define DVBSUB_REGION_SEGMENT   0x11
 #define DVBSUB_CLUT_SEGMENT     0x12
 #define DVBSUB_OBJECT_SEGMENT   0x13
+#define DVBSUB_DISPLAYDEFINITION_SEGMENT 0x14
 #define DVBSUB_DISPLAY_SEGMENT  0x80
 
 #define cm (ff_cropTbl + MAX_NEG_CROP)
@@ -216,6 +218,15 @@ typedef struct DVBSubRegion {
     struct DVBSubRegion *next;
 } DVBSubRegion;
 
+typedef struct DVBSubDisplayDefinition {
+    int version;
+
+    int x;
+    int y;
+    int width;
+    int height;
+} DVBSubDisplayDefinition;
+
 typedef struct DVBSubContext {
     int composition_id;
     int ancillary_id;
@@ -227,6 +238,7 @@ typedef struct DVBSubContext {
 
     int display_list_size;
     DVBSubRegionDisplay *display_list;
+    DVBSubDisplayDefinition *display_definition;
 } DVBSubContext;
 
 
@@ -334,6 +346,9 @@ static void delete_state(DVBSubContext *ctx)
         av_free(clut);
     }
 
+    if (ctx->display_definition)
+        av_free(ctx->display_definition);
+
     /* Should already be null */
     if (ctx->object_list)
         av_log(0, AV_LOG_ERROR, "Memory deallocation error!\n");
@@ -1254,10 +1269,49 @@ static void save_display_set(DVBSubContext *ctx)
 }
 #endif
 
+static void dvbsub_parse_display_definition_segment(AVCodecContext *avctx,
+                                                    const uint8_t *buf,
+                                                    int buf_size)
+{
+    DVBSubContext *ctx = (DVBSubContext*) avctx->priv_data;
+    DVBSubDisplayDefinition *display_def = ctx->display_definition;
+    int dds_version, info_byte;
+
+    if (buf_size < 5)
+        return;
+
+    info_byte   = bytestream_get_byte(&buf);
+    dds_version = (info_byte >> 4) & 0xF;
+    if (display_def && (display_def->version == dds_version))
+        return; // already have this display definition version
+
+    if (!display_def) {
+        ctx->display_definition = av_mallocz(sizeof(DVBSubDisplayDefinition));
+        display_def = ctx->display_definition;
+    }
+
+    display_def->version = dds_version;
+    display_def->x       = 0;
+    display_def->y       = 0;
+    display_def->width   = bytestream_get_be16(&buf) + 1;
+    display_def->height  = bytestream_get_be16(&buf) + 1;
+
+    if (buf_size < 13)
+        return;
+
+    if ((info_byte >> 3) & 1) { // display_window_flag
+        display_def->x = bytestream_get_be16(&buf);
+        display_def->y = bytestream_get_be16(&buf);
+        display_def->width  = bytestream_get_be16(&buf) - display_def->x + 1;
+        display_def->height = bytestream_get_be16(&buf) - display_def->y + 1;
+    }
+}
+
 static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf,
                                         int buf_size, AVSubtitle *sub)
 {
     DVBSubContext *ctx = (DVBSubContext*) avctx->priv_data;
+    DVBSubDisplayDefinition *display_def = ctx->display_definition;
 
     DVBSubRegion *region;
     DVBSubRegionDisplay *display;
@@ -1271,6 +1325,14 @@ static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf,
     sub->end_display_time = ctx->time_out * 1000;
     sub->format = 0;
 
+
+    if (display_def) {
+        sub->display_x = display_def->x;
+        sub->display_y = display_def->y;
+        avctx->width    = display_def->width;
+        avctx->height   = display_def->height;
+    }
+
     sub->num_rects = ctx->display_list_size;
 
     if (sub->num_rects > 0){
@@ -1389,6 +1451,8 @@ static int dvbsub_decode(AVCodecContext *avctx,
             case DVBSUB_OBJECT_SEGMENT:
                 dvbsub_parse_object_segment(avctx, p, segment_length);
                 break;
+            case DVBSUB_DISPLAYDEFINITION_SEGMENT:
+                dvbsub_parse_display_definition_segment(avctx, p, segment_length);
             case DVBSUB_DISPLAY_SEGMENT:
                 *data_size = dvbsub_display_end_segment(avctx, p, segment_length, sub);
                 break;



More information about the ffmpeg-devel mailing list