diff options
Diffstat (limited to 'sub/lavc_conv.c')
-rw-r--r-- | sub/lavc_conv.c | 92 |
1 files changed, 60 insertions, 32 deletions
diff --git a/sub/lavc_conv.c b/sub/lavc_conv.c index 8e1d1aad7f..3a33933605 100644 --- a/sub/lavc_conv.c +++ b/sub/lavc_conv.c @@ -23,17 +23,20 @@ #include <libavutil/common.h> #include <libavutil/opt.h> -#include "config.h" - #include "mpv_talloc.h" #include "common/msg.h" #include "common/av_common.h" +#include "demux/stheader.h" #include "misc/bstr.h" #include "sd.h" struct lavc_conv { struct mp_log *log; + struct mp_subtitle_opts *opts; + bool styled; AVCodecContext *avctx; + AVPacket *avpkt; + AVPacket *avpkt_vtt; char *codec; char *extradata; AVSubtitle cur; @@ -51,27 +54,13 @@ static const char *get_lavc_format(const char *format) return format; } -// Disable style definitions generated by the libavcodec converter. -// We always want the user defined style instead. -static void disable_styles(bstr header) -{ - bstr style = bstr0("\nStyle: "); - while (header.len) { - int n = bstr_find(header, style); - if (n < 0) - break; - header.start[n + 1] = '#'; // turn into a comment - header = bstr_cut(header, n + style.len); - } -} - -struct lavc_conv *lavc_conv_create(struct mp_log *log, const char *codec_name, - char *extradata, int extradata_len) +struct lavc_conv *lavc_conv_create(struct sd *sd) { struct lavc_conv *priv = talloc_zero(NULL, struct lavc_conv); - priv->log = log; + priv->log = sd->log; + priv->opts = sd->opts; priv->cur_list = talloc_array(priv, char*, 0); - priv->codec = talloc_strdup(priv, codec_name); + priv->codec = talloc_strdup(priv, sd->codec->codec); AVCodecContext *avctx = NULL; AVDictionary *opts = NULL; const char *fmt = get_lavc_format(priv->codec); @@ -81,11 +70,28 @@ struct lavc_conv *lavc_conv_create(struct mp_log *log, const char *codec_name, avctx = avcodec_alloc_context3(codec); if (!avctx) goto error; - if (mp_lavc_set_extradata(avctx, extradata, extradata_len) < 0) + if (mp_set_avctx_codec_headers(avctx, sd->codec) < 0) + goto error; + + priv->avpkt = av_packet_alloc(); + priv->avpkt_vtt = av_packet_alloc(); + if (!priv->avpkt || !priv->avpkt_vtt) goto error; + + switch (codec->id) { + case AV_CODEC_ID_DVB_TELETEXT: + av_dict_set_int(&opts, "txt_format", 2, 0); + break; + case AV_CODEC_ID_ARIB_CAPTION: + av_dict_set_int(&opts, "sub_type", SUBTITLE_ASS, 0); + break; + } + +#if LIBAVCODEC_VERSION_MAJOR < 59 av_dict_set(&opts, "sub_text_format", "ass", 0); +#endif av_dict_set(&opts, "flags2", "+ass_ro_flush_noop", 0); - if (strcmp(codec_name, "eia_608") == 0) + if (strcmp(priv->codec, "eia_608") == 0) av_dict_set(&opts, "real_time", "1", 0); if (avcodec_open2(avctx, codec, &opts) < 0) goto error; @@ -97,13 +103,14 @@ struct lavc_conv *lavc_conv_create(struct mp_log *log, const char *codec_name, priv->avctx = avctx; priv->extradata = talloc_strndup(priv, avctx->subtitle_header, avctx->subtitle_header_size); - disable_styles(bstr0(priv->extradata)); return priv; error: MP_FATAL(priv, "Could not open libavcodec subtitle converter\n"); av_dict_free(&opts); av_free(avctx); + mp_free_av_packet(&priv->avpkt); + mp_free_av_packet(&priv->avpkt_vtt); talloc_free(priv); return NULL; } @@ -221,26 +228,40 @@ char **lavc_conv_decode(struct lavc_conv *priv, struct demux_packet *packet, double *sub_pts, double *sub_duration) { AVCodecContext *avctx = priv->avctx; - AVPacket pkt; - AVPacket parsed_pkt = {0}; + AVPacket *curr_pkt = priv->avpkt; int ret, got_sub; int num_cur = 0; avsubtitle_free(&priv->cur); - mp_set_av_packet(&pkt, packet, &avctx->time_base); - if (pkt.pts < 0) - pkt.pts = 0; + mp_set_av_packet(priv->avpkt, packet, &avctx->time_base); + if (priv->avpkt->pts < 0) + priv->avpkt->pts = 0; if (strcmp(priv->codec, "webvtt-webm") == 0) { - if (parse_webvtt(&pkt, &parsed_pkt) < 0) { + if (parse_webvtt(priv->avpkt, priv->avpkt_vtt) < 0) { MP_ERR(priv, "Error parsing subtitle\n"); goto done; } - pkt = parsed_pkt; + curr_pkt = priv->avpkt_vtt; + } + + priv->styled = avctx->codec_id == AV_CODEC_ID_DVB_TELETEXT; + + if (avctx->codec_id == AV_CODEC_ID_DVB_TELETEXT) { + if (!priv->opts->teletext_page) { + av_opt_set(avctx, "txt_page", "subtitle", AV_OPT_SEARCH_CHILDREN); + priv->styled = false; + } else if (priv->opts->teletext_page == -1) { + av_opt_set(avctx, "txt_page", "*", AV_OPT_SEARCH_CHILDREN); + } else { + char page[4]; + snprintf(page, sizeof(page), "%d", priv->opts->teletext_page); + av_opt_set(avctx, "txt_page", page, AV_OPT_SEARCH_CHILDREN); + } } - ret = avcodec_decode_subtitle2(avctx, &priv->cur, &got_sub, &pkt); + ret = avcodec_decode_subtitle2(avctx, &priv->cur, &got_sub, curr_pkt); if (ret < 0) { MP_ERR(priv, "Error decoding subtitle\n"); } else if (got_sub) { @@ -263,11 +284,16 @@ char **lavc_conv_decode(struct lavc_conv *priv, struct demux_packet *packet, } done: - av_packet_unref(&parsed_pkt); + av_packet_unref(priv->avpkt_vtt); MP_TARRAY_APPEND(priv, priv->cur_list, num_cur, NULL); return priv->cur_list; } +bool lavc_conv_is_styled(struct lavc_conv *priv) +{ + return priv->styled; +} + void lavc_conv_reset(struct lavc_conv *priv) { avcodec_flush_buffers(priv->avctx); @@ -277,5 +303,7 @@ void lavc_conv_uninit(struct lavc_conv *priv) { avsubtitle_free(&priv->cur); avcodec_free_context(&priv->avctx); + mp_free_av_packet(&priv->avpkt); + mp_free_av_packet(&priv->avpkt_vtt); talloc_free(priv); } |