summaryrefslogtreecommitdiffstats
path: root/sub/lavc_conv.c
diff options
context:
space:
mode:
Diffstat (limited to 'sub/lavc_conv.c')
-rw-r--r--sub/lavc_conv.c92
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);
}