This also adds a new field to AVHWAccel to set supported hardware device
types, so that we can query the right hwaccel.
---
Not entirely sure that the AVCodecContext should be the first argument of
probe_hw() - AVCodecParameters might be nicer, but we are likely to end up
needing an AVCodecContext anyway. (More generally, please bikeshed freely over
naming and structures used.)
The probe_hw() function on the D*VA hwaccel would be where the extra alignment
gets set (when AVCodecContext.hw_device_ctx is not used).
doc/APIchanges | 3 +++
libavcodec/avcodec.h | 51 +++++++++++++++++++++++++++++++++++++++++++++++++
libavcodec/decode.c | 53 ++++++++++++++++++++++++++++++++++++++++++++-------
libavcodec/encode.c | 13 +++++++++++++
libavcodec/internal.h | 10 ++++++++++
libavcodec/utils.c | 15 +++++++++++++++
6 files changed, 138 insertions(+), 7 deletions(-)
diff --git a/doc/APIchanges b/doc/APIchanges
index 5da821c90..649d35a08 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,9 @@ libavutil: 2017-03-23
API changes, most recent first:
+2017-04-xx - xxxxxxx - lavc 58.x+1.0 - avcodec.h
+ Add AVHWAccel.device_type and avcodec_probe_hw().
+
2017-04-xx - xxxxxxx - lavc 58.x.y+1 - avcodec.h
Add AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH.
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 2aa70ca4f..8f7293d02 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -35,6 +35,7 @@
#include "libavutil/cpu.h"
#include "libavutil/dict.h"
#include "libavutil/frame.h"
+#include "libavutil/hwcontext.h"
#include "libavutil/log.h"
#include "libavutil/pixfmt.h"
#include "libavutil/rational.h"
@@ -2857,6 +2858,15 @@ typedef struct AVCodec {
* packets before decoding.
*/
const char *bsfs;
+
+ /**
+ * Test support for the given encode/decode parameters, and if possible
+ * set the fields in the frames context to a set of usable values.
+ *
+ * If a hwaccel is used with a decoder and it also has a probe_hw()
+ * function, that will be called instead of this.
+ */
+ int (*probe_hw)(AVCodecContext *avctx, AVHWFramesContext *hw_frames);
} AVCodec;
/**
@@ -2898,6 +2908,11 @@ typedef struct AVHWAccel {
*/
int capabilities;
+ /**
+ * Hardware device type which this hwaccel can use.
+ */
+ enum AVHWDeviceType device_type;
+
/*****************************************************************
* No fields below this line are part of the public API. They
* may not be used outside of libavcodec and can be changed and
@@ -2988,6 +3003,11 @@ typedef struct AVHWAccel {
* Internal hwaccel capabilities.
*/
int caps_internal;
+
+ /**
+ * Probe hardware for support and parameters.
+ */
+ int (*probe_hw)(AVCodecContext *avctx, AVHWFramesContext *hw_frames);
} AVHWAccel;
/**
@@ -4927,6 +4947,37 @@ const AVCodecDescriptor
*avcodec_descriptor_get_by_name(const char *name);
AVCPBProperties *av_cpb_properties_alloc(size_t *size);
/**
+ * Probe hardware support for the given codec parameters.
+ *
+ * For decoders, it tests whether a stream with the given parameters can be
+ * decoded on the given device. For encoders, it tests whether encoding with
+ * the given parameters is possible on the device.
+ *
+ * On successful return, the fields of hw_frames_ref are set such that, once
+ * initialised, it will be usable as AVCodecContext.hw_frames_ctx. If the
+ * user has additional requirements to apply to the frames context (for
+ * example, for a larger pool size or for frames created with some system-
+ * specific attribute) then they should be applied after this call but before
+ * calling av_hwframe_ctx_init().
+ *
+ * The device to use is provided as the allocating context of hw_frames_ref.
+ * (Even if set, the hw_frames_ctx and hw_device_ctx fields of avctx are
+ * ignored.)
+ *
+ * @param avctx Codec context with relevant fields set. It need not have been
+ * opened.
+ * @param hw_frames_ref A reference to a newly-allocated AVHWFramesContext,
+ * which will be used to return the result.
+ * @return 0 on success, otherwise negative error code:
+ * AVERROR(ENOSYS): This function is not implemented (hardware support
+ * may or may not be available).
+ * AVERROR(ENODEV): The device is not usable.
+ * AVERROR(EINVAL): The codec parameters are not supported.
+ * Other errors: Probing failed for some other reason.
+ */
+int avcodec_probe_hw(AVCodecContext *avctx, AVBufferRef *hw_frames_ref);
+
+/**
* @}
*/
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index e4f6a0d72..4029683e6 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -701,13 +701,6 @@ static int is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt)
return desc->flags & AV_PIX_FMT_FLAG_HWACCEL;
}
-enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const
enum AVPixelFormat *fmt)
-{
- while (*fmt != AV_PIX_FMT_NONE && is_hwaccel_pix_fmt(*fmt))
- ++fmt;
- return fmt[0];
-}
-
static AVHWAccel *find_hwaccel(enum AVCodecID codec_id,
enum AVPixelFormat pix_fmt)
{
@@ -753,6 +746,28 @@ static int setup_hwaccel(AVCodecContext *avctx,
return 0;
}
+enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const
enum AVPixelFormat *fmt)
+{
+ if (s->hw_device_ctx) {
+ const AVHWDeviceContext *device = (const
AVHWDeviceContext*)s->hw_device_ctx->data;
+ const AVHWAccel *hwaccel;
+ int i;
+ for (i = 0; fmt[i] != AV_PIX_FMT_NONE; i++) {
+ if (!is_hwaccel_pix_fmt(fmt[i]))
+ continue;
+ hwaccel = find_hwaccel(s->codec_id, fmt[i]);
+ if (!hwaccel)
+ continue;
+ if (hwaccel->device_type == device->type)
+ return fmt[i];
+ }
+ }
+
+ while (*fmt != AV_PIX_FMT_NONE && is_hwaccel_pix_fmt(*fmt))
+ ++fmt;
+ return fmt[0];
+}
+
int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
{
const AVPixFmtDescriptor *desc;
@@ -1210,3 +1225,27 @@ void ff_decode_bsfs_uninit(AVCodecContext *avctx)
av_freep(&s->bsfs);
s->nb_bsfs = 0;
}
+
+int ff_decode_probe_hw(AVCodecContext *avctx, AVHWFramesContext *hw_frames)
+{
+ const AVCodec *codec = avctx->codec;
+ const AVHWAccel *hwaccel = NULL;
+
+ if (!codec)
+ return AVERROR(EINVAL);
+
+ if (!hw_frames->device_ctx)
+ return AVERROR(ENODEV);
+
+ while ((hwaccel = av_hwaccel_next(hwaccel))) {
+ if (hwaccel->id == avctx->codec_id &&
+ hwaccel->device_type == hw_frames->device_ctx->type)
+ break;
+ }
+ if (hwaccel && hwaccel->probe_hw)
+ return hwaccel->probe_hw(avctx, hw_frames);
+ else if (codec->probe_hw)
+ return codec->probe_hw(avctx, hw_frames);
+ else
+ return AVERROR(ENOSYS);
+}
diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index 9bb7ae5bd..d4914d7da 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -354,3 +354,16 @@ int attribute_align_arg
avcodec_receive_packet(AVCodecContext *avctx, AVPacket *
avctx->internal->buffer_pkt_valid = 0;
return 0;
}
+
+int ff_encode_probe_hw(AVCodecContext *avctx, AVHWFramesContext *hw_frames)
+{
+ const AVCodec *codec = avctx->codec;
+
+ if (!codec)
+ return AVERROR(EINVAL);
+
+ if (codec->probe_hw)
+ return codec->probe_hw(avctx, hw_frames);
+ else
+ return AVERROR(ENOSYS);
+}
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index 403fb4a09..930b32fd6 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -285,4 +285,14 @@ int ff_decode_frame_props(AVCodecContext *avctx, AVFrame
*frame);
*/
AVCPBProperties *ff_add_cpb_side_data(AVCodecContext *avctx);
+/**
+ * Probe decoder/hwaccel hardware support.
+ */
+int ff_decode_probe_hw(AVCodecContext *avctx, AVHWFramesContext *hw_frames);
+
+/**
+ * Probe encoder hardware support.
+ */
+int ff_encode_probe_hw(AVCodecContext *avctx, AVHWFramesContext *hw_frames);
+
#endif /* AVCODEC_INTERNAL_H */
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index bc421f67f..2a73098ec 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -1685,3 +1685,18 @@ int avcodec_parameters_to_context(AVCodecContext *codec,
return 0;
}
+
+int avcodec_probe_hw(AVCodecContext *avctx, AVBufferRef *hw_frames_ref)
+{
+ AVHWFramesContext *hw_frames = (AVHWFramesContext*)hw_frames_ref->data;
+
+ switch (avctx->codec_type) {
+ case AVMEDIA_TYPE_VIDEO:
+ if (av_codec_is_encoder(avctx->codec))
+ return ff_encode_probe_hw(avctx, hw_frames);
+ else
+ return ff_decode_probe_hw(avctx, hw_frames);
+ default:
+ return AVERROR(ENOSYS);
+ }
+}
--
2.11.0
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel