[FFmpeg-devel] [PATCH v3 04/26] avfilter/subtitles: Update vf_subtitles to use new decoding api
ffmpegagent
ffmpegagent at gmail.com
Thu Jan 20 05:25:12 EET 2022
From: softworkz <softworkz at hotmail.com>
Signed-off-by: softworkz <softworkz at hotmail.com>
---
libavfilter/vf_subtitles.c | 56 +++++++++++++++++++++++++++++---------
1 file changed, 43 insertions(+), 13 deletions(-)
diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c
index 3fc4eeb63d..25e217e845 100644
--- a/libavfilter/vf_subtitles.c
+++ b/libavfilter/vf_subtitles.c
@@ -35,14 +35,12 @@
# include "libavformat/avformat.h"
#endif
#include "libavutil/avstring.h"
-#include "libavutil/imgutils.h"
#include "libavutil/opt.h"
#include "libavutil/parseutils.h"
#include "drawutils.h"
#include "avfilter.h"
#include "internal.h"
#include "formats.h"
-#include "video.h"
typedef struct AssContext {
const AVClass *class;
@@ -292,6 +290,29 @@ static int attachment_is_font(AVStream * st)
return 0;
}
+static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *pkt)
+{
+ int ret;
+
+ *got_frame = 0;
+
+ if (pkt) {
+ ret = avcodec_send_packet(avctx, pkt);
+ // In particular, we don't expect AVERROR(EAGAIN), because we read all
+ // decoded frames with avcodec_receive_frame() until done.
+ if (ret < 0 && ret != AVERROR_EOF)
+ return ret;
+ }
+
+ ret = avcodec_receive_frame(avctx, frame);
+ if (ret < 0 && ret != AVERROR(EAGAIN))
+ return ret;
+ if (ret >= 0)
+ *got_frame = 1;
+
+ return 0;
+}
+
AVFILTER_DEFINE_CLASS(subtitles);
static av_cold int init_subtitles(AVFilterContext *ctx)
@@ -306,6 +327,7 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
AVStream *st;
AVPacket pkt;
AssContext *ass = ctx->priv;
+ enum AVSubtitleType subtitle_format;
/* Init libass */
ret = init(ctx);
@@ -386,13 +408,17 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
ret = AVERROR_DECODER_NOT_FOUND;
goto end;
}
+
dec_desc = avcodec_descriptor_get(st->codecpar->codec_id);
- if (dec_desc && !(dec_desc->props & AV_CODEC_PROP_TEXT_SUB)) {
+ subtitle_format = avcodec_descriptor_get_subtitle_format(dec_desc);
+
+ if (subtitle_format != AV_SUBTITLE_FMT_ASS) {
av_log(ctx, AV_LOG_ERROR,
- "Only text based subtitles are currently supported\n");
- ret = AVERROR_PATCHWELCOME;
+ "Only text based subtitles are supported by this filter\n");
+ ret = AVERROR_INVALIDDATA;
goto end;
}
+
if (ass->charenc)
av_dict_set(&codec_opts, "sub_charenc", ass->charenc, 0);
@@ -448,27 +474,31 @@ static av_cold int init_subtitles(AVFilterContext *ctx)
dec_ctx->subtitle_header_size);
while (av_read_frame(fmt, &pkt) >= 0) {
int i, got_subtitle;
- AVSubtitle sub = {0};
+ AVFrame *sub = av_frame_alloc();
+ if (!sub) {
+ ret = AVERROR(ENOMEM);
+ goto end;
+ }
if (pkt.stream_index == sid) {
- ret = avcodec_decode_subtitle2(dec_ctx, &sub, &got_subtitle, &pkt);
+ ret = decode(dec_ctx, sub, &got_subtitle, &pkt);
if (ret < 0) {
av_log(ctx, AV_LOG_WARNING, "Error decoding: %s (ignored)\n",
av_err2str(ret));
} else if (got_subtitle) {
- const int64_t start_time = av_rescale_q(sub.pts, AV_TIME_BASE_Q, av_make_q(1, 1000));
- const int64_t duration = sub.end_display_time;
- for (i = 0; i < sub.num_rects; i++) {
- char *ass_line = sub.rects[i]->ass;
+ const int64_t start_time = av_rescale_q(sub->subtitle_timing.start_pts, AV_TIME_BASE_Q, av_make_q(1, 1000));
+ const int64_t duration = av_rescale_q(sub->subtitle_timing.duration, AV_TIME_BASE_Q, av_make_q(1, 1000));
+ for (i = 0; i < sub->num_subtitle_areas; i++) {
+ char *ass_line = sub->subtitle_areas[i]->ass;
if (!ass_line)
- break;
+ continue;
ass_process_chunk(ass->track, ass_line, strlen(ass_line),
start_time, duration);
}
}
}
av_packet_unref(&pkt);
- avsubtitle_free(&sub);
+ av_frame_free(&sub);
}
end:
--
ffmpeg-codebot
More information about the ffmpeg-devel
mailing list