Re: [FFmpeg-devel] [PATCH] ffmpeg_qsv.c: Init an hwframes_context for decoder instead of encoder

2017-01-21 Thread Huang, Zhengxu

在 2017/1/20 18:05, wm4 写道:


On Fri, 20 Jan 2017 17:41:01 +0800
"Huang, Zhengxu" <zhengxu.maxw...@gmail.com> wrote:


 From 2149f87637ab941be14828f7ae2c224908784c7d Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxw...@gmail.com>
Date: Wed, 4 Jan 2017 16:43:43 +0800
Subject: [PATCH] ffmpeg_qsv.c: Init an hwframes_context for decoder instead of
  encoder.

We consider that encoder is the last stage in the pipeline. Thinking
about filters, they get hwframes_context from their inputs. Likewise,
encoder should get hwframes_context from its input instead creating a
new faker one. Encoder can get acuurate parameters by doing so.

the idea is right. What ffmpeg.c does is a gross hack that avconv
doesn't have or need. Ideally, ffmpeg_qsv.c would look like avconv's
equivalent file:

https://git.libav.org/?p=libav.git;a=blob;f=avconv_qsv.c;hb=HEAD

This patch seem to be the right way to fix this issue.  Maybe it should be
merged ASAP after validation.


(It's quite possible that this still lacks avconv changes needed for
this, and which were either skipped during merge, or not merged yet.)


Signed-off-by: ChaoX A Liu <chaox.a@gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxw...@gmail.com>
Signed-off-by: Andrew, Zhang <huazh...@gmail.com>
---
  ffmpeg_qsv.c | 95 +++-
  1 file changed, 43 insertions(+), 52 deletions(-)

diff --git a/ffmpeg_qsv.c b/ffmpeg_qsv.c
index 86824b6..8cedb7e 100644
--- a/ffmpeg_qsv.c
+++ b/ffmpeg_qsv.c
@@ -81,25 +81,26 @@ int qsv_init(AVCodecContext *s)
  return ret;
  }
  
-av_buffer_unref(>hw_frames_ctx);

-ist->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx);
-if (!ist->hw_frames_ctx)
-return AVERROR(ENOMEM);
-
-frames_ctx   = (AVHWFramesContext*)ist->hw_frames_ctx->data;
-frames_hwctx = frames_ctx->hwctx;
-
-frames_ctx->width = FFALIGN(s->coded_width,  32);
-frames_ctx->height= FFALIGN(s->coded_height, 32);
-frames_ctx->format= AV_PIX_FMT_QSV;
-frames_ctx->sw_format = s->sw_pix_fmt;
-frames_ctx->initial_pool_size = 64;
-frames_hwctx->frame_type  = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
-
-ret = av_hwframe_ctx_init(ist->hw_frames_ctx);
-if (ret < 0) {
-av_log(NULL, AV_LOG_ERROR, "Error initializing a QSV frame pool\n");
-return ret;
+if(!ist->hw_frames_ctx) {

Why this check? It's pointless - hw_frames_ctx is unset when get_format
is called.

It also changes indentation, which makes reviewing harder.


+ist->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx);
+if (!ist->hw_frames_ctx)
+return AVERROR(ENOMEM);
+
+frames_ctx   = (AVHWFramesContext*)ist->hw_frames_ctx->data;
+frames_hwctx = frames_ctx->hwctx;
+
+frames_ctx->width = FFALIGN(s->coded_width,  32);
+frames_ctx->height= FFALIGN(s->coded_height, 32);
+frames_ctx->format= AV_PIX_FMT_QSV;
+frames_ctx->sw_format = s->sw_pix_fmt;
+frames_ctx->initial_pool_size = 64;
+frames_hwctx->frame_type  = 
MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
+
+ret = av_hwframe_ctx_init(ist->hw_frames_ctx);
+if (ret < 0) {
+av_log(NULL, AV_LOG_ERROR, "Error initializing a QSV frame 
pool\n");
+return ret;
+}
  }
  
  ist->hwaccel_get_buffer = qsv_get_buffer;

@@ -114,9 +115,8 @@ int qsv_transcode_init(OutputStream *ost)
  const enum AVPixelFormat *pix_fmt;
  
  int err, i;

-AVBufferRef *encode_frames_ref = NULL;
-AVHWFramesContext *encode_frames;
-AVQSVFramesContext *qsv_frames;
+AVHWFramesContext *frames_ctx;
+AVQSVFramesContext *frames_hwctx;
  
  /* check if the encoder supports QSV */

  if (!ost->enc->pix_fmts)
@@ -150,42 +150,33 @@ int qsv_transcode_init(OutputStream *ost)
  if (!hw_device_ctx) {
  err = qsv_device_init(ist);
  if (err < 0)
-goto fail;
-}
-
-// This creates a dummy hw_frames_ctx for the encoder to be
-// suitably initialised.  It only contains one real frame, so
-// hopefully doesn't waste too much memory.
-
-encode_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx);
-if (!encode_frames_ref) {
-err = AVERROR(ENOMEM);
-goto fail;
+return err;
  }
-encode_frames = (AVHWFramesContext*)encode_frames_ref->data;
-qsv_frames = encode_frames->hwctx;
  
-encode_frames->width = FFALIGN(ist->resample_width,  32);

-encode_frames->height= FFALIGN(ist->resample_height, 32);
-encode_frames->format= AV_PIX_FMT_QSV;
-encode_frames->sw_format = AV_PIX_FMT_NV12;
-encode_frames->initial_po

Re: [FFmpeg-devel] [PATCH] lavformat/utils: Fix a memleak that st->codec->hw_frames_ctx

2017-01-21 Thread Huang, Zhengxu

在 2017/1/20 17:56, wm4 写道:


On Fri, 20 Jan 2017 17:35:33 +0800
Chao Liu  wrote:


Have you ever used valgrind? Please just run the command below:
valgrind --leak-check=full --log-file=out.log ffmpeg -hwaccel qsv
-qsv_device /dev/dri/renderD128 -c:v h264_qsv -i a.h264 -c:v h264_qsv -b:v
2M  -y out.h264

See line 3323 of ffmpeg.c,
 ret = avcodec_copy_context(ost->st->codec, ost->enc_ctx);
and see what have been done in avcodec_copy_context:
 if (src->hw_frames_ctx) {
 dest->hw_frames_ctx = av_buffer_ref(src->hw_frames_ctx);
 if (!dest->hw_frames_ctx)
 goto fail;
 }
However, that is not freed when calling avformat_free_context.


The hardware decoder should never be created in the demuxer.
I quite can't understand why this related to the "demuxer". Firstly we 
should admint that if

there is a memleak issue. Secondly, how or where to free the hw_frames_ctx.

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] ffmpeg_qsv.c: Init an hwframes_context for decoder instead of encoder

2017-01-20 Thread Huang, Zhengxu


From 2149f87637ab941be14828f7ae2c224908784c7d Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxw...@gmail.com>
Date: Wed, 4 Jan 2017 16:43:43 +0800
Subject: [PATCH] ffmpeg_qsv.c: Init an hwframes_context for decoder instead of
 encoder.

We consider that encoder is the last stage in the pipeline. Thinking
about filters, they get hwframes_context from their inputs. Likewise,
encoder should get hwframes_context from its input instead creating a
new faker one. Encoder can get acuurate parameters by doing so.

Signed-off-by: ChaoX A Liu <chaox.a@gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxw...@gmail.com>
Signed-off-by: Andrew, Zhang <huazh...@gmail.com>
---
 ffmpeg_qsv.c | 95 +++-
 1 file changed, 43 insertions(+), 52 deletions(-)

diff --git a/ffmpeg_qsv.c b/ffmpeg_qsv.c
index 86824b6..8cedb7e 100644
--- a/ffmpeg_qsv.c
+++ b/ffmpeg_qsv.c
@@ -81,25 +81,26 @@ int qsv_init(AVCodecContext *s)
 return ret;
 }
 
-av_buffer_unref(>hw_frames_ctx);
-ist->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx);
-if (!ist->hw_frames_ctx)
-return AVERROR(ENOMEM);
-
-frames_ctx   = (AVHWFramesContext*)ist->hw_frames_ctx->data;
-frames_hwctx = frames_ctx->hwctx;
-
-frames_ctx->width = FFALIGN(s->coded_width,  32);
-frames_ctx->height= FFALIGN(s->coded_height, 32);
-frames_ctx->format= AV_PIX_FMT_QSV;
-frames_ctx->sw_format = s->sw_pix_fmt;
-frames_ctx->initial_pool_size = 64;
-frames_hwctx->frame_type  = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
-
-ret = av_hwframe_ctx_init(ist->hw_frames_ctx);
-if (ret < 0) {
-av_log(NULL, AV_LOG_ERROR, "Error initializing a QSV frame pool\n");
-return ret;
+if(!ist->hw_frames_ctx) {
+ist->hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx);
+if (!ist->hw_frames_ctx)
+return AVERROR(ENOMEM);
+
+frames_ctx   = (AVHWFramesContext*)ist->hw_frames_ctx->data;
+frames_hwctx = frames_ctx->hwctx;
+
+frames_ctx->width = FFALIGN(s->coded_width,  32);
+frames_ctx->height= FFALIGN(s->coded_height, 32);
+frames_ctx->format= AV_PIX_FMT_QSV;
+frames_ctx->sw_format = s->sw_pix_fmt;
+frames_ctx->initial_pool_size = 64;
+frames_hwctx->frame_type  = 
MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
+
+ret = av_hwframe_ctx_init(ist->hw_frames_ctx);
+if (ret < 0) {
+av_log(NULL, AV_LOG_ERROR, "Error initializing a QSV frame 
pool\n");
+return ret;
+}
 }
 
 ist->hwaccel_get_buffer = qsv_get_buffer;
@@ -114,9 +115,8 @@ int qsv_transcode_init(OutputStream *ost)
 const enum AVPixelFormat *pix_fmt;
 
 int err, i;
-AVBufferRef *encode_frames_ref = NULL;
-AVHWFramesContext *encode_frames;
-AVQSVFramesContext *qsv_frames;
+AVHWFramesContext *frames_ctx;
+AVQSVFramesContext *frames_hwctx;
 
 /* check if the encoder supports QSV */
 if (!ost->enc->pix_fmts)
@@ -150,42 +150,33 @@ int qsv_transcode_init(OutputStream *ost)
 if (!hw_device_ctx) {
 err = qsv_device_init(ist);
 if (err < 0)
-goto fail;
-}
-
-// This creates a dummy hw_frames_ctx for the encoder to be
-// suitably initialised.  It only contains one real frame, so
-// hopefully doesn't waste too much memory.
-
-encode_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx);
-if (!encode_frames_ref) {
-err = AVERROR(ENOMEM);
-goto fail;
+return err;
 }
-encode_frames = (AVHWFramesContext*)encode_frames_ref->data;
-qsv_frames = encode_frames->hwctx;
 
-encode_frames->width = FFALIGN(ist->resample_width,  32);
-encode_frames->height= FFALIGN(ist->resample_height, 32);
-encode_frames->format= AV_PIX_FMT_QSV;
-encode_frames->sw_format = AV_PIX_FMT_NV12;
-encode_frames->initial_pool_size = 1;
+ist->dec_ctx->pix_fmt = AV_PIX_FMT_QSV;
+ist->resample_pix_fmt = AV_PIX_FMT_QSV;
+ist->hw_frames_ctx= av_hwframe_ctx_alloc(hw_device_ctx);
+if (!ist->hw_frames_ctx)
+return AVERROR(ENOMEM);
 
-qsv_frames->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
+frames_ctx   = (AVHWFramesContext*)ist->hw_frames_ctx->data;
+frames_hwctx = frames_ctx->hwctx;
 
-err = av_hwframe_ctx_init(encode_frames_ref);
-if (err < 0)
-goto fail;
+frames_ctx->width = FFALIGN(ist->resample_width,  32);
+frames_ctx->height= FFALIGN(ist->resample_height, 32);
+frames_ctx->format= AV_PIX_FMT_QSV;
+frames_ctx->sw

[FFmpeg-devel] [PATCH] lavformat/utils: Fix a memleak that st->codec->hw_frames_ctx

2017-01-19 Thread Huang, Zhengxu


From 9ceb2ac6a89246f2e686eb3ad3448fbaff5328f7 Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxw...@gmail.com>
Date: Fri, 13 Jan 2017 10:33:05 +0800
Subject: [PATCH] lavformat/utils: Fix a memleak that st->codec->hw_frames_ctx
 is not released.

Signed-off-by: ChaoX A Liu <chaox.a@gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxw...@gmail.com>
Signed-off-by: Andrew, Zhang <huazh...@gmail.com>
---
 libavformat/utils.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libavformat/utils.c b/libavformat/utils.c
index d5dfca7..cadec15 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -4127,6 +4127,7 @@ static void free_stream(AVStream **pst)
 FF_DISABLE_DEPRECATION_WARNINGS
 av_freep(>codec->extradata);
 av_freep(>codec->subtitle_header);
+av_buffer_unref(>codec->hw_frames_ctx);
 av_freep(>codec);
 FF_ENABLE_DEPRECATION_WARNINGS
 #endif
-- 
1.8.3.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Re: [FFmpeg-devel] [PATCH 1/2 V2] libavcodec/qsvdec: Fix the QSV decoder can't work when using system memory

2017-01-16 Thread Huang, Zhengxu

在 2017/1/12 5:00, Mark Thompson 写道:


On 09/01/17 02:05, Huang, Zhengxu wrote:

 From 37629f14294125c7396e5e12970d75e895b1caba Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxw...@gmail.com>
Date: Mon, 19 Dec 2016 01:27:06 -0500
Subject: [PATCH 1/2] libavcodec/qsvdec: Fix the QSV decoder can't work when
  using system memory

Description: ./ffmpeg -c:v h264_qsv -i in -c:v h264 output.h264 does not
work because the qsv decode will failed.

Yes it does!  (Or at least, it works for me?)  In the absence of a provided 
device handle the dispatcher finds a device to use.
Our test environment is the MSS 16.5 PV1 and the decode indeed can't 
work in the system memory.


Now I can see that it is likely to run into exactly the same device-selection 
issues as were being fixed in other patch, but I don't see how this is fixing 
it.  You are not passing anything to av_hwdevice_ctx_create(), so it will be 
going through exactly the same set of possible device nodes as ffmpeg did and 
will therefore fail to find the device in exactly the same way.
So, to properly fix the problem I think you are having (but correct me if this 
is wrong), you really want the -qsv_device option added to ffmpeg to apply to 
this case in libavcodec as well?  That is, we get the qsv_device in ffmpeg into 
libavcodec somehow and then use it with the code below.  (Patch itself 
implementing that looks mostly fine, but I would prefer to get the methodology 
resolved first.  Similarly for the matching patch to the encoder.)
yes, you are right!  We do need to add the qsv_device for the 
encode/decode to choose a device handle.  The user can assign the device 
using the

below command:

/./ffmpeg -qsv_dev device -c:v h264_qsv -i in -c:v h264 output.h264/

/ ./ffmpeg -c:v h264 -i in  -qsv_dev device-c:v h264_qsv  output.h264/

Using the qsv_dev inorder to avoid conflicting with the global option 
"qsv_device".


Attached the updated patches.

Thanks.


- Mark



