avcodec/dvbsubdec: support returning exact end times

fixess part of ticket #2024

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Anshul Maheshwari 2014-06-22 12:54:33 +05:30 committed by Michael Niedermayer
parent 9b33cdcab2
commit ca2f59e121

View File

@ -234,6 +234,9 @@ typedef struct DVBSubContext {
int version; int version;
int time_out; int time_out;
int compute_edt; /**< if 1 end display time calculated using pts
if 0 (Default) calculated using time out */
int64_t prev_start;
DVBSubRegion *region_list; DVBSubRegion *region_list;
DVBSubCLUT *clut_list; DVBSubCLUT *clut_list;
DVBSubObject *object_list; DVBSubObject *object_list;
@ -383,6 +386,7 @@ static av_cold int dvbsub_init_decoder(AVCodecContext *avctx)
} }
ctx->version = -1; ctx->version = -1;
ctx->prev_start = AV_NOPTS_VALUE;
default_clut.id = -1; default_clut.id = -1;
default_clut.next = NULL; default_clut.next = NULL;
@ -759,7 +763,7 @@ static int dvbsub_read_8bit_string(uint8_t *destbuf, int dbuf_len,
return pixels_read; return pixels_read;
} }
static void save_subtitle_set(AVCodecContext *avctx, AVSubtitle *sub) static void save_subtitle_set(AVCodecContext *avctx, AVSubtitle *sub, int *got_output)
{ {
DVBSubContext *ctx = avctx->priv_data; DVBSubContext *ctx = avctx->priv_data;
DVBSubRegionDisplay *display; DVBSubRegionDisplay *display;
@ -771,14 +775,19 @@ static void save_subtitle_set(AVCodecContext *avctx, AVSubtitle *sub)
int i; int i;
int offset_x=0, offset_y=0; int offset_x=0, offset_y=0;
sub->end_display_time = ctx->time_out * 1000; if(ctx->compute_edt == 0)
sub->end_display_time = ctx->time_out * 1000;
if (display_def) { if (display_def) {
offset_x = display_def->x; offset_x = display_def->x;
offset_y = display_def->y; offset_y = display_def->y;
} }
sub->num_rects = 0; /* Not touching AVSubtitles again*/
if(sub->num_rects) {
avpriv_request_sample(ctx, "Different Version of Segment asked Twice\n");
return;
}
for (display = ctx->display_list; display; display = display->next) { for (display = ctx->display_list; display; display = display->next) {
region = get_region(ctx, display->region_id); region = get_region(ctx, display->region_id);
if (region && region->dirty) if (region && region->dirty)
@ -786,6 +795,13 @@ static void save_subtitle_set(AVCodecContext *avctx, AVSubtitle *sub)
} }
if (sub->num_rects > 0) { if (sub->num_rects > 0) {
if(ctx->compute_edt == 1 && ctx->prev_start != AV_NOPTS_VALUE) {
sub->end_display_time = av_rescale_q((sub->pts - ctx->prev_start ), AV_TIME_BASE_Q, (AVRational){ 1, 1000 }) - 1;
*got_output = 1;
} else if (ctx->compute_edt == 0) {
*got_output = 1;
}
sub->rects = av_mallocz_array(sizeof(*sub->rects), sub->num_rects); sub->rects = av_mallocz_array(sizeof(*sub->rects), sub->num_rects);
for(i=0; i<sub->num_rects; i++) for(i=0; i<sub->num_rects; i++)
sub->rects[i] = av_mallocz(sizeof(*sub->rects[i])); sub->rects[i] = av_mallocz(sizeof(*sub->rects[i]));
@ -1228,7 +1244,7 @@ static void dvbsub_parse_region_segment(AVCodecContext *avctx,
} }
static void dvbsub_parse_page_segment(AVCodecContext *avctx, static void dvbsub_parse_page_segment(AVCodecContext *avctx,
const uint8_t *buf, int buf_size, AVSubtitle *sub) const uint8_t *buf, int buf_size, AVSubtitle *sub, int *got_output)
{ {
DVBSubContext *ctx = avctx->priv_data; DVBSubContext *ctx = avctx->priv_data;
DVBSubRegionDisplay *display; DVBSubRegionDisplay *display;
@ -1256,6 +1272,9 @@ static void dvbsub_parse_page_segment(AVCodecContext *avctx,
av_dlog(avctx, "Page time out %ds, state %d\n", ctx->time_out, page_state); av_dlog(avctx, "Page time out %ds, state %d\n", ctx->time_out, page_state);
if(ctx->compute_edt == 1)
save_subtitle_set(avctx, sub, got_output);
if (page_state == 1 || page_state == 2) { if (page_state == 1 || page_state == 2) {
delete_regions(ctx); delete_regions(ctx);
delete_objects(ctx); delete_objects(ctx);
@ -1445,17 +1464,17 @@ static void dvbsub_parse_display_definition_segment(AVCodecContext *avctx,
} }
} }
static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf, static void dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf,
int buf_size, AVSubtitle *sub) int buf_size, AVSubtitle *sub,int *got_output)
{ {
DVBSubContext *ctx = avctx->priv_data; DVBSubContext *ctx = avctx->priv_data;
save_subtitle_set(avctx,sub); if(ctx->compute_edt == 0)
save_subtitle_set(avctx, sub, got_output);
#ifdef DEBUG #ifdef DEBUG
save_display_set(ctx); save_display_set(ctx);
#endif #endif
return 1;
} }
static int dvbsub_decode(AVCodecContext *avctx, static int dvbsub_decode(AVCodecContext *avctx,
@ -1471,7 +1490,7 @@ static int dvbsub_decode(AVCodecContext *avctx,
int page_id; int page_id;
int segment_length; int segment_length;
int i; int i;
int ret; int ret = 0;
int got_segment = 0; int got_segment = 0;
av_dlog(avctx, "DVB sub packet:\n"); av_dlog(avctx, "DVB sub packet:\n");
@ -1507,14 +1526,15 @@ static int dvbsub_decode(AVCodecContext *avctx,
if (p_end - p < segment_length) { if (p_end - p < segment_length) {
av_dlog(avctx, "incomplete or broken packet"); av_dlog(avctx, "incomplete or broken packet");
return -1; ret = -1;
goto end;
} }
if (page_id == ctx->composition_id || page_id == ctx->ancillary_id || if (page_id == ctx->composition_id || page_id == ctx->ancillary_id ||
ctx->composition_id == -1 || ctx->ancillary_id == -1) { ctx->composition_id == -1 || ctx->ancillary_id == -1) {
switch (segment_type) { switch (segment_type) {
case DVBSUB_PAGE_SEGMENT: case DVBSUB_PAGE_SEGMENT:
dvbsub_parse_page_segment(avctx, p, segment_length, sub); dvbsub_parse_page_segment(avctx, p, segment_length, sub, data_size);
got_segment |= 1; got_segment |= 1;
break; break;
case DVBSUB_REGION_SEGMENT: case DVBSUB_REGION_SEGMENT:
@ -1523,7 +1543,7 @@ static int dvbsub_decode(AVCodecContext *avctx,
break; break;
case DVBSUB_CLUT_SEGMENT: case DVBSUB_CLUT_SEGMENT:
ret = dvbsub_parse_clut_segment(avctx, p, segment_length); ret = dvbsub_parse_clut_segment(avctx, p, segment_length);
if (ret < 0) return ret; if (ret < 0) goto end;
got_segment |= 4; got_segment |= 4;
break; break;
case DVBSUB_OBJECT_SEGMENT: case DVBSUB_OBJECT_SEGMENT:
@ -1534,7 +1554,7 @@ static int dvbsub_decode(AVCodecContext *avctx,
dvbsub_parse_display_definition_segment(avctx, p, segment_length); dvbsub_parse_display_definition_segment(avctx, p, segment_length);
break; break;
case DVBSUB_DISPLAY_SEGMENT: case DVBSUB_DISPLAY_SEGMENT:
*data_size = dvbsub_display_end_segment(avctx, p, segment_length, sub); dvbsub_display_end_segment(avctx, p, segment_length, sub, data_size);
got_segment |= 16; got_segment |= 16;
break; break;
default: default:
@ -1550,13 +1570,24 @@ static int dvbsub_decode(AVCodecContext *avctx,
// segments then we need no further data. // segments then we need no further data.
if (got_segment == 15 && sub) { if (got_segment == 15 && sub) {
av_log(avctx, AV_LOG_DEBUG, "Missing display_end_segment, emulating\n"); av_log(avctx, AV_LOG_DEBUG, "Missing display_end_segment, emulating\n");
*data_size = dvbsub_display_end_segment(avctx, p, 0, sub); dvbsub_display_end_segment(avctx, p, 0, sub, data_size);
}
end:
if(ret < 0) {
*data_size = 0;
avsubtitle_free(sub);
return ret;
} else {
if(ctx->compute_edt == 1 )
FFSWAP(int64_t, ctx->prev_start, sub->pts);
} }
return p - buf; return p - buf;
} }
static const AVOption options[] = { static const AVOption options[] = {
{"compute_edt", "compute end of time using pts or timeout", offsetof(DVBSubContext, compute_edt), FF_OPT_TYPE_INT, {.i64 = 0}, 0, 1, 0},
{NULL} {NULL}
}; };
static const AVClass dvbsubdec_class = { static const AVClass dvbsubdec_class = {