# HG changeset patch # User janne # Date 1276693632 0 # Node ID c591e96c03ab824073c5d053f28ab9849785495c # Parent 8daf3134622c997c6e528d9d192a916541ef425f dvbsub: parse display definition segment The display definition segment is used to properly display SD DVB subtitles in HD video streams. diff -r 8daf3134622c -r c591e96c03ab dvbsubdec.c --- a/dvbsubdec.c Tue Jun 15 22:38:16 2010 +0000 +++ b/dvbsubdec.c Wed Jun 16 13:07:12 2010 +0000 @@ -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 @@ 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 @@ int display_list_size; DVBSubRegionDisplay *display_list; + DVBSubDisplayDefinition *display_definition; } DVBSubContext; @@ -334,6 +346,8 @@ av_free(clut); } + av_freep(&ctx->display_definition); + /* Should already be null */ if (ctx->object_list) av_log(0, AV_LOG_ERROR, "Memory deallocation error!\n"); @@ -1254,10 +1268,51 @@ } #endif +static void dvbsub_parse_display_definition_segment(AVCodecContext *avctx, + const uint8_t *buf, + int buf_size) +{ + DVBSubContext *ctx = 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; + if (display_def && display_def->version == dds_version) + return; // already have this display definition version + + if (!display_def) { + display_def = av_mallocz(sizeof(*display_def)); + ctx->display_definition = display_def; + } + if (!display_def) + return; + + 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 & 1<<3) { // 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 +1320,18 @@ 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 +1349,8 @@ 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 +1450,8 @@ 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;