Root cuase: when using the system rather than the 
hwaccel,ff_qsv_init_internal_session
does not set the vaDisplay handle for the session. The qsv decode will failed.

Solution: when creating the internal session , call the HwContext API to get 
session and
release all resource when close the decoder.

Signed-off-by: ChaoX A Liu <chaox.a@gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxw...@gmail.com>
Signed-off-by: Andrew, Zhang <huazh...@gmail.com>
---
  libavcodec/qsv.c  |  6 ++---
  libavcodec/qsv_internal.h |  5 
  libavcodec/qsvdec.c   | 59 ---
  libavcodec/qsvdec.h   |  1 +
  4 files changed, 65 insertions(+), 6 deletions(-)

diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index aac6ce6..a932fc3 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -120,7 +120,7 @@ int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t 
*fourcc)
  }
  }
  
-static int qsv_load_plugins(mfxSession session, const char *load_plugins,

+int ff_qsv_load_plugins(mfxSession session, const char *load_plugins,
  void *logctx)
  {
  if (!load_plugins || !*load_plugins)
@@ -185,7 +185,7 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, 
mfxSession *session,
  return ff_qsv_error(ret);
  }
  
-ret = qsv_load_plugins(*session, load_plugins, avctx);

+ret = ff_qsv_load_plugins(*session, load_plugins, avctx);
  if (ret < 0) {
  av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
  return ret;
@@ -329,7 +329,7 @@ int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, 
mfxSession *psession,
  }
  }
  
-ret = qsv_load_plugins(session, load_plugins, avctx);

+ret = ff_qsv_load_plugins(session, load_plugins, avctx);
  if (ret < 0) {
  av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
  return ret;
diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
index 5d2a216..13f23ef 100644
--- a/libavcodec/qsv_internal.h
+++ b/libavcodec/qsv_internal.h
@@ -50,6 +50,10 @@ typedef struct QSVFrame {
  struct QSVFrame *next;
  } QSVFrame;
  
+typedef struct QSVDeviceContext {

+AVBufferRef *hw_device_ctx;
+} QSVDeviceContext;
+
  typedef struct QSVFramesContext {
  AVBufferRef *hw_frames_ctx;
  mfxFrameInfo info;
@@ -73,5 +77,6 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, 
mfxSession *session,
  int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, mfxSession *session,
QSVFramesContext *qsv_frames_ctx,
const char *load_plugins, int opaque);
+int ff_qsv_load_plugins(mfxSession session, const char *load_plugins, void 
*logctx);
  
  #endif /* AVCODEC_QSV_INTERNAL_H */

diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
index 258042d..ccd5e26 100644
--- a/libavcodec/qsvdec.c
+++ b/libavcodec/qsvdec.c
@@ -41,6 +41,58 @@
  #i

Re: [FFmpeg-devel] [PATCH 2/2 V2] libavcodec/qsvenc: Fix the encode part hwaccle issue when using system memory

2017-01-16 Thread Huang, Zhengxu

在 2017/1/9 10:10, Huang, Zhengxu 写道:




From 8466186d4622f760194edd62f7779a0ab8a230d2 Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxw...@gmail.com>
Date: Mon, 19 Dec 2016 03:39:39 -0500
Subject: [PATCH 2/2] libavcodec/qsvenc: Fix the encode part hwaccle issue when
 using system memory

Description: when using system memory the encode actually uses the
PARTIAL_ACCELERATION which means the SW encoder of MSDK. And the performance
will quite poor compared with the HW MSDK.
eg: ./ffmpeg -c:v h264 -i in -c:v h264_qsv  output.h264

Fix: Use the HWContext to get the vaDisplay and configure the encode to HW
mode. The performance will be improved significantly

Signed-off-by: ChaoX A Liu <chaox.a@gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxw...@gmail.com>
Signed-off-by: Andrew, Zhang <huazh...@gmail.com>
---
 libavcodec/qsvenc.c | 65 +++--
 libavcodec/qsvenc.h |  4 +++-
 2 files changed, 66 insertions(+), 3 deletions(-)

diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index ac443c1..f61aad7 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -651,6 +651,66 @@ static int qsv_init_opaque_alloc(AVCodecContext *avctx, 
QSVEncContext *q)
 return 0;
 }
 
+static int qsv_init_internal_session(AVCodecContext *avctx, mfxSession 
*session,
+ QSVEncContext *q, const char *load_plugins)
+{
+mfxIMPL impl   = MFX_IMPL_AUTO_ANY;
+const char *desc;
+int ret;
+AVHWDeviceContext *device_hw;
+AVQSVDeviceContext *hwctx;
+AVBufferRef *hw_device_ctx;
+AVDictionary *dict = NULL;
+
+if (q->dev_name) {
+ret = av_dict_set(, "child_device", q->dev_name, 0);
+if (ret < 0)
+return ret;
+}
+
+ret = av_hwdevice_ctx_create(_device_ctx, AV_HWDEVICE_TYPE_QSV, NULL, 
dict, 0);
+if (ret < 0) {
+av_log(NULL, AV_LOG_ERROR, "Failed to create a QSV device\n");
+av_dict_free();
+return ret;
+}
+av_dict_free();
+
+device_hw = (AVHWDeviceContext*)hw_device_ctx->data;
+hwctx = device_hw->hwctx;
+
+*session = hwctx->session;
+
+q->device_ctx.hw_device_ctx = hw_device_ctx;
+
+ret = ff_qsv_load_plugins(*session, load_plugins, avctx);
+if (ret < 0) {
+av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
+return ret;
+}
+MFXQueryIMPL(*session, );
+
+switch (MFX_IMPL_BASETYPE(impl)) {
+case MFX_IMPL_SOFTWARE:
+desc = "software";
+break;
+case MFX_IMPL_HARDWARE:
+case MFX_IMPL_HARDWARE2:
+case MFX_IMPL_HARDWARE3:
+case MFX_IMPL_HARDWARE4:
+desc = "hardware accelerated";
+break;
+default:
+desc = "unknown";
+}
+
+av_log(avctx, AV_LOG_VERBOSE,
+   "Initialized an internal MFX session using %s implementation\n",
+   desc);
+
+return 0;
+}
+
 static int qsvenc_init_session(AVCodecContext *avctx, QSVEncContext *q)
 {
 int ret;
@@ -673,12 +733,12 @@ static int qsvenc_init_session(AVCodecContext *avctx, 
QSVEncContext *q)
 
 q->session = q->internal_session;
 } else {
-ret = ff_qsv_init_internal_session(avctx, >internal_session,
+ret = qsv_init_internal_session(avctx, >session, q,
q->load_plugins);
 if (ret < 0)
 return ret;
 
-q->session = q->internal_session;
+   // q->session = q->internal_session;
 }
 
 return 0;
@@ -1088,6 +1148,7 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext 
*q)
 q->internal_session = NULL;
 
 av_buffer_unref(>frames_ctx.hw_frames_ctx);
