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

Janne Grunau janne-ffmpeg
Fri May 21 01:50:15 CEST 2010


On Thu, May 20, 2010 at 10:20:22PM +0200, Michael Niedermayer wrote:
> 
> i see no case in which a hierachical system with an additional rectangle
> that contanins the other rectangles would make sense.
> thats besides that whatever is done the API must be unambigously and clearly
> be described. that is the interaction/relation of all the values and their
> scale must be documented.
> anyway, please elaborate on what problem you see

The only (minor) problem I see is that recalculating the subtitle rect's
x/y position makes scaling them up to the full display size harder.
As far as I understand the only purpose of this part of the DVB subtitle
standard is to center SD subtitles reused for HD streams.
So it's valid concern but probably not important enough to clutter the
API.

Attached patch doesn't change API and changes only x/y values.

Janne
-------------- next part --------------
diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c
index 54c74b5..210aa63 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;
@@ -1265,12 +1319,18 @@ static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf,
     DVBSubCLUT *clut;
     uint32_t *clut_table;
     int i;
+    int offset_x=0, offset_y=0;
 
     sub->rects = NULL;
     sub->start_display_time = 0;
     sub->end_display_time = ctx->time_out * 1000;
     sub->format = 0;
 
+    if (display_def) {
+        offset_x = display_def->x;
+        offset_y = display_def->y;
+    }
+
     sub->num_rects = ctx->display_list_size;
 
     if (sub->num_rects > 0){
@@ -1288,8 +1348,8 @@ static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf,
         if (!region)
             continue;
 
-        rect->x = display->x_pos;
-        rect->y = display->y_pos;
+        rect->x = display->x_pos + offset_x;
+        rect->y = display->y_pos + offset_y;
         rect->w = region->width;
         rect->h = region->height;
         rect->nb_colors = 16;
@@ -1389,6 +1449,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