Re: [libav-devel] [RFC] [PATCH] stereo3d: Update the naming API to be more consistent

2017-04-23 Thread James Almer

On 4/20/2017 12:34 PM, Vittorio Giovara wrote:

Change input type of the type->str function and return a proper
error code for the str->type function.
---
Similar reasoning to the previous patch.
Vittorio

  libavutil/stereo3d.c | 6 +++---
  libavutil/stereo3d.h | 2 +-
  2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/libavutil/stereo3d.c b/libavutil/stereo3d.c
index 5dc902e909..6e2f9f3ad2 100644
--- a/libavutil/stereo3d.c
+++ b/libavutil/stereo3d.c
@@ -54,9 +54,9 @@ static const char * const stereo3d_type_names[] = {
  [AV_STEREO3D_COLUMNS] = "interleaved columns",
  };
  
-const char *av_stereo3d_type_name(unsigned int type)

+const char *av_stereo3d_type_name(enum AVStereo3DType type)
  {
-if (type >= FF_ARRAY_ELEMS(stereo3d_type_names))
+if ((unsigned) type >= FF_ARRAY_ELEMS(stereo3d_type_names))
  return "unknown";
  
  return stereo3d_type_names[type];

@@ -72,5 +72,5 @@ int av_stereo3d_from_name(const char *name)
  return i;
  }
  
-return -1;

+return AVERROR(EINVAL);


Why EINVAL here but ENOSYS for spherical?

Also, while changing -1 to AVERROR() isn't a considerable API break as 
changing NULL on failure to a string on failure, it's still one and 
really makes me wonder if it's worth doing.
While most users probably just check for < 0, in which case both return 
values would work the same, anyone instead checking explicitly for -1 (a 
completely valid check as per the documentation, which you for that 
matter did not update in this patch) will instead break.



  }
diff --git a/libavutil/stereo3d.h b/libavutil/stereo3d.h
index 0fa9f63a2c..cbf138faef 100644
--- a/libavutil/stereo3d.h
+++ b/libavutil/stereo3d.h
@@ -190,7 +190,7 @@ AVStereo3D *av_stereo3d_create_side_data(AVFrame *frame);
   *
   * @return The name of the stereo3d value, or "unknown".
   */