+av_buffer_unref(>device_ctx.hw_device_ctx);
 av_freep(>frames_ctx.mids);
 q->frames_ctx.nb_mids = 0;
 
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
index 361d933..42d3ed5 100644
--- a/libavcodec/qsvenc.h
+++ b/libavcodec/qsvenc.h
@@ -71,6 +71,7 @@
 { "adaptive_b", "Adaptive B-frame placement", 
OFFSET(qsv.adaptive_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1,  1, VE 
}, \
 { "b_strategy", "Strategy to choose between I/P/B-frames", 
OFFSET(qsv.b_strategy),AV_OPT_TYPE_INT, { .i64 = -1 }, -1,  1, VE 
}, \
 { "cavlc",  "Enable CAVLC",   
OFFSET(qsv.cavlc),  AV_OPT_TYPE_INT, { .i64 = 0 },   0,  1, VE 
}, \
+{ "qsv_dev","Set QSV hardware device (DirectX adapter index, DRM path 
or X11 display name)", OFFSET(qsv.dev_name), AV_OPT_TYPE_STRING, { .str = "" }, 
0, 128, VE }, \
 
 typedef int SetEncodeCtrlCB (AVCodecContext *avctx,
  const AVFrame *frame, m

Re: [FFmpeg-devel] [PATCH] libavutil/hwcontext_qsv: Command line using hwaccel 'QSV' doesn't work

2017-01-08 Thread Huang, Zhengxu

在 2017/1/8 7:36, Mark Thompson 写道:

On 06/01/17 06:37, Huang, Zhengxu wrote:

Hi

According to the suggestion update the patch.

thanks.


 From 4beadd3c84c797a56c4f375458d0a1e9d9b233c8 Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxw...@gmail.com>
Date: Thu, 5 Jan 2017 14:48:06 +0800
Subject: [PATCH] ffmpeg_qsv: Add an option "qsv_child_device" to choose an
  proper node for QSV child device(vaapi or dxva2).

Reason: For some cases, such as 2 or more graphics card existing, the
default command line may fail because ffmpeg open a wrong device node:
 ffmpeg -hwaccel qsv -c:v h264_qsv -i test.264 -c:v h264_qsv out.264
Let user to choose the proper one by running like below:
 ffmpeg -hwaccel qsv -qsv_child_device /dev/dri/renderD128 -c:v h264_qsv \
-i test.264 -c:v h264_qsv out.264

I think it should just be "qsv_device".  It is the device being used by qsv, 
the fact that it is a child device of another kind (dxva or vaapi) wrapped inside the 
hwcontext infrastructure isn't really relevant to the ffmpeg utility.


Signed-off-by: ChaoX A Liu <chaox.a....@gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxw...@gmail.com>
Signed-off-by: Andrew, Zhang <huazh...@gmail.com>
---
  ffmpeg.h |  3 +++
  ffmpeg_opt.c |  5 +
  ffmpeg_qsv.c | 11 ++-
  3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/ffmpeg.h b/ffmpeg.h
index ebe5bf0..91a 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -602,6 +602,9 @@ extern const OptionDef options[];
  extern const HWAccel hwaccels[];
  extern int hwaccel_lax_profile_check;
  extern AVBufferRef *hw_device_ctx;
+#if CONFIG_QSV
+extern char *qsv_child_device;
+#endif
  
  
  void term_init(void);

diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c
index 6862456..7fd08a2 100644
--- a/ffmpeg_opt.c
+++ b/ffmpeg_opt.c
@@ -3679,5 +3679,10 @@ const OptionDef options[] = {
  "set VAAPI hardware device (DRM path or X11 display name)", "device" 
},
  #endif
  
+#if CONFIG_QSV

+{ "qsv_child_device", HAS_ARG | OPT_STRING | OPT_EXPERT, { 
_child_device },
+"set QSV child device (DRM path or DXVA)", "device"},

An X11 display will still work here.  Also, maybe clarify that the DXVA case is 
a DirectX adapter index?

"set QSV hardware device (DirectX adapter index, DRM path or X11 display 
name)", say.


+#endif
+
  { NULL, },
  };
diff --git a/ffmpeg_qsv.c b/ffmpeg_qsv.c
index 68ff5bd..5a6db20 100644
--- a/ffmpeg_qsv.c
+++ b/ffmpeg_qsv.c
@@ -28,6 +28,8 @@
  
  #include "ffmpeg.h"
  
+char *qsv_child_device = NULL;

+
  static int qsv_get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
  {
  InputStream *ist = s->opaque;
@@ -44,9 +46,16 @@ static void qsv_uninit(AVCodecContext *s)
  static int qsv_device_init(InputStream *ist)
  {
  int err;
+AVDictionary *dict = NULL;
+
+if (qsv_child_device) {
+err = av_dict_set(, "child_device", qsv_child_device, 0);
+if (err < 0)
+return err;
+}
  
  err = av_hwdevice_ctx_create(_device_ctx, AV_HWDEVICE_TYPE_QSV,

- ist->hwaccel_device, NULL, 0);
+ ist->hwaccel_device, dict, 0);
  if (err < 0) {
  av_log(NULL, AV_LOG_ERROR, "Error creating a QSV device\n");
  return err;
--
1.8.3.1


Patch otherwise ok.

Hi Mark,
 thanks a lot.
 update the above two questions you mentioned.

Thanks,

- Mark
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


From ce4bcaf1cf4010bb5ad9ff97d6df803a629d2e88 Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxw...@gmail.com>
Date: Thu, 5 Jan 2017 14:48:06 +0800
Subject: [PATCH] ffmpeg_qsv: Add an option "qsv_device" to choose an proper
 node for QSV child device(vaapi or dxva2).

Reason: For some cases, such as 2 or more graphics card existing, the
default command line may fail because ffmpeg open a wrong device node:
ffmpeg -hwaccel qsv -c:v h264_qsv -i test.264 -c:v h264_qsv out.264
Let user to choose the proper one by running like below:
ffmpeg -hwaccel qsv -qsv_device /dev/dri/renderD128 -c:v h264_qsv \
-i test.264 -c:v h264_qsv out.264

Signed-off-by: ChaoX A Liu <chaox.a@gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxw...@gmail.com>
Signed-off-by: Andrew, Zhang <huazh...@gmail.com>
---
 ffmpeg.h |  3 +++
 ffmpeg_opt.c |  5 +
 ffmpeg_qsv.c | 19 ---
 3 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/ffmpeg.h b/ffmpeg.h
index ebe5bf0..081913b 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -602,6 +602,9 @@ extern const OptionDef options[];
 extern const HWAccel hwaccels[];
 extern int hwaccel_lax_profile_check;
 extern AVBufferRef *hw_device_ctx;
+#if CONFIG_QSV
+extern char *qsv_device;
+#endif

[FFmpeg-devel] [PATCH 2/2] libavcodec/qsvenc: Fix the encode part hwaccle issue when using system memory

2017-01-08 Thread Huang, Zhengxu


From 256dd95eded93894c01e67648eec41d05e35d64e Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxw...@gmail.com>
Date: Mon, 19 Dec 2016 03:39:39 -0500
Subject: [PATCH 2/2] libavcodec/qsvenc: Fix the encode part hwaccle issue when
 using system memory

Description: when using system memory the encode actually uses the
PARTIAL_ACCELERATION which means the SW encoder of MSDK. And the performance
will quite poor compared with the HW MSDK.
eg: ./ffmpeg -c:v h264 -i in -c:v h264_qsv  output.h264

Fix: Use the HWContext to get the vaDisplay and configure the encode to HW
mode. The performance will be improved significantly

Signed-off-by: ChaoX A Liu <chaox.a@gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxw...@gmail.com>
Signed-off-by: Andrew, Zhang <huazh...@gmail.com>
---
 libavcodec/qsvenc.c | 55 +++--
 libavcodec/qsvenc.h |  2 +-
 2 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index ac443c1..1ce2c3c 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -651,6 +651,56 @@ static int qsv_init_opaque_alloc(AVCodecContext *avctx, 
QSVEncContext *q)
 return 0;
 }
 
+static int qsv_init_internal_session(AVCodecContext *avctx, mfxSession 
*session,
+ QSVEncContext *q, const char *load_plugins)
+{
+mfxIMPL impl   = MFX_IMPL_AUTO_ANY;
+const char *desc;
+int ret;
+AVHWDeviceContext *device_hw;
+AVQSVDeviceContext *hwctx;
+AVBufferRef *hw_device_ctx;
+
+ret = av_hwdevice_ctx_create(_device_ctx, AV_HWDEVICE_TYPE_QSV, NULL, 
NULL, 0);
+if (ret < 0) {
+av_log(NULL, AV_LOG_ERROR, "Failed to create a QSV device\n");
+return ret;
+}
+device_hw = (AVHWDeviceContext*)hw_device_ctx->data;
+hwctx = device_hw->hwctx;
+
+*session = hwctx->session;
+
+q->device_ctx.hw_device_ctx = hw_device_ctx;
+
+ret = ff_qsv_load_plugins(*session, load_plugins, avctx);
+if (ret < 0) {
+av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
+return ret;
+}
+MFXQueryIMPL(*session, );
+
+switch (MFX_IMPL_BASETYPE(impl)) {
+case MFX_IMPL_SOFTWARE:
+desc = "software";
+break;
+case MFX_IMPL_HARDWARE:
+case MFX_IMPL_HARDWARE2:
+case MFX_IMPL_HARDWARE3:
+case MFX_IMPL_HARDWARE4:
+desc = "hardware accelerated";
+break;
+default:
+desc = "unknown";
+}
+
+av_log(avctx, AV_LOG_VERBOSE,
+   "Initialized an internal MFX session using %s implementation\n",
+   desc);
+
+return 0;
+}
+
 static int qsvenc_init_session(AVCodecContext *avctx, QSVEncContext *q)
 {
 int ret;
@@ -673,12 +723,12 @@ static int qsvenc_init_session(AVCodecContext *avctx, 
QSVEncContext *q)
 
 q->session = q->internal_session;
 } else {
-ret = ff_qsv_init_internal_session(avctx, >internal_session,
+ret = qsv_init_internal_session(avctx, >session, q,
q->load_plugins);
 if (ret < 0)
 return ret;
 
-q->session = q->internal_session;
+   // q->session = q->internal_session;
 }
 
 return 0;
@@ -1088,6 +1138,7 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext 
*q)
 q->internal_session = NULL;
 
 av_buffer_unref(>frames_ctx.hw_frames_ctx);
+av_buffer_unref(>device_ctx.hw_device_ctx);
 av_freep(>frames_ctx.mids);
 q->frames_ctx.nb_mids = 0;
 
diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
index 361d933..d377ea4 100644
--- a/libavcodec/qsvenc.h
+++ b/libavcodec/qsvenc.h
@@ -105,7 +105,7 @@ typedef struct QSVEncContext {
 AVFifoBuffer *async_fifo;
 
 QSVFramesContext frames_ctx;
-
+QSVDeviceContext device_ctx;
 // options set by the caller
 int async_depth;
 int idr_interval;
-- 
1.8.3.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH 1/2] libavcodec/qsvdec: Fix the QSV decoder can't work when using system memory

2017-01-08 Thread Huang, Zhengxu


From 37629f14294125c7396e5e12970d75e895b1caba Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxw...@gmail.com>
Date: Mon, 19 Dec 2016 01:27:06 -0500
Subject: [PATCH 1/2] libavcodec/qsvdec: Fix the QSV decoder can't work when
 using system memory

Description: ./ffmpeg -c:v h264_qsv -i in -c:v h264 output.h264 does not
work because the qsv decode will failed.

Root cuase: when using the system rather than the 
hwaccel,ff_qsv_init_internal_session
does not set the vaDisplay handle for the session. The qsv decode will failed.

Solution: when creating the internal session , call the HwContext API to get 
session and
release all resource when close the decoder.

Signed-off-by: ChaoX A Liu <chaox.a@gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxw...@gmail.com>
Signed-off-by: Andrew, Zhang <huazh...@gmail.com>
---
 libavcodec/qsv.c  |  6 ++---
 libavcodec/qsv_internal.h |  5 
 libavcodec/qsvdec.c   | 59 ---
 libavcodec/qsvdec.h   |  1 +
 4 files changed, 65 insertions(+), 6 deletions(-)

diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
index aac6ce6..a932fc3 100644
--- a/libavcodec/qsv.c
+++ b/libavcodec/qsv.c
@@ -120,7 +120,7 @@ int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t 
*fourcc)
 }
 }
 
-static int qsv_load_plugins(mfxSession session, const char *load_plugins,
+int ff_qsv_load_plugins(mfxSession session, const char *load_plugins,
 void *logctx)
 {
 if (!load_plugins || !*load_plugins)
@@ -185,7 +185,7 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, 
mfxSession *session,
 return ff_qsv_error(ret);
 }
 
-ret = qsv_load_plugins(*session, load_plugins, avctx);
+ret = ff_qsv_load_plugins(*session, load_plugins, avctx);
 if (ret < 0) {
 av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
 return ret;
@@ -329,7 +329,7 @@ int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, 
mfxSession *psession,
 }
 }
 
-ret = qsv_load_plugins(session, load_plugins, avctx);
+ret = ff_qsv_load_plugins(session, load_plugins, avctx);
 if (ret < 0) {
 av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
 return ret;
diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
index 5d2a216..13f23ef 100644
--- a/libavcodec/qsv_internal.h
+++ b/libavcodec/qsv_internal.h
@@ -50,6 +50,10 @@ typedef struct QSVFrame {
 struct QSVFrame *next;
 } QSVFrame;
 
+typedef struct QSVDeviceContext {
+AVBufferRef *hw_device_ctx;
+} QSVDeviceContext;
+
 typedef struct QSVFramesContext {
 AVBufferRef *hw_frames_ctx;
 mfxFrameInfo info;
@@ -73,5 +77,6 @@ int ff_qsv_init_internal_session(AVCodecContext *avctx, 
mfxSession *session,
 int ff_qsv_init_session_hwcontext(AVCodecContext *avctx, mfxSession *session,
   QSVFramesContext *qsv_frames_ctx,
   const char *load_plugins, int opaque);
+int ff_qsv_load_plugins(mfxSession session, const char *load_plugins, void 
*logctx);
 
 #endif /* AVCODEC_QSV_INTERNAL_H */
diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
index 258042d..ccd5e26 100644
--- a/libavcodec/qsvdec.c
+++ b/libavcodec/qsvdec.c
@@ -41,6 +41,58 @@
 #include "qsv_internal.h"
 #include "qsvdec.h"
 
+static int qsv_init_internal_session(AVCodecContext *avctx, mfxSession 
*session,
+ QSVContext *q, const char *load_plugins)
+{
+mfxIMPL impl   = MFX_IMPL_AUTO_ANY;
+mfxVersion ver = { { QSV_VERSION_MINOR, QSV_VERSION_MAJOR } };
+
+const char *desc;
+int ret;
+AVHWDeviceContext *device_hw;
+AVQSVDeviceContext *hwctx;
+AVBufferRef *hw_device_ctx;
+
+ret = av_hwdevice_ctx_create(_device_ctx, AV_HWDEVICE_TYPE_QSV, NULL, 
NULL, 0);
+if (ret < 0) {
+av_log(NULL, AV_LOG_ERROR, "Failed to create a QSV device\n");
+return ret;
+}
+device_hw = (AVHWDeviceContext*)hw_device_ctx->data;
+hwctx = device_hw->hwctx;
+
+*session = hwctx->session;
+
+q->device_ctx.hw_device_ctx = hw_device_ctx;
+
+ret = ff_qsv_load_plugins(*session, load_plugins, avctx);
+if (ret < 0) {
+av_log(avctx, AV_LOG_ERROR, "Error loading plugins\n");
+return ret;
+}
+MFXQueryIMPL(*session, );
+
+switch (MFX_IMPL_BASETYPE(impl)) {
+case MFX_IMPL_SOFTWARE:
+desc = "software";
+break;
+case MFX_IMPL_HARDWARE:
+case MFX_IMPL_HARDWARE2:
+case MFX_IMPL_HARDWARE3:
+case MFX_IMPL_HARDWARE4:
+desc = "hardware accelerated";
+break;
+default:
+desc = "unknown";
+}
+
+av_log(avctx, AV_LOG_VERBOSE,
+   "Initialized an internal MFX session using %s implementation\n",
+   desc);
+
+return 0;
+}
+
 static int qsv_i

Re: [FFmpeg-devel] [PATCH] libavutil/hwcontext_qsv: Command line using hwaccel 'QSV' doesn't work

2017-01-05 Thread Huang, Zhengxu

Hi

According to the suggestion update the patch.

thanks.


在 2017/1/3 21:14, Mark Thompson 写道:

On 03/01/17 07:13, Huang, Zhengxu wrote:

 From 687ce9c804b2618f021100235c46a33b48fa522c Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxw...@gmail.com>
Date: Wed, 14 Dec 2016 11:55:31 +0800
Subject: [PATCH] libavutil/hwcontext_qsv: Command line using hwaccel 'QSV'
  doesn't work.

Command: ffmpeg -hwaccel qsv -c:v h264_qsv -i test.264 -c:v h264_qsv out.264

Reason: hwcontext_qsv will create a child hwcontext_vaapi. VAAPI will
  open X11 display ":0.0" defaultly. However, MSDK doesn't support X11 so
  far. This results in the failure of this command.

Fix: When using VAAPI, let VAAPI try to create DRM display handle by scanning
  device nodes under '/dev/dri/'.

We already default to attempting to open the first render node inside 
hwcontext_vaapi (if opening via X11 fails):

http://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavutil/hwcontext_vaapi.c;h=6176bdc880c81dec7cac0b214a8d55f3b1160abc;hb=HEAD#l936

I think if you want this behaviour it would be better to add code there rather 
than in hwcontext_qsv (which doesn't really care about this aspect at all, it 
just wants a usable subdevice for the platform).

Can you explain your case which hits this?  Do you have some other external 
graphics card(s) along with the on-chip Intel graphics?  For that case, I don't 
like the idea of scanning for a device node because it is perfectly possible to 
get a valid VADisplay handle for a non-QSV device (an AMD or Nvidia card with 
mesa, most obviously) which will then fail opaquely later when libmfx tries to 
use it because the Intel proprietary driver is required.  This may even fail 
randomly, because device nodes associated with independent drivers are not 
ordered.


Signed-off-by: ChaoX A Liu <chaox.a@gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxw...@gmail.com>
Signed-off-by: Andrew, Zhang <huazh...@gmail.com>
---
  libavutil/hwcontext_qsv.c | 44 +++-
  1 file changed, 31 insertions(+), 13 deletions(-)

diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index 2dc9aca..2701b5a 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -707,12 +707,41 @@ static mfxIMPL choose_implementation(const char *device)
  return impl;
  }
  
+static int create_proper_child_device(AVBufferRef **ctx, const char *device, int flags)

+{
+enum AVHWDeviceType child_device_type;
+char adapter[256];
+int  adapter_num;
+
+if (CONFIG_VAAPI)
+child_device_type = AV_HWDEVICE_TYPE_VAAPI;
+else if (CONFIG_DXVA2)
+child_device_type = AV_HWDEVICE_TYPE_DXVA2;
+else
+return AVERROR(ENOSYS);
+
+if (device || CONFIG_DXVA2)
+return av_hwdevice_ctx_create(ctx, child_device_type, device, NULL, 
flags);
+
+for (adapter_num = 0; adapter_num < 6; adapter_num++) {
+if (adapter_num < 3)
+snprintf(adapter,sizeof(adapter),
+"/dev/dri/renderD%d", adapter_num+128);
+else
+snprintf(adapter,sizeof(adapter),
+"/dev/dri/card%d", adapter_num-3);

I would prefer not to open the DRM master device (/dev/dri/card*) by default - 
until very recent kernels it was exclusive-access-only, so nothing else can use 
the graphics at the same time (most obviously another ffmpeg instance).


+if (av_hwdevice_ctx_create(ctx, child_device_type, adapter, NULL, 
flags) == 0)
+return 0;
+}
+
+return AVERROR(ENOSYS);
+}
+
  static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
   AVDictionary *opts, int flags)
  {
  AVQSVDeviceContext *hwctx = ctx->hwctx;
  QSVDevicePriv *priv;
-enum AVHWDeviceType child_device_type;
  AVDictionaryEntry *e;
  
  mfxVersionver = { { 3, 1 } };

@@ -730,18 +759,7 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const 
char *device,
  ctx->free= qsv_device_free;
  
  e = av_dict_get(opts, "child_device", NULL, 0);

-
-if (CONFIG_VAAPI)
-child_device_type = AV_HWDEVICE_TYPE_VAAPI;
-else if (CONFIG_DXVA2)
-child_device_type = AV_HWDEVICE_TYPE_DXVA2;
-else {
-av_log(ctx, AV_LOG_ERROR, "No supported child device type is 
enabled\n");
-return AVERROR(ENOSYS);
-}
-
-ret = av_hwdevice_ctx_create(>child_device_ctx, child_device_type,
- e ? e->value : NULL, NULL, 0);
+ret = create_proper_child_device(>child_device_ctx, e ? e->value : 
NULL, 0);
  if (ret < 0)
  return ret;
  
--

1.8.3.1


For your specific case in the ffmpeg utility it might be best to add a new command-line 
option (-qsv_device?) and then pass it as the "child_device" in the options 
dictionary?  I admit this isn't necessarily helpful for ot

Re: [FFmpeg-devel] [PATCH] libavutil/hwcontext_qsv: Fix bug that the QSV encoded frames'width and height are 32-aligned

2017-01-04 Thread Huang, Zhengxu

Hi,


If fixing this issue by adjusting the cropping parameters after copying 
the FrameInfo, maybe it will still have some problem.


This fix will only modify the encoder's surface information but other 
modules' surface information(CropW and CropH of the FrameInfo) also 
needs to be modified. So many more codes need to modify.


In my opinion fixing this case in the hwcontext_qsv.c maybe much better 
. And the surface information do need align when doing allocator.


What's your opinion, or some other better suggestion ,thanks.


在 2017/1/3 20:40, Mark Thompson 写道:

On 03/01/17 06:35, Huang, Zhengxu wrote:

 From 8b1bcc0634f6ce36acfbd2bfdd26690a6323d09c Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxw...@gmail.com>
Date: Fri, 16 Dec 2016 11:10:34 +0800
Subject: [PATCH] libavutil/hwcontext_qsv: Fix bug that the QSV encoded frames'
  width and height are 32-aligned.

Description:
If an input is of 1280x720, the encoded stream created by command below is of 
1280x736:
ffmpeg -hwaccel qsv -c:v h264_qsv -i test.h264 -c:v h264_qsv out.h264

Reason:
When creating a AVQSVFramesContext, width and height shouldn't be aligned, or 
the mfxSurfaces'
  cropW and cropH will be wrong.

Fix:
User should configure AVQSVFramesContext with origin width and height and 
AVFramesContext will
  align the width and height when being initiallized.

Signed-off-by: ChaoX A Liu <chaox.a@gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxw...@gmail.com>
Signed-off-by: Andrew, Zhang <huazh...@gmail.com>
---
  ffmpeg_qsv.c  | 8 
  libavutil/hwcontext_qsv.c | 8 ++--
  2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/ffmpeg_qsv.c b/ffmpeg_qsv.c
index 68ff5bd..aab7375 100644
--- a/ffmpeg_qsv.c
+++ b/ffmpeg_qsv.c
@@ -76,8 +76,8 @@ int qsv_init(AVCodecContext *s)
  frames_ctx   = (AVHWFramesContext*)ist->hw_frames_ctx->data;
  frames_hwctx = frames_ctx->hwctx;
  
-frames_ctx->width = FFALIGN(s->coded_width,  32);

-frames_ctx->height= FFALIGN(s->coded_height, 32);
+frames_ctx->width = s->coded_width;
+frames_ctx->height= s->coded_height;
  frames_ctx->format= AV_PIX_FMT_QSV;
  frames_ctx->sw_format = s->sw_pix_fmt;
  frames_ctx->initial_pool_size = 64;
@@ -152,8 +152,8 @@ int qsv_transcode_init(OutputStream *ost)
  encode_frames = (AVHWFramesContext*)encode_frames_ref->data;
  qsv_frames = encode_frames->hwctx;
  
-encode_frames->width = FFALIGN(ist->resample_width,  32);

-encode_frames->height= FFALIGN(ist->resample_height, 32);
+encode_frames->width = ist->resample_width;
+encode_frames->height= ist->resample_height;
  encode_frames->format= AV_PIX_FMT_QSV;
  encode_frames->sw_format = AV_PIX_FMT_NV12;
  encode_frames->initial_pool_size = 1;
diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index 03244a6..2dc9aca 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -308,9 +308,13 @@ static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t 
fourcc)
  surf->Info.ChromaFormat   = MFX_CHROMAFORMAT_YUV444;
  
  surf->Info.FourCC = fourcc;

-surf->Info.Width  = ctx->width;
+/*
+ * WxH being aligned with 32x32 is needed by MSDK.
+ * CropW and CropH are the real size of the frame.
+ */
+surf->Info.Width  = FFALIGN(ctx->width, 32);
  surf->Info.CropW  = ctx->width;
-surf->Info.Height = ctx->height;
+surf->Info.Height = FFALIGN(ctx->height, 32);
  surf->Info.CropH  = ctx->height;
  surf->Info.FrameRateExtN  = 25;
  surf->Info.FrameRateExtD  = 1;
--
1.8.3.1


This seems wrong to me - the hwcontext code is only dealing in surfaces, and 
should not be interested in the actual dimensions of the frame on each surface 
(that is a per-frame property anyway, since it need not be the same for all 
frames in a context).

Is it possible to instead fix this case by adjusting the cropping parameters 
after copying the FrameInfo at libavcodec/qsvenc.c:378?  Maybe this (not tested 
at all):

diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
index ac443c1a26..32e2a4ed13 100644
--- a/libavcodec/qsvenc.c
+++ b/libavcodec/qsvenc.c
@@ -376,6 +376,8 @@ static int init_video_param(AVCodecContext *avctx, 
QSVEncContext *q)
  AVHWFramesContext *frames_ctx = 
(AVHWFramesContext*)avctx->hw_frames_ctx->data;
  AVQSVFramesContext *frames_hwctx = frames_ctx->hwctx;
  q->param.mfx.FrameInfo = frames_hwctx->surfaces[0].Info;
+q->param.mfx.FrameInfo.CropW = avctx->width;
+q->param.mfx.FrameInfo.CropH = avctx->height;
 

Re: [FFmpeg-devel] [PATCH] libavutil/hwcontext_qsv: Command line using hwaccel 'QSV' doesn't work

2017-01-04 Thread Huang, Zhengxu

在 2017/1/3 21:14, Mark Thompson 写道:


On 03/01/17 07:13, Huang, Zhengxu wrote:

 From 687ce9c804b2618f021100235c46a33b48fa522c Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxw...@gmail.com>
Date: Wed, 14 Dec 2016 11:55:31 +0800
Subject: [PATCH] libavutil/hwcontext_qsv: Command line using hwaccel 'QSV'
  doesn't work.

Command: ffmpeg -hwaccel qsv -c:v h264_qsv -i test.264 -c:v h264_qsv out.264

Reason: hwcontext_qsv will create a child hwcontext_vaapi. VAAPI will
  open X11 display ":0.0" defaultly. However, MSDK doesn't support X11 so
  far. This results in the failure of this command.

Fix: When using VAAPI, let VAAPI try to create DRM display handle by scanning
  device nodes under '/dev/dri/'.

We already default to attempting to open the first render node inside 
hwcontext_vaapi (if opening via X11 fails):

http://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavutil/hwcontext_vaapi.c;h=6176bdc880c81dec7cac0b214a8d55f3b1160abc;hb=HEAD#l936

I think if you want this behaviour it would be better to add code there rather 
than in hwcontext_qsv (which doesn't really care about this aspect at all, it 
just wants a usable subdevice for the platform).

your concern makes sense and this fix does may introduce some other problem.

Can you explain your case which hits this?  Do you have some other external 
graphics card(s) along with the on-chip Intel graphics?  For that case, I don't 
like the idea of scanning for a device node because it is perfectly possible to 
get a valid VADisplay handle for a non-QSV device (an AMD or Nvidia card with 
mesa, most obviously) which will then fail opaquely later when libmfx tries to 
use it because the Intel proprietary driver is required.  This may even fail 
randomly, because device nodes associated with independent drivers are not 
ordered.
The reason that we do like this is that we met some special case before. 
Under the /dev/dri node there is no dev/dri/renderD128 and only
the card0 and card1. The card0 can't work and the card1 can work well. 
So we add the scanning device node code.



Signed-off-by: ChaoX A Liu <chaox.a@gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxw...@gmail.com>
Signed-off-by: Andrew, Zhang <huazh...@gmail.com>
---
  libavutil/hwcontext_qsv.c | 44 +++-
  1 file changed, 31 insertions(+), 13 deletions(-)

diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index 2dc9aca..2701b5a 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -707,12 +707,41 @@ static mfxIMPL choose_implementation(const char *device)
  return impl;
  }
  
+static int create_proper_child_device(AVBufferRef **ctx, const char *device, int flags)

+{
+enum AVHWDeviceType child_device_type;
+char adapter[256];
+int  adapter_num;
+
+if (CONFIG_VAAPI)
+child_device_type = AV_HWDEVICE_TYPE_VAAPI;
+else if (CONFIG_DXVA2)
+child_device_type = AV_HWDEVICE_TYPE_DXVA2;
+else
+return AVERROR(ENOSYS);
+
+if (device || CONFIG_DXVA2)
+return av_hwdevice_ctx_create(ctx, child_device_type, device, NULL, 
flags);
+
+for (adapter_num = 0; adapter_num < 6; adapter_num++) {
+if (adapter_num < 3)
+snprintf(adapter,sizeof(adapter),
+"/dev/dri/renderD%d", adapter_num+128);
+else
+snprintf(adapter,sizeof(adapter),
+"/dev/dri/card%d", adapter_num-3);

I would prefer not to open the DRM master device (/dev/dri/card*) by default - 
until very recent kernels it was exclusive-access-only, so nothing else can use 
the graphics at the same time (most obviously another ffmpeg instance).


+if (av_hwdevice_ctx_create(ctx, child_device_type, adapter, NULL, 
flags) == 0)
+return 0;
+}
+
+return AVERROR(ENOSYS);
+}
+
  static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
   AVDictionary *opts, int flags)
  {
  AVQSVDeviceContext *hwctx = ctx->hwctx;
  QSVDevicePriv *priv;
-enum AVHWDeviceType child_device_type;
  AVDictionaryEntry *e;
  
  mfxVersionver = { { 3, 1 } };

@@ -730,18 +759,7 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const 
char *device,
  ctx->free= qsv_device_free;
  
  e = av_dict_get(opts, "child_device", NULL, 0);

-
-if (CONFIG_VAAPI)
-child_device_type = AV_HWDEVICE_TYPE_VAAPI;
-else if (CONFIG_DXVA2)
-child_device_type = AV_HWDEVICE_TYPE_DXVA2;
-else {
-av_log(ctx, AV_LOG_ERROR, "No supported child device type is 
enabled\n");
-return AVERROR(ENOSYS);
-}
-
-ret = av_hwdevice_ctx_create(>child_device_ctx, child_device_type,
- e ? e->value : NULL, NULL, 0);
+ret = create_proper_child_device(>child_device_ctx, e ? e->value : 
NULL, 0);
  if (ret < 0)

[FFmpeg-devel] [PATCH] libavutil/hwcontext_qsv: Command line using hwaccel 'QSV' doesn't work

2017-01-02 Thread Huang, Zhengxu


From 687ce9c804b2618f021100235c46a33b48fa522c Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxw...@gmail.com>
Date: Wed, 14 Dec 2016 11:55:31 +0800
Subject: [PATCH] libavutil/hwcontext_qsv: Command line using hwaccel 'QSV'
 doesn't work.

Command: ffmpeg -hwaccel qsv -c:v h264_qsv -i test.264 -c:v h264_qsv out.264

Reason: hwcontext_qsv will create a child hwcontext_vaapi. VAAPI will
 open X11 display ":0.0" defaultly. However, MSDK doesn't support X11 so
 far. This results in the failure of this command.

Fix: When using VAAPI, let VAAPI try to create DRM display handle by scanning
 device nodes under '/dev/dri/'.

Signed-off-by: ChaoX A Liu <chaox.a@gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxw...@gmail.com>
Signed-off-by: Andrew, Zhang <huazh...@gmail.com>
---
 libavutil/hwcontext_qsv.c | 44 +++-
 1 file changed, 31 insertions(+), 13 deletions(-)

diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index 2dc9aca..2701b5a 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -707,12 +707,41 @@ static mfxIMPL choose_implementation(const char *device)
 return impl;
 }
 
+static int create_proper_child_device(AVBufferRef **ctx, const char *device, 
int flags)
+{
+enum AVHWDeviceType child_device_type;
+char adapter[256];
+int  adapter_num;
+
+if (CONFIG_VAAPI)
+child_device_type = AV_HWDEVICE_TYPE_VAAPI;
+else if (CONFIG_DXVA2)
+child_device_type = AV_HWDEVICE_TYPE_DXVA2;
+else
+return AVERROR(ENOSYS);
+
+if (device || CONFIG_DXVA2)
+return av_hwdevice_ctx_create(ctx, child_device_type, device, NULL, 
flags);
+
+for (adapter_num = 0; adapter_num < 6; adapter_num++) {
+if (adapter_num < 3)
+snprintf(adapter,sizeof(adapter),
+"/dev/dri/renderD%d", adapter_num+128);
+else
+snprintf(adapter,sizeof(adapter),
+"/dev/dri/card%d", adapter_num-3);
+if (av_hwdevice_ctx_create(ctx, child_device_type, adapter, NULL, 
flags) == 0)
+return 0;
+}
+
+return AVERROR(ENOSYS);
+}
+
 static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
  AVDictionary *opts, int flags)
 {
 AVQSVDeviceContext *hwctx = ctx->hwctx;
 QSVDevicePriv *priv;
-enum AVHWDeviceType child_device_type;
 AVDictionaryEntry *e;
 
 mfxVersionver = { { 3, 1 } };
@@ -730,18 +759,7 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const 
char *device,
 ctx->free= qsv_device_free;
 
 e = av_dict_get(opts, "child_device", NULL, 0);
-
-if (CONFIG_VAAPI)
-child_device_type = AV_HWDEVICE_TYPE_VAAPI;
-else if (CONFIG_DXVA2)
-child_device_type = AV_HWDEVICE_TYPE_DXVA2;
-else {
-av_log(ctx, AV_LOG_ERROR, "No supported child device type is 
enabled\n");
-return AVERROR(ENOSYS);
-}
-
-ret = av_hwdevice_ctx_create(>child_device_ctx, child_device_type,
- e ? e->value : NULL, NULL, 0);
+ret = create_proper_child_device(>child_device_ctx, e ? e->value : 
NULL, 0);
 if (ret < 0)
 return ret;
 
-- 
1.8.3.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH] libavutil/hwcontext_qsv: Fix bug that the QSV encoded frames'width and height are 32-aligned

2017-01-02 Thread Huang, Zhengxu


From 8b1bcc0634f6ce36acfbd2bfdd26690a6323d09c Mon Sep 17 00:00:00 2001
From: Zhengxu <zhengxu.maxw...@gmail.com>
Date: Fri, 16 Dec 2016 11:10:34 +0800
Subject: [PATCH] libavutil/hwcontext_qsv: Fix bug that the QSV encoded frames'
 width and height are 32-aligned.

Description:
If an input is of 1280x720, the encoded stream created by command below is of 
1280x736:
ffmpeg -hwaccel qsv -c:v h264_qsv -i test.h264 -c:v h264_qsv out.h264

Reason:
When creating a AVQSVFramesContext, width and height shouldn't be aligned, or 
the mfxSurfaces'
 cropW and cropH will be wrong.

Fix:
User should configure AVQSVFramesContext with origin width and height and 
AVFramesContext will
 align the width and height when being initiallized.

Signed-off-by: ChaoX A Liu <chaox.a@gmail.com>
Signed-off-by: Huang, Zhengxu <zhengxu.maxw...@gmail.com>
Signed-off-by: Andrew, Zhang <huazh...@gmail.com>
---
 ffmpeg_qsv.c  | 8 
 libavutil/hwcontext_qsv.c | 8 ++--
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/ffmpeg_qsv.c b/ffmpeg_qsv.c
index 68ff5bd..aab7375 100644
--- a/ffmpeg_qsv.c
+++ b/ffmpeg_qsv.c
@@ -76,8 +76,8 @@ int qsv_init(AVCodecContext *s)
 frames_ctx   = (AVHWFramesContext*)ist->hw_frames_ctx->data;
 frames_hwctx = frames_ctx->hwctx;
 
-frames_ctx->width = FFALIGN(s->coded_width,  32);
-frames_ctx->height= FFALIGN(s->coded_height, 32);
+frames_ctx->width = s->coded_width;
+frames_ctx->height= s->coded_height;
 frames_ctx->format= AV_PIX_FMT_QSV;
 frames_ctx->sw_format = s->sw_pix_fmt;
 frames_ctx->initial_pool_size = 64;
@@ -152,8 +152,8 @@ int qsv_transcode_init(OutputStream *ost)
 encode_frames = (AVHWFramesContext*)encode_frames_ref->data;
 qsv_frames = encode_frames->hwctx;
 
-encode_frames->width = FFALIGN(ist->resample_width,  32);
-encode_frames->height= FFALIGN(ist->resample_height, 32);
+encode_frames->width = ist->resample_width;
+encode_frames->height= ist->resample_height;
 encode_frames->format= AV_PIX_FMT_QSV;
 encode_frames->sw_format = AV_PIX_FMT_NV12;
 encode_frames->initial_pool_size = 1;
diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index 03244a6..2dc9aca 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -308,9 +308,13 @@ static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t 
fourcc)
 surf->Info.ChromaFormat   = MFX_CHROMAFORMAT_YUV444;
 
 surf->Info.FourCC = fourcc;
-surf->Info.Width  = ctx->width;
+/*
+ * WxH being aligned with 32x32 is needed by MSDK.
+ * CropW and CropH are the real size of the frame.
+ */
+surf->Info.Width  = FFALIGN(ctx->width, 32);
 surf->Info.CropW  = ctx->width;
-surf->Info.Height = ctx->height;
+surf->Info.Height = FFALIGN(ctx->height, 32);
 surf->Info.CropH  = ctx->height;
 surf->Info.FrameRateExtN  = 25;
 surf->Info.FrameRateExtD  = 1;
-- 
1.8.3.1

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel