[FFmpeg-devel] [PATCH 11/25] fftools/ffmpeg: move opening decoders to a new file
Anton Khirnov
anton at khirnov.net
Thu Apr 13 17:12:09 EEST 2023
All decoding code will be moved to this file in the future.
---
fftools/Makefile | 1 +
fftools/ffmpeg.c | 111 +----------------------------------
fftools/ffmpeg.h | 2 +
fftools/ffmpeg_dec.c | 135 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 139 insertions(+), 110 deletions(-)
create mode 100644 fftools/ffmpeg_dec.c
diff --git a/fftools/Makefile b/fftools/Makefile
index 9939c7095c..56820e6bc8 100644
--- a/fftools/Makefile
+++ b/fftools/Makefile
@@ -10,6 +10,7 @@ ALLAVPROGS = $(AVBASENAMES:%=%$(PROGSSUF)$(EXESUF))
ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF))
OBJS-ffmpeg += \
+ fftools/ffmpeg_dec.o \
fftools/ffmpeg_demux.o \
fftools/ffmpeg_enc.o \
fftools/ffmpeg_filter.o \
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 57bdc12473..d8b06eb724 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -621,11 +621,6 @@ void assert_avoptions(AVDictionary *m)
}
}
-static void abort_codec_experimental(const AVCodec *c, int encoder)
-{
- exit_program(1);
-}
-
void update_benchmark(const char *fmt, ...)
{
if (do_benchmark_all) {
@@ -1858,110 +1853,6 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo
return !eof_reached;
}
-static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts)
-{
- InputStream *ist = s->opaque;
- const enum AVPixelFormat *p;
- int ret;
-
- for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) {
- const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p);
- const AVCodecHWConfig *config = NULL;
- int i;
-
- if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
- break;
-
- if (ist->hwaccel_id == HWACCEL_GENERIC ||
- ist->hwaccel_id == HWACCEL_AUTO) {
- for (i = 0;; i++) {
- config = avcodec_get_hw_config(s->codec, i);
- if (!config)
- break;
- if (!(config->methods &
- AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX))
- continue;
- if (config->pix_fmt == *p)
- break;
- }
- }
- if (config && config->device_type == ist->hwaccel_device_type) {
- ret = hwaccel_decode_init(s);
- if (ret < 0) {
- if (ist->hwaccel_id == HWACCEL_GENERIC) {
- av_log(NULL, AV_LOG_FATAL,
- "%s hwaccel requested for input stream #%d:%d, "
- "but cannot be initialized.\n",
- av_hwdevice_get_type_name(config->device_type),
- ist->file_index, ist->st->index);
- return AV_PIX_FMT_NONE;
- }
- continue;
- }
-
- ist->hwaccel_pix_fmt = *p;
- break;
- }
- }
-
- return *p;
-}
-
-static int init_input_stream(InputStream *ist)
-{
- int ret;
-
- if (ist->decoding_needed) {
- const AVCodec *codec = ist->dec;
- if (!codec) {
- av_log(ist, AV_LOG_ERROR,
- "Decoding requested, but no decoder found for: %s\n",
- avcodec_get_name(ist->dec_ctx->codec_id));
- return AVERROR(EINVAL);
- }
-
- ist->dec_ctx->opaque = ist;
- ist->dec_ctx->get_format = get_format;
-
- if (ist->dec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE &&
- (ist->decoding_needed & DECODING_FOR_OST)) {
- av_dict_set(&ist->decoder_opts, "compute_edt", "1", AV_DICT_DONT_OVERWRITE);
- if (ist->decoding_needed & DECODING_FOR_FILTER)
- av_log(NULL, AV_LOG_WARNING, "Warning using DVB subtitles for filtering and output at the same time is not fully supported, also see -compute_edt [0|1]\n");
- }
-
- /* Useful for subtitles retiming by lavf (FIXME), skipping samples in
- * audio, and video decoders such as cuvid or mediacodec */
- ist->dec_ctx->pkt_timebase = ist->st->time_base;
-
- if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0))
- av_dict_set(&ist->decoder_opts, "threads", "auto", 0);
- /* Attached pics are sparse, therefore we would not want to delay their decoding till EOF. */
- if (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)
- av_dict_set(&ist->decoder_opts, "threads", "1", 0);
-
- ret = hw_device_setup_for_decode(ist);
- if (ret < 0) {
- av_log(ist, AV_LOG_ERROR,
- "Hardware device setup failed for decoder: %s\n",
- av_err2str(ret));
- return ret;
- }
-
- if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) {
- if (ret == AVERROR_EXPERIMENTAL)
- abort_codec_experimental(codec, 0);
-
- av_log(ist, AV_LOG_ERROR, "Error while opening decoder: %s\n",
- av_err2str(ret));
- return ret;
- }
- assert_avoptions(ist->decoder_opts);
- }
-
- return 0;
-}
-
static int init_output_stream_nofilter(OutputStream *ost)
{
int ret = 0;
@@ -1993,7 +1884,7 @@ static int transcode_init(void)
/* init input streams */
for (InputStream *ist = ist_iter(NULL); ist; ist = ist_iter(ist))
- if ((ret = init_input_stream(ist)) < 0)
+ if (ist->decoding_needed && (ret = dec_open(ist)) < 0)
goto dump_format;
/*
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index c73fc8a459..5833c13812 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -829,6 +829,8 @@ AVBufferRef *hw_device_for_filter(void);
int hwaccel_decode_init(AVCodecContext *avctx);
+int dec_open(InputStream *ist);
+
int enc_alloc(Encoder **penc, const AVCodec *codec);
void enc_free(Encoder **penc);
diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c
new file mode 100644
index 0000000000..ccf558649c
--- /dev/null
+++ b/fftools/ffmpeg_dec.c
@@ -0,0 +1,135 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/dict.h"
+#include "libavutil/error.h"
+#include "libavutil/log.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/pixfmt.h"
+
+#include "libavcodec/avcodec.h"
+#include "libavcodec/codec.h"
+
+#include "ffmpeg.h"
+
+static void abort_codec_experimental(const AVCodec *c, int encoder)
+{
+ exit_program(1);
+}
+
+static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts)
+{
+ InputStream *ist = s->opaque;
+ const enum AVPixelFormat *p;
+ int ret;
+
+ for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) {
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p);
+ const AVCodecHWConfig *config = NULL;
+ int i;
+
+ if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
+ break;
+
+ if (ist->hwaccel_id == HWACCEL_GENERIC ||
+ ist->hwaccel_id == HWACCEL_AUTO) {
+ for (i = 0;; i++) {
+ config = avcodec_get_hw_config(s->codec, i);
+ if (!config)
+ break;
+ if (!(config->methods &
+ AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX))
+ continue;
+ if (config->pix_fmt == *p)
+ break;
+ }
+ }
+ if (config && config->device_type == ist->hwaccel_device_type) {
+ ret = hwaccel_decode_init(s);
+ if (ret < 0) {
+ if (ist->hwaccel_id == HWACCEL_GENERIC) {
+ av_log(NULL, AV_LOG_FATAL,
+ "%s hwaccel requested for input stream #%d:%d, "
+ "but cannot be initialized.\n",
+ av_hwdevice_get_type_name(config->device_type),
+ ist->file_index, ist->st->index);
+ return AV_PIX_FMT_NONE;
+ }
+ continue;
+ }
+
+ ist->hwaccel_pix_fmt = *p;
+ break;
+ }
+ }
+
+ return *p;
+}
+
+int dec_open(InputStream *ist)
+{
+ const AVCodec *codec = ist->dec;
+ int ret;
+
+ if (!codec) {
+ av_log(ist, AV_LOG_ERROR,
+ "Decoding requested, but no decoder found for: %s\n",
+ avcodec_get_name(ist->dec_ctx->codec_id));
+ return AVERROR(EINVAL);
+ }
+
+ ist->dec_ctx->opaque = ist;
+ ist->dec_ctx->get_format = get_format;
+
+ if (ist->dec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE &&
+ (ist->decoding_needed & DECODING_FOR_OST)) {
+ av_dict_set(&ist->decoder_opts, "compute_edt", "1", AV_DICT_DONT_OVERWRITE);
+ if (ist->decoding_needed & DECODING_FOR_FILTER)
+ av_log(NULL, AV_LOG_WARNING, "Warning using DVB subtitles for filtering and output at the same time is not fully supported, also see -compute_edt [0|1]\n");
+ }
+
+ /* Useful for subtitles retiming by lavf (FIXME), skipping samples in
+ * audio, and video decoders such as cuvid or mediacodec */
+ ist->dec_ctx->pkt_timebase = ist->st->time_base;
+
+ if (!av_dict_get(ist->decoder_opts, "threads", NULL, 0))
+ av_dict_set(&ist->decoder_opts, "threads", "auto", 0);
+ /* Attached pics are sparse, therefore we would not want to delay their decoding till EOF. */
+ if (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC)
+ av_dict_set(&ist->decoder_opts, "threads", "1", 0);
+
+ ret = hw_device_setup_for_decode(ist);
+ if (ret < 0) {
+ av_log(ist, AV_LOG_ERROR,
+ "Hardware device setup failed for decoder: %s\n",
+ av_err2str(ret));
+ return ret;
+ }
+
+ if ((ret = avcodec_open2(ist->dec_ctx, codec, &ist->decoder_opts)) < 0) {
+ if (ret == AVERROR_EXPERIMENTAL)
+ abort_codec_experimental(codec, 0);
+
+ av_log(ist, AV_LOG_ERROR, "Error while opening decoder: %s\n",
+ av_err2str(ret));
+ return ret;
+ }
+ assert_avoptions(ist->decoder_opts);
+
+ return 0;
+}
--
2.39.1
More information about the ffmpeg-devel
mailing list