-const char *av_stereo3d_type_name(unsigned int type);
+const char *av_stereo3d_type_name(enum AVStereo3DType type);
  
  /**

   * Get the AVStereo3DType form a human-readable name.



___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

[libav-devel] [PATCH 7/9] vf_hwmap: Add device derivation

2017-04-23 Thread Mark Thompson
Also refactor a little and improve error messages to make failure
cases easier to understand.
---
Removed the useless device reference.

Example use:

./avconv -y -init_hw_device vaapi -hwaccel vaapi -hwaccel_output_format vaapi 
-i in.mp4 -an -vf 
'deinterlace_vaapi,scale_vaapi=1280:720,hwmap=derive_device=qsv,format=qsv' 
-c:v h264_qsv -b 5M -maxrate 5M out.mp4


 libavfilter/vf_hwmap.c | 67 --
 1 file changed, 49 insertions(+), 18 deletions(-)

diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c
index 11595bd6c..f19d10f2c 100644
--- a/libavfilter/vf_hwmap.c
+++ b/libavfilter/vf_hwmap.c
@@ -30,10 +30,10 @@
 typedef struct HWMapContext {
 const AVClass *class;
 
-AVBufferRef   *hwdevice_ref;
 AVBufferRef   *hwframes_ref;
 
 intmode;
+char  *derive_device_type;
 intmap_backwards;
 } HWMapContext;
 
@@ -52,6 +52,7 @@ static int hwmap_config_output(AVFilterLink *outlink)
 HWMapContext  *ctx = avctx->priv;
 AVFilterLink   *inlink = avctx->inputs[0];
 AVHWFramesContext *hwfc;
+AVBufferRef *device;
 const AVPixFmtDescriptor *desc;
 int err;
 
@@ -59,30 +60,58 @@ static int hwmap_config_output(AVFilterLink *outlink)
av_get_pix_fmt_name(inlink->format),
av_get_pix_fmt_name(outlink->format));
 
+av_buffer_unref(>hwframes_ref);
+
+device = avctx->hw_device_ctx;
+
 if (inlink->hw_frames_ctx) {
 hwfc = (AVHWFramesContext*)inlink->hw_frames_ctx->data;
 
+if (ctx->derive_device_type) {
+enum AVHWDeviceType type;
+
+type = av_hwdevice_find_type_by_name(ctx->derive_device_type);
+if (type == AV_HWDEVICE_TYPE_NONE) {
+av_log(avctx, AV_LOG_ERROR, "Invalid device type.\n");
+goto fail;
+}
+
+err = av_hwdevice_ctx_create_derived(, type,
+ hwfc->device_ref, 0);
+if (err < 0) {
+av_log(avctx, AV_LOG_ERROR, "Failed to created derived "
+   "device context: %d.\n", err);
+goto fail;
+}
+}
+
 desc = av_pix_fmt_desc_get(outlink->format);
-if (!desc)
-return AVERROR(EINVAL);
+if (!desc) {
+err = AVERROR(EINVAL);
+goto fail;
+}
 
 if (inlink->format == hwfc->format &&
 (desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
 // Map between two hardware formats (including the case of
 // undoing an existing mapping).
 
-ctx->hwdevice_ref = av_buffer_ref(avctx->hw_device_ctx);
-if (!ctx->hwdevice_ref) {
-err = AVERROR(ENOMEM);
+if (!device) {
+av_log(avctx, AV_LOG_ERROR, "A device reference is "
+   "required to map to a hardware format.\n");
+err = AVERROR(EINVAL);
 goto fail;
 }
 
 err = av_hwframe_ctx_create_derived(>hwframes_ref,
 outlink->format,
-ctx->hwdevice_ref,
+device,
 inlink->hw_frames_ctx, 0);
-if (err < 0)
+if (err < 0) {
+av_log(avctx, AV_LOG_ERROR, "Failed to create derived "
+   "frames context: %d.\n", err);
 goto fail;
+}
 
 } else if ((outlink->format == hwfc->format &&
 inlink->format  == hwfc->sw_format) ||
@@ -90,8 +119,6 @@ static int hwmap_config_output(AVFilterLink *outlink)
 // Map from a hardware format to a software format, or
 // undo an existing such mapping.
 
-ctx->hwdevice_ref = NULL;
-
 ctx->hwframes_ref = av_buffer_ref(inlink->hw_frames_ctx);
 if (!ctx->hwframes_ref) {
 err = AVERROR(ENOMEM);
@@ -115,15 +142,17 @@ static int hwmap_config_output(AVFilterLink *outlink)
 // returns frames mapped from that to the previous link in
 // order to fill them without an additional copy.
 
-ctx->map_backwards = 1;
-
-ctx->hwdevice_ref = av_buffer_ref(avctx->hw_device_ctx);
-if (!ctx->hwdevice_ref) {
-err = AVERROR(ENOMEM);
+if (!device) {
+av_log(avctx, AV_LOG_ERROR, "A device reference is "
+   "required to create new frames with backwards "
+   "mapping.\n");
+err = AVERROR(EINVAL);
 goto fail;
 }
 
-ctx->hwframes_ref = av_hwframe_ctx_alloc(ctx->hwdevice_ref);
+ctx->map_backwards = 1;
+
+ctx->hwframes_ref = av_hwframe_ctx_alloc(device);
 if (!ctx->hwframes_ref) {
 err = AVERROR(ENOMEM);
 goto 

[libav-devel] [PATCH 6/9] hwcontext: Improve allocation in derived contexts

2017-04-23 Thread Mark Thompson
Use the flags argument of av_hwframe_ctx_create_derived() to pass the
mapping flags which will be used on allocation.  Also, set the format
and hardware context on the allocated frame automatically - the user
should not be required to do this themselves.
---
Added APIchanges + version bump.


 doc/APIchanges |  4 
 libavutil/hwcontext.c  | 14 +-
 libavutil/hwcontext.h  |  4 +++-
 libavutil/hwcontext_internal.h |  5 +
 libavutil/version.h|  2 +-
 5 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index a0ca3b7ac..9c530b348 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,10 @@ libavutil: 2017-03-23
 
 API changes, most recent first:
 
+2017-04-xx - xxx - lavu 56.0.1 - hwcontext.h
+  av_hwframe_ctx_create_derived() now takes some AV_HWFRAME_MAP_* combination
+  as its flags argument (which was previously unused).
+
 2017-03-xx - xxx - lavc 57.37.0 - avcodec.h
   Add AVCodecContext.hwaccel_flags field. This will control some hwaccels at
   a later point.
diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index a6d88421d..360b01205 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -455,6 +455,11 @@ int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, 
AVFrame *frame, int flags)
 // and map the frame immediately.
 AVFrame *src_frame;
 
+frame->format = ctx->format;
+frame->hw_frames_ctx = av_buffer_ref(hwframe_ref);
+if (!frame->hw_frames_ctx)
+return AVERROR(ENOMEM);
+
 src_frame = av_frame_alloc();
 if (!src_frame)
 return AVERROR(ENOMEM);
@@ -464,7 +469,8 @@ int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame 
*frame, int flags)
 if (ret < 0)
 return ret;
 
-ret = av_hwframe_map(frame, src_frame, 0);
+ret = av_hwframe_map(frame, src_frame,
+ ctx->internal->source_allocation_map_flags);
 if (ret) {
 av_log(ctx, AV_LOG_ERROR, "Failed to map frame into derived "
"frame context: %d.\n", ret);
@@ -816,6 +822,12 @@ int av_hwframe_ctx_create_derived(AVBufferRef 
**derived_frame_ctx,
 goto fail;
 }
 
+dst->internal->source_allocation_map_flags =
+flags & (AV_HWFRAME_MAP_READ  |
+ AV_HWFRAME_MAP_WRITE |
+ AV_HWFRAME_MAP_OVERWRITE |
+ AV_HWFRAME_MAP_DIRECT);
+
 ret = AVERROR(ENOSYS);
 if (src->internal->hw_type->frames_derive_from)
 ret = src->internal->hw_type->frames_derive_from(dst, src, flags);
diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index 889e30365..eaf40c46f 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -564,7 +564,9 @@ int av_hwframe_map(AVFrame *dst, const AVFrame *src, int 
flags);
  *   AVHWFramesContext on.
  * @param source_frame_ctx   A reference to an existing AVHWFramesContext
  *   which will be mapped to the derived context.
- * @param flags  Currently unused; should be set to zero.
+ * @param flags  Some combination of AV_HWFRAME_MAP_* flags, defining the
+ *   mapping parameters to apply to frames which are allocated
+ *   in the derived device.
  * @return   Zero on success, negative AVERROR code on failure.
  */
 int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx,
diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h
index 87b32e191..7cf6cb07c 100644
--- a/libavutil/hwcontext_internal.h
+++ b/libavutil/hwcontext_internal.h
@@ -121,6 +121,11 @@ struct AVHWFramesInternal {
  * context it was derived from.
  */
 AVBufferRef *source_frames;
+/**
+ * Flags to apply to the mapping from the source to the derived
+ * frame context when trying to allocate in the derived context.
+ */
+int source_allocation_map_flags;
 };
 
 typedef struct HWMapDescriptor {
diff --git a/libavutil/version.h b/libavutil/version.h
index b8425ea2c..86e645763 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -55,7 +55,7 @@
 
 #define LIBAVUTIL_VERSION_MAJOR 56
 #define LIBAVUTIL_VERSION_MINOR  0
-#define LIBAVUTIL_VERSION_MICRO  0
+#define LIBAVUTIL_VERSION_MICRO  1
 
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
LIBAVUTIL_VERSION_MINOR, \
-- 
2.11.0

___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

[libav-devel] [PATCH 8/9] vf_hwmap: Add reverse mapping for hardware frames

2017-04-23 Thread Mark Thompson
This is something of a hack.  It allocates a new hwframe context for
the target format, then maps it back to the source link and overwrites
the input link hw_frames_ctx so that the previous filter will receive
the frames we want from ff_get_video_buffer().  It may fail if
the previous filter imposes any additional constraints on the frames
it wants to use as output.
---
Unchanged.


 libavfilter/vf_hwmap.c | 68 --
 1 file changed, 61 insertions(+), 7 deletions(-)

diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c
index f19d10f2c..2983528ea 100644
--- a/libavfilter/vf_hwmap.c
+++ b/libavfilter/vf_hwmap.c
@@ -34,7 +34,7 @@ typedef struct HWMapContext {
 
 intmode;
 char  *derive_device_type;
-intmap_backwards;
+intreverse;
 } HWMapContext;
 
 static int hwmap_query_formats(AVFilterContext *avctx)
@@ -92,7 +92,8 @@ static int hwmap_config_output(AVFilterLink *outlink)
 }
 
 if (inlink->format == hwfc->format &&
-(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
+(desc->flags & AV_PIX_FMT_FLAG_HWACCEL) &&
+!ctx->reverse) {
 // Map between two hardware formats (including the case of
 // undoing an existing mapping).
 
@@ -113,6 +114,56 @@ static int hwmap_config_output(AVFilterLink *outlink)
 goto fail;
 }
 
+} else if (inlink->format == hwfc->format &&
+   (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) &&
+   ctx->reverse) {
+// Map between two hardware formats, but do it in reverse.
+// Make a new hwframe context for the target type, and then
+// overwrite the input hwframe context with a derived context
+// mapped from that back to the source type.
+AVBufferRef *source;
+AVHWFramesContext *frames;
+
+ctx->hwframes_ref = av_hwframe_ctx_alloc(device);
+if (!ctx->hwframes_ref) {
+err = AVERROR(ENOMEM);
+goto fail;
+}
+frames = (AVHWFramesContext*)ctx->hwframes_ref->data;
+
+frames->format= outlink->format;
+frames->sw_format = hwfc->sw_format;
+frames->width = hwfc->width;
+frames->height= hwfc->height;
+frames->initial_pool_size = 64;
+
+err = av_hwframe_ctx_init(ctx->hwframes_ref);
+if (err < 0) {
+av_log(avctx, AV_LOG_ERROR, "Failed to initialise "
+   "target frames context: %d.\n", err);
+goto fail;
+}
+
+err = av_hwframe_ctx_create_derived(,
+inlink->format,
+hwfc->device_ref,
+ctx->hwframes_ref,
+ctx->mode);
+if (err < 0) {
+av_log(avctx, AV_LOG_ERROR, "Failed to create "
+   "derived source frames context: %d.\n", err);
+goto fail;
+}
+
+// Here is the naughty bit.  This overwriting changes what
+// ff_get_video_buffer() in the previous filter returns -
+// it will now give a frame allocated here mapped back to
+// the format it expects.  If there were any additional
+// constraints on the output frames there then this may
+// break nastily.
+av_buffer_unref(>hw_frames_ctx);
+inlink->hw_frames_ctx = source;
+
 } else if ((outlink->format == hwfc->format &&
 inlink->format  == hwfc->sw_format) ||
inlink->format == hwfc->format) {
@@ -144,13 +195,13 @@ static int hwmap_config_output(AVFilterLink *outlink)
 
 if (!device) {
 av_log(avctx, AV_LOG_ERROR, "A device reference is "
-   "required to create new frames with backwards "
+   "required to create new frames with reverse "
"mapping.\n");
 err = AVERROR(EINVAL);
 goto fail;
 }
 
-ctx->map_backwards = 1;
+ctx->reverse = 1;
 
 ctx->hwframes_ref = av_hwframe_ctx_alloc(device);
 if (!ctx->hwframes_ref) {
@@ -167,7 +218,7 @@ static int hwmap_config_output(AVFilterLink *outlink)
 err = av_hwframe_ctx_init(ctx->hwframes_ref);
 if (err < 0) {
 av_log(avctx, AV_LOG_ERROR, "Failed to create frame "
-   "context for backward mapping: %d.\n", err);
+   "context for reverse mapping: %d.\n", err);
 goto fail;
 }
 
@@ -199,7 +250,7 @@ static AVFrame *hwmap_get_buffer(AVFilterLink *inlink, int 
w, int h)
 AVFilterLink  *outlink = avctx->outputs[0];
 HWMapContext  *ctx = 

[libav-devel] [PATCH 9/9] avconv_dxva2: Allow output of hardware frames

2017-04-23 Thread Mark Thompson
---
Kindof hacky, but a simple way to make hardware transcode with dxva2 work in 
avconv without needing the hw_device_ctx support to convert it to the 
hw-generic tooling.

Slightly unfortunate that the pixfmt is called "dxva_vld", though.

Example:

./avconv.exe -y -init_hw_device dxva2 -hwaccel dxva2 -hwaccel_output_format 
dxva2_vld -i in.mp4 -an -vf 'hwmap=derive_device=qsv,format=qsv' -c:v h264_qsv 
-b 5M -maxrate 5M out.mp4


 avtools/avconv_dxva2.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/avtools/avconv_dxva2.c b/avtools/avconv_dxva2.c
index 7578c3f63..710b1a818 100644
--- a/avtools/avconv_dxva2.c
+++ b/avtools/avconv_dxva2.c
@@ -137,6 +137,9 @@ static int dxva2_retrieve_data(AVCodecContext *s, AVFrame 
*frame)
 DXVA2Context   *ctx = ist->hwaccel_ctx;
 intret;
 
+if (frame->format == ist->hwaccel_output_format)
+return 0;
+
 ret = av_hwframe_transfer_data(ctx->tmp_frame, frame, 0);
 if (ret < 0)
 return ret;
-- 
2.11.0

___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

[libav-devel] [PATCH 4/9] hwcontext_qsv: Implement mapping frames from the child device type

2017-04-23 Thread Mark Thompson
Factorises out existing surface initialisation code to reuse.
---
No change.


 libavutil/hwcontext_qsv.c | 174 +-
 1 file changed, 142 insertions(+), 32 deletions(-)

diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index 46636ef9e..f981e6e53 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -94,6 +94,16 @@ static const struct {
 { AV_PIX_FMT_PAL8, MFX_FOURCC_P8   },
 };
 
+static uint32_t qsv_fourcc_from_pix_fmt(enum AVPixelFormat pix_fmt)
+{
+int i;
+for (i = 0; i < FF_ARRAY_ELEMS(supported_pixel_formats); i++) {
+if (supported_pixel_formats[i].pix_fmt == pix_fmt)
+return supported_pixel_formats[i].fourcc;
+}
+return 0;
+}
+
 static int qsv_device_init(AVHWDeviceContext *ctx)
 {
 AVQSVDeviceContext *hwctx = ctx->hwctx;
@@ -272,18 +282,48 @@ fail:
 return ret;
 }
 
+static int qsv_init_surface(AVHWFramesContext *ctx, mfxFrameSurface1 *surf)
+{
+const AVPixFmtDescriptor *desc;
+uint32_t fourcc;
+
+desc = av_pix_fmt_desc_get(ctx->sw_format);
+if (!desc)
+return AVERROR(EINVAL);
+
+fourcc = qsv_fourcc_from_pix_fmt(ctx->sw_format);
+if (!fourcc)
+return AVERROR(EINVAL);
+
+surf->Info.BitDepthLuma   = desc->comp[0].depth;
+surf->Info.BitDepthChroma = desc->comp[0].depth;
+surf->Info.Shift  = desc->comp[0].depth > 8;
+
+if (desc->log2_chroma_w && desc->log2_chroma_h)
+surf->Info.ChromaFormat   = MFX_CHROMAFORMAT_YUV420;
+else if (desc->log2_chroma_w)
+surf->Info.ChromaFormat   = MFX_CHROMAFORMAT_YUV422;
+else
+surf->Info.ChromaFormat   = MFX_CHROMAFORMAT_YUV444;
+
+surf->Info.FourCC = fourcc;
+surf->Info.Width  = ctx->width;
+surf->Info.CropW  = ctx->width;
+surf->Info.Height = ctx->height;
+surf->Info.CropH  = ctx->height;
+surf->Info.FrameRateExtN  = 25;
+surf->Info.FrameRateExtD  = 1;
+
+return 0;
+}
+
 static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t fourcc)
 {
 QSVFramesContext  *s = ctx->internal->priv;
 AVQSVFramesContext *frames_hwctx = ctx->hwctx;
-const AVPixFmtDescriptor *desc;
 
 int i, ret = 0;
 
-desc = av_pix_fmt_desc_get(ctx->sw_format);
-if (!desc)
-return AVERROR_BUG;
-
 if (ctx->initial_pool_size <= 0) {
 av_log(ctx, AV_LOG_ERROR, "QSV requires a fixed frame pool size\n");
 return AVERROR(EINVAL);
@@ -295,26 +335,9 @@ static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t 
fourcc)
 return AVERROR(ENOMEM);
 
 for (i = 0; i < ctx->initial_pool_size; i++) {
-mfxFrameSurface1 *surf = >surfaces_internal[i];
-
-surf->Info.BitDepthLuma   = desc->comp[0].depth;
-surf->Info.BitDepthChroma = desc->comp[0].depth;
-surf->Info.Shift  = desc->comp[0].depth > 8;
-
-if (desc->log2_chroma_w && desc->log2_chroma_h)
-surf->Info.ChromaFormat   = MFX_CHROMAFORMAT_YUV420;
-else if (desc->log2_chroma_w)
-surf->Info.ChromaFormat   = MFX_CHROMAFORMAT_YUV422;
-else
-surf->Info.ChromaFormat   = MFX_CHROMAFORMAT_YUV444;
-
-surf->Info.FourCC = fourcc;
-surf->Info.Width  = ctx->width;
-surf->Info.CropW  = ctx->width;
-surf->Info.Height = ctx->height;
-surf->Info.CropH  = ctx->height;
-surf->Info.FrameRateExtN  = 25;
-surf->Info.FrameRateExtD  = 1;
+ret = qsv_init_surface(ctx, >surfaces_internal[i]);
+if (ret < 0)
+return ret;
 }
 
 if (!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)) {
@@ -466,15 +489,10 @@ static int qsv_frames_init(AVHWFramesContext *ctx)
 
 int opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
 
-uint32_t fourcc = 0;
+uint32_t fourcc;
 int i, ret;
 
-for (i = 0; i < FF_ARRAY_ELEMS(supported_pixel_formats); i++) {
-if (supported_pixel_formats[i].pix_fmt == ctx->sw_format) {
-fourcc = supported_pixel_formats[i].fourcc;
-break;
-}
-}
+fourcc = qsv_fourcc_from_pix_fmt(ctx->sw_format);
 if (!fourcc) {
 av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format\n");
 return AVERROR(ENOSYS);
@@ -723,6 +741,96 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, 
AVFrame *dst,
 return 0;
 }
 
+static int qsv_frames_derive_to(AVHWFramesContext *dst_ctx,
+AVHWFramesContext *src_ctx, int flags)
+{
+QSVFramesContext *s = dst_ctx->internal->priv;
+AVQSVFramesContext *dst_hwctx = dst_ctx->hwctx;
+int i;
+
+switch (src_ctx->device_ctx->type) {
+#if CONFIG_VAAPI
+case AV_HWDEVICE_TYPE_VAAPI:
+{
+AVVAAPIFramesContext *src_hwctx = src_ctx->hwctx;
+s->surfaces_internal = av_mallocz_array(src_hwctx->nb_surfaces,
+   

[libav-devel] [PATCH 3/9] hwcontext: Add frame context mapping for nontrivial contexts

2017-04-23 Thread Mark Thompson
Some frames contexts are not usable without additional format-specific
state in hwctx.  This change adds new functions frames_derive_from and
frames_derive_to to initialise this state appropriately when deriving
a frames context which will require it to be set.
---
map_frames_to/from renamed to frames_derive_to/from.


 libavutil/hwcontext.c  | 9 -
 libavutil/hwcontext_internal.h | 5 +
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index ff9fe99ab..a6d88421d 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -816,7 +816,14 @@ int av_hwframe_ctx_create_derived(AVBufferRef 
**derived_frame_ctx,
 goto fail;
 }
 
-ret = av_hwframe_ctx_init(dst_ref);
+ret = AVERROR(ENOSYS);
+if (src->internal->hw_type->frames_derive_from)
+ret = src->internal->hw_type->frames_derive_from(dst, src, flags);
+if (ret == AVERROR(ENOSYS) &&
+dst->internal->hw_type->frames_derive_to)
+ret = dst->internal->hw_type->frames_derive_to(dst, src, flags);
+if (ret == AVERROR(ENOSYS))
+ret = 0;
 if (ret)
 goto fail;
 
diff --git a/libavutil/hwcontext_internal.h b/libavutil/hwcontext_internal.h
index 66f54142e..87b32e191 100644
--- a/libavutil/hwcontext_internal.h
+++ b/libavutil/hwcontext_internal.h
@@ -92,6 +92,11 @@ typedef struct HWContextType {
const AVFrame *src, int flags);
 int  (*map_from)(AVHWFramesContext *ctx, AVFrame *dst,
  const AVFrame *src, int flags);
+
+int  (*frames_derive_to)(AVHWFramesContext *dst_ctx,
+ AVHWFramesContext *src_ctx, int 
flags);
+int  (*frames_derive_from)(AVHWFramesContext *dst_ctx,
+   AVHWFramesContext *src_ctx, int 
flags);
 } HWContextType;
 
 struct AVHWDeviceInternal {
-- 
2.11.0

___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

[libav-devel] [PATCH 1/9] avconv: Support setting the hardware device to use when filtering

2017-04-23 Thread Mark Thompson
This only supports one device globally, but more can be used by
passing them with input streams in hw_frames_ctx or by deriving new
devices inside a filter graph with hwmap.
---
Added doc.


 avtools/avconv.h|  1 +
 avtools/avconv_filter.c | 10 --
 avtools/avconv_opt.c| 21 +
 doc/avconv.texi | 11 +++
 4 files changed, 41 insertions(+), 2 deletions(-)

diff --git a/avtools/avconv.h b/avtools/avconv.h
index 9415b208b..3354c5044 100644
--- a/avtools/avconv.h
+++ b/avtools/avconv.h
@@ -489,6 +489,7 @@ extern const OptionDef options[];
 extern const HWAccel hwaccels[];
 extern int hwaccel_lax_profile_check;
 extern AVBufferRef *hw_device_ctx;
+extern HWDevice *filter_hw_device;
 
 void reset_options(OptionsContext *o);
 void show_usage(void);
diff --git a/avtools/avconv_filter.c b/avtools/avconv_filter.c
index e53dcd271..884478da2 100644
--- a/avtools/avconv_filter.c
+++ b/avtools/avconv_filter.c
@@ -711,9 +711,15 @@ int configure_filtergraph(FilterGraph *fg)
 if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, , 
)) < 0)
 goto fail;
 
-if (hw_device_ctx) {
+if (filter_hw_device || hw_device_ctx) {
+AVBufferRef *device = filter_hw_device ? filter_hw_device->device_ref
+   : hw_device_ctx;
 for (i = 0; i < fg->graph->nb_filters; i++) {
-fg->graph->filters[i]->hw_device_ctx = 
av_buffer_ref(hw_device_ctx);
+fg->graph->filters[i]->hw_device_ctx = av_buffer_ref(device);
+if (!fg->graph->filters[i]->hw_device_ctx) {
+ret = AVERROR(ENOMEM);
+goto fail;
+}
 }
 }
 
diff --git a/avtools/avconv_opt.c b/avtools/avconv_opt.c
index e970c8e46..cdc980870 100644
--- a/avtools/avconv_opt.c
+++ b/avtools/avconv_opt.c
@@ -80,6 +80,7 @@ const HWAccel hwaccels[] = {
 };
 int hwaccel_lax_profile_check = 0;
 AVBufferRef *hw_device_ctx;
+HWDevice *filter_hw_device;
 
 char *vstats_filename;
 
@@ -369,6 +370,24 @@ static int opt_init_hw_device(void *optctx, const char 
*opt, const char *arg)
 }
 }
 
+static int opt_filter_hw_device(void *optctx, const char *opt, const char *arg)
+{
+int err;
+if (filter_hw_device) {
+av_log(NULL, AV_LOG_ERROR, "Only one filter device can be used.\n");
+return AVERROR(EINVAL);
+}
+filter_hw_device = hw_device_get_by_name(arg);
+if (!filter_hw_device) {
+err = hw_device_init_from_string(arg, _hw_device);
+if (err < 0) {
+av_log(NULL, AV_LOG_ERROR, "Invalid filter device %s.\n", arg);
+return AVERROR_UNKNOWN;
+}
+}
+return 0;
+}
+
 /**
  * Parse a metadata specifier passed as 'arg' parameter.
  * @param arg  metadata string to parse
@@ -2775,6 +2794,8 @@ const OptionDef options[] = {
 
 { "init_hw_device", HAS_ARG | OPT_EXPERT, { .func_arg = opt_init_hw_device 
},
 "initialise hardware device", "args" },
+{ "filter_hw_device", HAS_ARG | OPT_EXPERT, { .func_arg = 
opt_filter_hw_device },
+"set hardware device used when filtering", "device" },
 
 { NULL, },
 };
diff --git a/doc/avconv.texi b/doc/avconv.texi
index 7bcb78797..2837e30f3 100644
--- a/doc/avconv.texi
+++ b/doc/avconv.texi
@@ -644,6 +644,17 @@ deriving it from the existing device with the name 
@var{source}.
 @item -init_hw_device list
 List all hardware device types supported in this build of avconv.
 
+@item -filter_hw_device @var{name}
+Pass the hardware device called @var{name} to all filters in any filter graph.
+This can be used to set the device to upload to with the @code{hwupload} 
filter,
+or the device to map to with the @code{hwmap} filter.  Other filters may also
+make use of this parameter when they require a hardware device.  Note that this
+is typically only required when the input is not already in hardware frames -
+when it is, filters will derive the device they require from the context of the
+frames they receive as input.
+
+This is a global setting, so all filters will receive the same device.
+
 @item -hwaccel[:@var{stream_specifier}] @var{hwaccel} (@emph{input,per-stream})
 Use hardware acceleration to decode the matching stream(s). The allowed values
 of @var{hwaccel} are:
-- 
2.11.0

___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

[libav-devel] [PATCH 5/9] hwcontext_qsv: Implement mapping frames to the child device type

2017-04-23 Thread Mark Thompson
---
Now uses frame context derivation, so should properly support DXVA2 (previously 
it didn't look like a fixed-size pool, but that didn't actually matter for some 
use-cases).

It feels like the MemId stuff should be done more consistently, but actually 
every use is slightly different so the crazy casts are staying for now.


 libavutil/hwcontext_qsv.c | 88 +--
 1 file changed, 86 insertions(+), 2 deletions(-)

diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index f981e6e53..3ff6ccc28 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -577,13 +577,62 @@ static int qsv_transfer_get_formats(AVHWFramesContext 
*ctx,
 return 0;
 }
 
+static int qsv_frames_derive_from(AVHWFramesContext *dst_ctx,
+  AVHWFramesContext *src_ctx, int flags)
+{
+AVQSVFramesContext *src_hwctx = src_ctx->hwctx;
+int i;
+
+switch (dst_ctx->device_ctx->type) {
+#if CONFIG_VAAPI
+case AV_HWDEVICE_TYPE_VAAPI:
+{
+AVVAAPIFramesContext *dst_hwctx = dst_ctx->hwctx;
+dst_hwctx->surface_ids = av_mallocz_array(src_hwctx->nb_surfaces,
+  
sizeof(*dst_hwctx->surface_ids));
+if (!dst_hwctx->surface_ids)
+return AVERROR(ENOMEM);
+for (i = 0; i < src_hwctx->nb_surfaces; i++)
+dst_hwctx->surface_ids[i] =
+*(VASurfaceID*)src_hwctx->surfaces[i].Data.MemId;
+dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
+}
+break;
+#endif
+#if CONFIG_DXVA2
+case AV_HWDEVICE_TYPE_DXVA2:
+{
+AVDXVA2FramesContext *dst_hwctx = dst_ctx->hwctx;
+dst_hwctx->surfaces = av_mallocz_array(src_hwctx->nb_surfaces,
+   
sizeof(*dst_hwctx->surfaces));
+if (!dst_hwctx->surfaces)
+return AVERROR(ENOMEM);
+for (i = 0; i < src_hwctx->nb_surfaces; i++)
+dst_hwctx->surfaces[i] =
+(IDirect3DSurface9*)src_hwctx->surfaces[i].Data.MemId;
+dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
+if (src_hwctx->frame_type == 
MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
+dst_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget;
+else
+dst_hwctx->surface_type = DXVA2_VideoProcessorRenderTarget;
+}
+break;
+#endif
+default:
+return AVERROR(ENOSYS);
+}
+
+return 0;
+}
+
 static int qsv_map_from(AVHWFramesContext *ctx,
 AVFrame *dst, const AVFrame *src, int flags)
 {
 QSVFramesContext *s = ctx->internal->priv;
 mfxFrameSurface1 *surf = (mfxFrameSurface1*)src->data[3];
 AVHWFramesContext *child_frames_ctx;
-
+const AVPixFmtDescriptor *desc;
+uint8_t *child_data;
 AVFrame *dummy;
 int ret = 0;
 
@@ -591,6 +640,40 @@ static int qsv_map_from(AVHWFramesContext *ctx,
 return AVERROR(ENOSYS);
 child_frames_ctx = (AVHWFramesContext*)s->child_frames_ref->data;
 
+switch (child_frames_ctx->device_ctx->type) {
+#if CONFIG_VAAPI
+case AV_HWDEVICE_TYPE_VAAPI:
+child_data = (uint8_t*)(intptr_t)*(VASurfaceID*)surf->Data.MemId;
+break;
+#endif
+#if CONFIG_DXVA2
+case AV_HWDEVICE_TYPE_DXVA2:
+child_data = surf->Data.MemId;
+break;
+#endif
+default:
+return AVERROR(ENOSYS);
+}
+
+if (dst->format == child_frames_ctx->format) {
+ret = ff_hwframe_map_create(s->child_frames_ref,
+dst, src, NULL, NULL);
+if (ret < 0)
+return ret;
+
+dst->width   = src->width;
+dst->height  = src->height;
+dst->data[3] = child_data;
+
+return 0;
+}
+
+desc = av_pix_fmt_desc_get(dst->format);
+if (desc && desc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
+// This only supports mapping to software.
+return AVERROR(ENOSYS);
+}
+
 dummy = av_frame_alloc();
 if (!dummy)
 return AVERROR(ENOMEM);
@@ -603,7 +686,7 @@ static int qsv_map_from(AVHWFramesContext *ctx,
 dummy->format= child_frames_ctx->format;
 dummy->width = src->width;
 dummy->height= src->height;
-dummy->data[3]   = surf->Data.MemId;
+dummy->data[3]   = child_data;
 
 ret = av_hwframe_map(dst, dummy, flags);
 
@@ -1042,6 +1125,7 @@ const HWContextType ff_hwcontext_type_qsv = {
 .map_to = qsv_map_to,
 .map_from   = qsv_map_from,
 .frames_derive_to   = qsv_frames_derive_to,
+.frames_derive_from = qsv_frames_derive_from,
 
 .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_QSV, AV_PIX_FMT_NONE 
},
 };
-- 
2.11.0

___
libav-devel mailing list
libav-devel@libav.org

[libav-devel] [PATCH 2/9] hwcontext_qsv: Support derivation from child devices

2017-04-23 Thread Mark Thompson
---
Rearranged a bit to avoid some duplication.


 libavutil/hwcontext_qsv.c | 113 ++
 1 file changed, 84 insertions(+), 29 deletions(-)

diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index 3409e9b97..46636ef9e 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -792,21 +792,96 @@ static mfxIMPL choose_implementation(const char *device)
 return impl;
 }
 
-static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
- AVDictionary *opts, int flags)
+static int qsv_device_derive_from_child(AVHWDeviceContext *ctx,
+mfxIMPL implementation,
+AVHWDeviceContext *child_device_ctx,
+int flags)
 {
 AVQSVDeviceContext *hwctx = ctx->hwctx;
-QSVDevicePriv *priv;
-enum AVHWDeviceType child_device_type;
-AVDictionaryEntry *e;
+QSVDeviceContext   *s = ctx->internal->priv;
 
 mfxVersionver = { { 3, 1 } };
-mfxIMPL   impl;
 mfxHDLhandle;
 mfxHandleType handle_type;
 mfxStatus err;
 int ret;
 
+switch (child_device_ctx->type) {
+#if CONFIG_VAAPI
+case AV_HWDEVICE_TYPE_VAAPI:
+{
+AVVAAPIDeviceContext *child_device_hwctx = child_device_ctx->hwctx;
+handle_type = MFX_HANDLE_VA_DISPLAY;
+handle = (mfxHDL)child_device_hwctx->display;
+}
+break;
+#endif
+#if CONFIG_DXVA2
+case AV_HWDEVICE_TYPE_DXVA2:
+{
+AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx;
+handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
+handle = (mfxHDL)child_device_hwctx->devmgr;
+}
+break;
+#endif
+default:
+ret = AVERROR(ENOSYS);
+goto fail;
+}
+
+err = MFXInit(implementation, , >session);
+if (err != MFX_ERR_NONE) {
+av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session: "
+   "%d.\n", err);
+ret = AVERROR_UNKNOWN;
+goto fail;
+}
+
+err = MFXVideoCORE_SetHandle(hwctx->session, handle_type, handle);
+if (err != MFX_ERR_NONE) {
+av_log(ctx, AV_LOG_ERROR, "Error setting child device handle: "
+   "%d\n", err);
+ret = AVERROR_UNKNOWN;
+goto fail;
+}
+
+ret = qsv_device_init(ctx);
+if (ret < 0)
+goto fail;
+if (s->handle_type != handle_type) {
+av_log(ctx, AV_LOG_ERROR, "Error in child device handle setup: "
+   "type mismatch (%d != %d).\n", s->handle_type, handle_type);
+err = AVERROR_UNKNOWN;
+goto fail;
+}
+
+return 0;
+
+fail:
+if (hwctx->session)
+MFXClose(hwctx->session);
+return ret;
+}
+
+static int qsv_device_derive(AVHWDeviceContext *ctx,
+ AVHWDeviceContext *child_device_ctx, int flags)
+{
+return qsv_device_derive_from_child(ctx, MFX_IMPL_HARDWARE_ANY,
+child_device_ctx, flags);
+}
+
+static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
+ AVDictionary *opts, int flags)
+{
+QSVDevicePriv *priv;
+enum AVHWDeviceType child_device_type;
+AVHWDeviceContext *child_device;
+AVDictionaryEntry *e;
+
+mfxIMPL impl;
+int ret;
+
 priv = av_mallocz(sizeof(*priv));
 if (!priv)
 return AVERROR(ENOMEM);
@@ -830,32 +905,11 @@ static int qsv_device_create(AVHWDeviceContext *ctx, 
const char *device,
 if (ret < 0)
 return ret;
 
-{
-AVHWDeviceContext  *child_device_ctx = 
(AVHWDeviceContext*)priv->child_device_ctx->data;
-#if CONFIG_VAAPI
-AVVAAPIDeviceContext *child_device_hwctx = child_device_ctx->hwctx;
-handle_type = MFX_HANDLE_VA_DISPLAY;
-handle = (mfxHDL)child_device_hwctx->display;
-#elif CONFIG_DXVA2
-AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx;
-handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
-handle = (mfxHDL)child_device_hwctx->devmgr;
-#endif
-}
+child_device = (AVHWDeviceContext*)priv->child_device_ctx->data;
 
 impl = choose_implementation(device);
 
-err = MFXInit(impl, , >session);
-if (err != MFX_ERR_NONE) {
-av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session\n");
-return AVERROR_UNKNOWN;
-}
-
-err = MFXVideoCORE_SetHandle(hwctx->session, handle_type, handle);
-if (err != MFX_ERR_NONE)
-return AVERROR_UNKNOWN;
-
-return 0;
+return qsv_device_derive_from_child(ctx, impl, child_device, 0);
 }
 
 const HWContextType ff_hwcontext_type_qsv = {
@@ -868,6 +922,7 @@ const HWContextType ff_hwcontext_type_qsv = {
 .frames_priv_size   = sizeof(QSVFramesContext),
 
 .device_create  = qsv_device_create,
+.device_derive  = qsv_device_derive,
 

[libav-devel] [PATCH] configure: Fix sem_timedwait probe

2017-04-23 Thread Luca Barbato
It requires pthreads.
---
 configure | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure b/configure
index e83a4cf697..dde172d011 100755
--- a/configure
+++ b/configure
@@ -4693,7 +4693,7 @@ if ! disabled pthreads && ! enabled w32threads; then
 fi
 
 enabled pthreads &&
-check_builtin sem_timedwait semaphore.h "sem_t *s; sem_init(s,0,0); 
sem_timedwait(s,0); sem_destroy(s)"
+check_builtin sem_timedwait semaphore.h "sem_t *s; sem_init(s,0,0); 
sem_timedwait(s,0); sem_destroy(s)" $pthreads_extralibs
 
 disabled  zlib || check_lib  zlib  zlib.h  zlibVersion -lz
 disabled bzlib || check_lib bzlib bzlib.h BZ2_bzlibVersion -lbz2
-- 
2.11.1

___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Re: [libav-devel] [PATCH] configure: Escape elements being filtered

2017-04-23 Thread Luca Barbato
On 4/6/17 6:14 PM, Luca Barbato wrote:
> The function is used to filter out ldflags arguments that may contain $.
> Update filter() as well to be consistent.
> ---
> 
> Ping in form of updated patch.
> 
>  configure | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/configure b/configure
> index ecc7784..4458df3 100755
> --- a/configure
> +++ b/configure
> @@ -433,7 +433,7 @@ filter(){
>  pat=$1
>  shift
>  for v; do
> -eval "case $v in $pat) printf '%s ' $v ;; esac"
> +eval "case '$v' in $pat) printf '%s ' '$v' ;; esac"
>  done
>  }
> 
> @@ -441,7 +441,7 @@ filter_out(){
>  pat=$1
>  shift
>  for v; do
> -eval "case $v in $pat) ;; *) printf '%s ' $v ;; esac"
> +eval "case '$v' in $pat) ;; *) printf '%s ' '$v' ;; esac"
>  done
>  }
> 

Ping.

___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Re: [libav-devel] [PATCH] avprobe: Handle invalid values for the color description

2017-04-23 Thread Luca Barbato
On 4/18/17 7:11 PM, Luca Barbato wrote:
> On 17/04/2017 18:04, Vittorio Giovara wrote:
>> On Mon, Apr 17, 2017 at 9:48 AM, Luca Barbato  wrote:
>>> print_str() cannot print NULL.
>>>
>>> Bug-Id: 1040
>>> CC: libav-sta...@libav.org
>>> ---
>>>  avtools/avprobe.c | 36 +++-
>>>  1 file changed, 31 insertions(+), 5 deletions(-)
>>
>> I'm not sure about this. First of all these values are not invalid but
>> simply unknown.
> 
> So is it ok for you if I use Unknown (something) ?
> 

Ping on that, I'd push this and change it back if there consensus on how
those functions should behave tilts on having "unknown" returned.

lu

___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Re: [libav-devel] [PATCH] vc1dec: raise an error if sprite picture data is missing

2017-04-23 Thread Luca Barbato
On 4/23/17 1:19 AM, Sean McGovern wrote:
> Bug-Id: 1013
> CC: libav-sta...@libav.org
> ---
>  libavcodec/vc1dec.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c
> index 89b4f4b..51745c1 100644
> --- a/libavcodec/vc1dec.c
> +++ b/libavcodec/vc1dec.c
> @@ -270,7 +270,7 @@ static int vc1_decode_sprites(VC1Context *v, 
> GetBitContext* gb)
>  
>  vc1_parse_sprites(v, gb, );
>  
> -if (!s->current_picture.f->data[0]) {
> +if (!s->current_picture.f || !s->current_picture.f->data[0]) {
>  av_log(avctx, AV_LOG_ERROR, "Got no sprites\n");
>  return -1;
>  }
> 

I'm not against it.

lu
___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel