dvbsub: parse display definition segment
The display definition segment is used to properly display SD DVB subtitles in HD video streams. Originally committed as revision 23626 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
8b889b3480
commit
08943c0bd1
@ -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 @@
|
|||||||
#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 {
|
|||||||
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 {
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
#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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user