diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 80c09d1662..abf95f106b 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -286,6 +286,14 @@ enum DecoderFlags { DECODER_FLAG_TS_UNRELIABLE = (1 << 1), }; +typedef struct DecoderOpts { + /* hwaccel options */ + enum HWAccelID hwaccel_id; + enum AVHWDeviceType hwaccel_device_type; + char *hwaccel_device; + enum AVPixelFormat hwaccel_output_format; +} DecoderOpts; + typedef struct Decoder { const AVClass *class; @@ -351,12 +359,6 @@ typedef struct InputStream { int nb_outputs; int reinit_filters; - - /* hwaccel options */ - enum HWAccelID hwaccel_id; - enum AVHWDeviceType hwaccel_device_type; - char *hwaccel_device; - enum AVPixelFormat hwaccel_output_format; } InputStream; typedef struct InputFile { @@ -736,7 +738,7 @@ AVBufferRef *hw_device_for_filter(void); * is transferred to the decoder. */ int dec_open(InputStream *ist, Scheduler *sch, unsigned sch_idx, - AVDictionary **dec_opts, int flags); + AVDictionary **dec_opts, int flags, const DecoderOpts *o); void dec_free(Decoder **pdec); int dec_add_filter(Decoder *dec, InputFilter *ifilter); diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c index b66c0e35ee..791df8d98c 100644 --- a/fftools/ffmpeg_dec.c +++ b/fftools/ffmpeg_dec.c @@ -48,7 +48,10 @@ typedef struct DecoderPriv { // a combination of DECODER_FLAG_*, provided to dec_open() int flags; - enum AVPixelFormat hwaccel_pix_fmt; + enum AVPixelFormat hwaccel_pix_fmt; + enum HWAccelID hwaccel_id; + enum AVHWDeviceType hwaccel_device_type; + enum AVPixelFormat hwaccel_output_format; // pts/estimated duration of the last decoded frame // * in decoder timebase for video, @@ -267,9 +270,9 @@ static int64_t video_duration_estimate(const InputStream *ist, const AVFrame *fr static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input) { - InputStream *ist = avctx->opaque; + DecoderPriv *dp = avctx->opaque; AVFrame *output = NULL; - enum AVPixelFormat output_format = ist->hwaccel_output_format; + enum AVPixelFormat output_format = dp->hwaccel_output_format; int err; if (input->format == output_format) { @@ -746,8 +749,7 @@ finish: static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts) { - InputStream *ist = s->opaque; - DecoderPriv *dp = dp_from_dec(ist->decoder); + DecoderPriv *dp = s->opaque; const enum AVPixelFormat *p; for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) { @@ -758,8 +760,8 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) break; - if (ist->hwaccel_id == HWACCEL_GENERIC || - ist->hwaccel_id == HWACCEL_AUTO) { + if (dp->hwaccel_id == HWACCEL_GENERIC || + dp->hwaccel_id == HWACCEL_AUTO) { for (i = 0;; i++) { config = avcodec_get_hw_config(s->codec, i); if (!config) @@ -771,7 +773,7 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat break; } } - if (config && config->device_type == ist->hwaccel_device_type) { + if (config && config->device_type == dp->hwaccel_device_type) { dp->hwaccel_pix_fmt = *p; break; } @@ -797,21 +799,22 @@ static HWDevice *hw_device_match_by_codec(const AVCodec *codec) } } -static int hw_device_setup_for_decode(InputStream *ist, DecoderPriv *dp) +static int hw_device_setup_for_decode(InputStream *ist, DecoderPriv *dp, + const char *hwaccel_device) { const AVCodecHWConfig *config; enum AVHWDeviceType type; HWDevice *dev = NULL; int err, auto_device = 0; - if (ist->hwaccel_device) { - dev = hw_device_get_by_name(ist->hwaccel_device); + if (hwaccel_device) { + dev = hw_device_get_by_name(hwaccel_device); if (!dev) { - if (ist->hwaccel_id == HWACCEL_AUTO) { + if (dp->hwaccel_id == HWACCEL_AUTO) { auto_device = 1; - } else if (ist->hwaccel_id == HWACCEL_GENERIC) { - type = ist->hwaccel_device_type; - err = hw_device_init_from_type(type, ist->hwaccel_device, + } else if (dp->hwaccel_id == HWACCEL_GENERIC) { + type = dp->hwaccel_device_type; + err = hw_device_init_from_type(type, hwaccel_device, &dev); } else { // This will be dealt with by API-specific initialisation @@ -819,22 +822,22 @@ static int hw_device_setup_for_decode(InputStream *ist, DecoderPriv *dp) return 0; } } else { - if (ist->hwaccel_id == HWACCEL_AUTO) { - ist->hwaccel_device_type = dev->type; - } else if (ist->hwaccel_device_type != dev->type) { + if (dp->hwaccel_id == HWACCEL_AUTO) { + dp->hwaccel_device_type = dev->type; + } else if (dp->hwaccel_device_type != dev->type) { av_log(dp, AV_LOG_ERROR, "Invalid hwaccel device " "specified for decoder: device %s of type %s is not " "usable with hwaccel %s.\n", dev->name, av_hwdevice_get_type_name(dev->type), - av_hwdevice_get_type_name(ist->hwaccel_device_type)); + av_hwdevice_get_type_name(dp->hwaccel_device_type)); return AVERROR(EINVAL); } } } else { - if (ist->hwaccel_id == HWACCEL_AUTO) { + if (dp->hwaccel_id == HWACCEL_AUTO) { auto_device = 1; - } else if (ist->hwaccel_id == HWACCEL_GENERIC) { - type = ist->hwaccel_device_type; + } else if (dp->hwaccel_id == HWACCEL_GENERIC) { + type = dp->hwaccel_device_type; dev = hw_device_get_by_type(type); // When "-qsv_device device" is used, an internal QSV device named @@ -884,17 +887,17 @@ static int hw_device_setup_for_decode(InputStream *ist, DecoderPriv *dp) break; type = config->device_type; // Try to make a new device of this type. - err = hw_device_init_from_type(type, ist->hwaccel_device, + err = hw_device_init_from_type(type, hwaccel_device, &dev); if (err < 0) { // Can't make a device of this type. continue; } - if (ist->hwaccel_device) { + if (hwaccel_device) { av_log(dp, AV_LOG_INFO, "Using auto " "hwaccel type %s with new device created " "from %s.\n", av_hwdevice_get_type_name(type), - ist->hwaccel_device); + hwaccel_device); } else { av_log(dp, AV_LOG_INFO, "Using auto " "hwaccel type %s with new default device.\n", @@ -902,11 +905,11 @@ static int hw_device_setup_for_decode(InputStream *ist, DecoderPriv *dp) } } if (dev) { - ist->hwaccel_device_type = type; + dp->hwaccel_device_type = type; } else { av_log(dp, AV_LOG_INFO, "Auto hwaccel " "disabled: no device found.\n"); - ist->hwaccel_id = HWACCEL_NONE; + dp->hwaccel_id = HWACCEL_NONE; return 0; } } @@ -940,7 +943,7 @@ static const AVClass dec_class = { }; int dec_open(InputStream *ist, Scheduler *sch, unsigned sch_idx, - AVDictionary **dec_opts, int flags) + AVDictionary **dec_opts, int flags, const DecoderOpts *o) { DecoderPriv *dp; const AVCodec *codec = ist->dec; @@ -958,6 +961,10 @@ int dec_open(InputStream *ist, Scheduler *sch, unsigned sch_idx, dp->dec.class = &dec_class; dp->log_parent = ist; + dp->hwaccel_id = o->hwaccel_id; + dp->hwaccel_device_type = o->hwaccel_device_type; + dp->hwaccel_output_format = o->hwaccel_output_format; + snprintf(dp->log_name, sizeof(dp->log_name), "dec:%s", codec->name); if (codec->type == AVMEDIA_TYPE_SUBTITLE && @@ -984,7 +991,7 @@ int dec_open(InputStream *ist, Scheduler *sch, unsigned sch_idx, return ret; } - dp->dec_ctx->opaque = ist; + dp->dec_ctx->opaque = dp; dp->dec_ctx->get_format = get_format; if (dp->dec_ctx->codec_id == AV_CODEC_ID_DVB_SUBTITLE && @@ -1005,7 +1012,7 @@ int dec_open(InputStream *ist, Scheduler *sch, unsigned sch_idx, av_dict_set(dec_opts, "flags", "+copy_opaque", AV_DICT_MULTIKEY); - ret = hw_device_setup_for_decode(ist, dp); + ret = hw_device_setup_for_decode(ist, dp, o->hwaccel_device); if (ret < 0) { av_log(dp, AV_LOG_ERROR, "Hardware device setup failed for decoder: %s\n", diff --git a/fftools/ffmpeg_demux.c b/fftools/ffmpeg_demux.c index 729d7e476b..0f426e3c2e 100644 --- a/fftools/ffmpeg_demux.c +++ b/fftools/ffmpeg_demux.c @@ -72,6 +72,8 @@ typedef struct DemuxStream { const AVCodecDescriptor *codec_desc; + DecoderOpts dec_opts; + AVBSFContext *bsf; /* number of packets successfully read for this stream */ @@ -823,7 +825,7 @@ static void ist_free(InputStream **pist) av_dict_free(&ist->decoder_opts); av_freep(&ist->filters); av_freep(&ist->outputs); - av_freep(&ist->hwaccel_device); + av_freep(&ds->dec_opts.hwaccel_device); avcodec_parameters_free(&ist->par); @@ -905,7 +907,7 @@ static int ist_use(InputStream *ist, int decoding_needed) return ret; ret = dec_open(ist, d->sch, ds->sch_idx_dec, - &ist->decoder_opts, dec_flags); + &ist->decoder_opts, dec_flags, &ds->dec_opts); if (ret < 0) return ret; @@ -1166,25 +1168,25 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) "WARNING: defaulting hwaccel_output_format to cuda for compatibility " "with old commandlines. This behaviour is DEPRECATED and will be removed " "in the future. Please explicitly set \"-hwaccel_output_format cuda\".\n"); - ist->hwaccel_output_format = AV_PIX_FMT_CUDA; + ds->dec_opts.hwaccel_output_format = AV_PIX_FMT_CUDA; } else if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "qsv")) { av_log(ist, AV_LOG_WARNING, "WARNING: defaulting hwaccel_output_format to qsv for compatibility " "with old commandlines. This behaviour is DEPRECATED and will be removed " "in the future. Please explicitly set \"-hwaccel_output_format qsv\".\n"); - ist->hwaccel_output_format = AV_PIX_FMT_QSV; + ds->dec_opts.hwaccel_output_format = AV_PIX_FMT_QSV; } else if (!hwaccel_output_format && hwaccel && !strcmp(hwaccel, "mediacodec")) { // There is no real AVHWFrameContext implementation. Set // hwaccel_output_format to avoid av_hwframe_transfer_data error. - ist->hwaccel_output_format = AV_PIX_FMT_MEDIACODEC; + ds->dec_opts.hwaccel_output_format = AV_PIX_FMT_MEDIACODEC; } else if (hwaccel_output_format) { - ist->hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format); - if (ist->hwaccel_output_format == AV_PIX_FMT_NONE) { + ds->dec_opts.hwaccel_output_format = av_get_pix_fmt(hwaccel_output_format); + if (ds->dec_opts.hwaccel_output_format == AV_PIX_FMT_NONE) { av_log(ist, AV_LOG_FATAL, "Unrecognised hwaccel output " "format: %s", hwaccel_output_format); } } else { - ist->hwaccel_output_format = AV_PIX_FMT_NONE; + ds->dec_opts.hwaccel_output_format = AV_PIX_FMT_NONE; } if (hwaccel) { @@ -1193,17 +1195,17 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) hwaccel = "cuda"; if (!strcmp(hwaccel, "none")) - ist->hwaccel_id = HWACCEL_NONE; + ds->dec_opts.hwaccel_id = HWACCEL_NONE; else if (!strcmp(hwaccel, "auto")) - ist->hwaccel_id = HWACCEL_AUTO; + ds->dec_opts.hwaccel_id = HWACCEL_AUTO; else { enum AVHWDeviceType type = av_hwdevice_find_type_by_name(hwaccel); if (type != AV_HWDEVICE_TYPE_NONE) { - ist->hwaccel_id = HWACCEL_GENERIC; - ist->hwaccel_device_type = type; + ds->dec_opts.hwaccel_id = HWACCEL_GENERIC; + ds->dec_opts.hwaccel_device_type = type; } - if (!ist->hwaccel_id) { + if (!ds->dec_opts.hwaccel_id) { av_log(ist, AV_LOG_FATAL, "Unrecognized hwaccel: %s.\n", hwaccel); av_log(ist, AV_LOG_FATAL, "Supported hwaccels: "); @@ -1220,14 +1222,14 @@ static int ist_add(const OptionsContext *o, Demuxer *d, AVStream *st) MATCH_PER_STREAM_OPT(hwaccel_devices, str, hwaccel_device, ic, st); if (hwaccel_device) { - ist->hwaccel_device = av_strdup(hwaccel_device); - if (!ist->hwaccel_device) + ds->dec_opts.hwaccel_device = av_strdup(hwaccel_device); + if (!ds->dec_opts.hwaccel_device) return AVERROR(ENOMEM); } } - ret = choose_decoder(o, ic, st, ist->hwaccel_id, ist->hwaccel_device_type, - &ist->dec); + ret = choose_decoder(o, ic, st, ds->dec_opts.hwaccel_id, + ds->dec_opts.hwaccel_device_type, &ist->dec); if (ret < 0) return ret;