Commit 641ec5ed authored by janne's avatar janne

dvbsub: parse display definition segment

The display definition segment is used to properly display SD DVB subtitles in
HD video streams.


git-svn-id: file:///var/local/repositories/ffmpeg/trunk@23626 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b
parent 9cd11550
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "dsputil.h" #include "dsputil.h"
#include "get_bits.h" #include "get_bits.h"
#include "colorspace.h" #include "colorspace.h"
#include "bytestream.h"
//#define DEBUG //#define DEBUG
//#define DEBUG_PACKET_CONTENTS //#define DEBUG_PACKET_CONTENTS
...@@ -31,6 +32,7 @@ ...@@ -31,6 +32,7 @@
#define DVBSUB_REGION_SEGMENT 0x11 #define DVBSUB_REGION_SEGMENT 0x11
#define DVBSUB_CLUT_SEGMENT 0x12 #define DVBSUB_CLUT_SEGMENT 0x12
#define DVBSUB_OBJECT_SEGMENT 0x13 #define DVBSUB_OBJECT_SEGMENT 0x13
#define DVBSUB_DISPLAYDEFINITION_SEGMENT 0x14
#define DVBSUB_DISPLAY_SEGMENT 0x80 #define DVBSUB_DISPLAY_SEGMENT 0x80
#define cm (ff_cropTbl + MAX_NEG_CROP) #define cm (ff_cropTbl + MAX_NEG_CROP)
...@@ -216,6 +218,15 @@ typedef struct DVBSubRegion { ...@@ -216,6 +218,15 @@ typedef struct DVBSubRegion {
struct DVBSubRegion *next; struct DVBSubRegion *next;
} DVBSubRegion; } DVBSubRegion;
typedef struct DVBSubDisplayDefinition {
int version;
int x;
int y;
int width;
int height;
} DVBSubDisplayDefinition;
typedef struct DVBSubContext { typedef struct DVBSubContext {
int composition_id; int composition_id;
int ancillary_id; int ancillary_id;
...@@ -227,6 +238,7 @@ typedef struct DVBSubContext { ...@@ -227,6 +238,7 @@ typedef struct DVBSubContext {
int display_list_size; int display_list_size;
DVBSubRegionDisplay *display_list; DVBSubRegionDisplay *display_list;
DVBSubDisplayDefinition *display_definition;
} DVBSubContext; } DVBSubContext;
...@@ -334,6 +346,8 @@ static void delete_state(DVBSubContext *ctx) ...@@ -334,6 +346,8 @@ static void delete_state(DVBSubContext *ctx)
av_free(clut); av_free(clut);
} }
av_freep(&ctx->display_definition);
/* Should already be null */ /* Should already be null */
if (ctx->object_list) if (ctx->object_list)
av_log(0, AV_LOG_ERROR, "Memory deallocation error!\n"); av_log(0, AV_LOG_ERROR, "Memory deallocation error!\n");
...@@ -1254,10 +1268,51 @@ static void save_display_set(DVBSubContext *ctx) ...@@ -1254,10 +1268,51 @@ static void save_display_set(DVBSubContext *ctx)
} }
#endif #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, static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf,
int buf_size, AVSubtitle *sub) int buf_size, AVSubtitle *sub)
{ {
DVBSubContext *ctx = (DVBSubContext*) avctx->priv_data; DVBSubContext *ctx = (DVBSubContext*) avctx->priv_data;
DVBSubDisplayDefinition *display_def = ctx->display_definition;
DVBSubRegion *region; DVBSubRegion *region;
DVBSubRegionDisplay *display; DVBSubRegionDisplay *display;
...@@ -1265,12 +1320,18 @@ static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf, ...@@ -1265,12 +1320,18 @@ static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf,
DVBSubCLUT *clut; DVBSubCLUT *clut;
uint32_t *clut_table; uint32_t *clut_table;
int i; int i;
int offset_x=0, offset_y=0;
sub->rects = NULL; sub->rects = NULL;
sub->start_display_time = 0; sub->start_display_time = 0;
sub->end_display_time = ctx->time_out * 1000; sub->end_display_time = ctx->time_out * 1000;
sub->format = 0; sub->format = 0;
if (display_def) {
offset_x = display_def->x;
offset_y = display_def->y;
}
sub->num_rects = ctx->display_list_size; sub->num_rects = ctx->display_list_size;
if (sub->num_rects > 0){ if (sub->num_rects > 0){
...@@ -1288,8 +1349,8 @@ static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf, ...@@ -1288,8 +1349,8 @@ static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf,
if (!region) if (!region)
continue; continue;
rect->x = display->x_pos; rect->x = display->x_pos + offset_x;
rect->y = display->y_pos; rect->y = display->y_pos + offset_y;
rect->w = region->width; rect->w = region->width;
rect->h = region->height; rect->h = region->height;
rect->nb_colors = 16; rect->nb_colors = 16;
...@@ -1389,6 +1450,8 @@ static int dvbsub_decode(AVCodecContext *avctx, ...@@ -1389,6 +1450,8 @@ static int dvbsub_decode(AVCodecContext *avctx,
case DVBSUB_OBJECT_SEGMENT: case DVBSUB_OBJECT_SEGMENT:
dvbsub_parse_object_segment(avctx, p, segment_length); dvbsub_parse_object_segment(avctx, p, segment_length);
break; break;
case DVBSUB_DISPLAYDEFINITION_SEGMENT:
dvbsub_parse_display_definition_segment(avctx, p, segment_length);
case DVBSUB_DISPLAY_SEGMENT: case DVBSUB_DISPLAY_SEGMENT:
*data_size = dvbsub_display_end_segment(avctx, p, segment_length, sub); *data_size = dvbsub_display_end_segment(avctx, p, segment_length, sub);
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment