Re: [libav-devel] [PATCH v4] qsvvpp: Fix to perform full init only when needed

2018-07-17 Thread Mark Thompson
On 18/07/18 00:25, Maxym Dmytrychenko wrote:
> On Wed, Jul 18, 2018 at 12:48 AM Mark Thompson  wrote:
> 
>> On 17/07/18 17:07, Maxym Dmytrychenko wrote:
>>> Not used VPP sessions, like for hwupload/hwdownload handling,
>>> can increase CPU utilization and this patch fixes it.
>>> thank you,Joe, for the contribution.
>>>
>>> Signed-off-by: Maxym Dmytrychenko 
>>> ---
>>>  libavutil/hwcontext_qsv.c | 38 +-
>>>  1 file changed, 29 insertions(+), 9 deletions(-)
>>>
>>> diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
>>> index b3eb4a3ea..390c3aac4 100644
>>> --- a/libavutil/hwcontext_qsv.c
>>> +++ b/libavutil/hwcontext_qsv.c
>>> @@ -18,6 +18,7 @@
>>>
>>>  #include 
>>>  #include 
>>> +#include 
>>>
>>>  #include 
>>>
>>> @@ -56,7 +57,9 @@ typedef struct QSVDeviceContext {
>>>
>>>  typedef struct QSVFramesContext {
>>>  mfxSession session_download;
>>> +atomic_int session_download_init;
>>>  mfxSession session_upload;
>>> +atomic_int session_upload_init;
>>>
>>>  AVBufferRef *child_frames_ref;
>>>  mfxFrameSurface1 *surfaces_internal;
>>> @@ -146,13 +149,15 @@ static void qsv_frames_uninit(AVHWFramesContext
>> *ctx)
>>>  MFXVideoVPP_Close(s->session_download);
>>>  MFXClose(s->session_download);
>>>  }
>>> -s->session_download = NULL;
>>> +s->session_download  = NULL;
>>> +s->session_download_init = 0;
>>>
>>>  if (s->session_upload) {
>>>  MFXVideoVPP_Close(s->session_upload);
>>>  MFXClose(s->session_upload);
>>>  }
>>> -s->session_upload = NULL;
>>> +s->session_upload  = NULL;
>>> +s->session_upload_init = 0;
>>>
>>>  av_freep(>mem_ids);
>>>  av_freep(>surface_ptrs);
>>> @@ -535,13 +540,10 @@ static int qsv_frames_init(AVHWFramesContext *ctx)
>>>  s->mem_ids[i] = frames_hwctx->surfaces[i].Data.MemId;
>>>  }
>>>
>>> -ret = qsv_init_internal_session(ctx, >session_download, 0);
>>> -if (ret < 0)
>>> -return ret;
>>> -
>>> -ret = qsv_init_internal_session(ctx, >session_upload, 1);
>>> -if (ret < 0)
>>> -return ret;
>>> +s->session_download  = NULL;
>>> +s->session_upload= NULL;
>>> +s->session_download_init = 0;
>>> +s->session_upload_init   = 0;
>>>
>>>  return 0;
>>>  }
>>> @@ -741,6 +743,15 @@ static int qsv_transfer_data_from(AVHWFramesContext
>> *ctx, AVFrame *dst,
>>>  mfxSyncPoint sync = NULL;
>>>  mfxStatus err;
>>>
>>> +while (!s->session_download_init && !s->session_download) {
>>> + if (atomic_fetch_add(>session_download_init, 1) == 0) {
>>> +qsv_init_internal_session(ctx, >session_download, 0);
>>> +}
>>> + else {
>>> +av_usleep(1);
>>
>> This races - consider what happens if the other thread is preempted for
>> more than 1µs, or if the initialisation itself takes more than that long.

(Apologies, I misread that the first time - with the spin loop it should only 
be a benign race on session_download, but it's still undefined behaviour by C11 
and things like tsan will complain about it: read in the non-initialising 
thread against write in the initialising thread, after the flag has been set to 
1.)

>>
>> You need to actually do some synchronisation here (e.g. with a 'once'
>> variable) - with only atomic flags there is no way to guarantee that the
>> other thread has finished unless you spin, which isn't acceptable.
>>
>> pthread_once was considered but we need to pass  s->session_download
> adding mutex - can be overkill for each call of   qsv_transfer_data_*
> 
> what do you mean by 'once' variable?
> dont really see it currently implemented somewhere...

See AVOnce.  It's used in a few places in this role, for example in 
hwcontext_d3d11va.c for the library loading.

>>> +}
>>> +}
>>> +
>>>  if (!s->session_download) {
>>>  if (s->child_frames_ref)
>>>  return qsv_transfer_data_child(ctx, dst, src);
>>> @@ -788,6 +799,15 @@ static int qsv_transfer_data_to(AVHWFramesContext
>> *ctx, AVFrame *dst,
>>>  mfxSyncPoint sync = NULL;
>>>  mfxStatus err;
>>>
>>> +while (!s->session_upload_init && !s->session_upload) {
>>> + if (atomic_fetch_add(>session_upload_init, 1) == 0) {
>>> +qsv_init_internal_session(ctx, >session_upload, 1);
>>> +}
>>> + else {
>>> +av_usleep(1);
>>> +}
>>> +}
>>> +
>>>  if (!s->session_upload) {
>>>  if (s->child_frames_ref)
>>>  return qsv_transfer_data_child(ctx, dst, src);
>>>
___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Re: [libav-devel] [PATCH v4] qsvvpp: Fix to perform full init only when needed

2018-07-17 Thread Mark Thompson
On 17/07/18 17:07, Maxym Dmytrychenko wrote:
> Not used VPP sessions, like for hwupload/hwdownload handling,
> can increase CPU utilization and this patch fixes it.
> thank you,Joe, for the contribution.
> 
> Signed-off-by: Maxym Dmytrychenko 
> ---
>  libavutil/hwcontext_qsv.c | 38 +-
>  1 file changed, 29 insertions(+), 9 deletions(-)
> 
> diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
> index b3eb4a3ea..390c3aac4 100644
> --- a/libavutil/hwcontext_qsv.c
> +++ b/libavutil/hwcontext_qsv.c
> @@ -18,6 +18,7 @@
>  
>  #include 
>  #include 
> +#include 
>  
>  #include 
>  
> @@ -56,7 +57,9 @@ typedef struct QSVDeviceContext {
>  
>  typedef struct QSVFramesContext {
>  mfxSession session_download;
> +atomic_int session_download_init;
>  mfxSession session_upload;
> +atomic_int session_upload_init;
>  
>  AVBufferRef *child_frames_ref;
>  mfxFrameSurface1 *surfaces_internal;
> @@ -146,13 +149,15 @@ static void qsv_frames_uninit(AVHWFramesContext *ctx)
>  MFXVideoVPP_Close(s->session_download);
>  MFXClose(s->session_download);
>  }
> -s->session_download = NULL;
> +s->session_download  = NULL;
> +s->session_download_init = 0;
>  
>  if (s->session_upload) {
>  MFXVideoVPP_Close(s->session_upload);
>  MFXClose(s->session_upload);
>  }
> -s->session_upload = NULL;
> +s->session_upload  = NULL;
> +s->session_upload_init = 0;
>  
>  av_freep(>mem_ids);
>  av_freep(>surface_ptrs);
> @@ -535,13 +540,10 @@ static int qsv_frames_init(AVHWFramesContext *ctx)
>  s->mem_ids[i] = frames_hwctx->surfaces[i].Data.MemId;
>  }
>  
> -ret = qsv_init_internal_session(ctx, >session_download, 0);
> -if (ret < 0)
> -return ret;
> -
> -ret = qsv_init_internal_session(ctx, >session_upload, 1);
> -if (ret < 0)
> -return ret;
> +s->session_download  = NULL;
> +s->session_upload= NULL;
> +s->session_download_init = 0;
> +s->session_upload_init   = 0;
>  
>  return 0;
>  }
> @@ -741,6 +743,15 @@ static int qsv_transfer_data_from(AVHWFramesContext 
> *ctx, AVFrame *dst,
>  mfxSyncPoint sync = NULL;
>  mfxStatus err;
>  
> +while (!s->session_download_init && !s->session_download) {
> + if (atomic_fetch_add(>session_download_init, 1) == 0) {
> +qsv_init_internal_session(ctx, >session_download, 0);
> +}
> + else {
> +av_usleep(1);

This races - consider what happens if the other thread is preempted for more 
than 1µs, or if the initialisation itself takes more than that long.

You need to actually do some synchronisation here (e.g. with a 'once' variable) 
- with only atomic flags there is no way to guarantee that the other thread has 
finished unless you spin, which isn't acceptable.

> +}
> +}
> +
>  if (!s->session_download) {
>  if (s->child_frames_ref)
>  return qsv_transfer_data_child(ctx, dst, src);
> @@ -788,6 +799,15 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, 
> AVFrame *dst,
>  mfxSyncPoint sync = NULL;
>  mfxStatus err;
>  
> +while (!s->session_upload_init && !s->session_upload) {
> + if (atomic_fetch_add(>session_upload_init, 1) == 0) {
> +qsv_init_internal_session(ctx, >session_upload, 1);
> +}
> + else {
> +av_usleep(1);
> +}
> +}
> +
>  if (!s->session_upload) {
>  if (s->child_frames_ref)
>  return qsv_transfer_data_child(ctx, dst, src);
> 

Thanks,

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

Re: [libav-devel] [PATCH v3] qsvvpp: Fix to perform full init only when needed

2018-07-16 Thread Mark Thompson
On 16/07/18 23:13, Maxym Dmytrychenko wrote:
> On Tue, Jul 17, 2018 at 12:00 AM Mark Thompson  wrote:
> 
>> On 16/07/18 14:26, Maxym Dmytrychenko wrote:
>>> Not used VPP sessions, like for hwupload/hwdownload handling,
>>> can increase CPU utilization and this patch fixes it.
>>> thank you,Joe, for the contribution.
>>>
>>> Signed-off-by: Maxym Dmytrychenko 
>>> ---
>>>  libavutil/hwcontext_qsv.c | 35 ++-
>>>  1 file changed, 26 insertions(+), 9 deletions(-)
>>
>> This makes sense, but it looks like it might need some sort of 'once'
>> construction for thread-safety?
>>
>> I believe the current API intent is that performing simultaneous transfer
>> operations on different frames in the same frames context should be safe.
>>
>> good point!
> So far, I see pretty much always the same thread, so like single threaded
> usage, unless I am missing something.
> should we consider this implementation ok and to remember: if
> multithreading support - to be adjusted?

Well, the code is currently (I believe) thread-safe and this patch looks like 
it would change it not to be.  While I don't think avconv ever hits this case, 
API users certainly can.

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

Re: [libav-devel] [PATCH v3] qsvvpp: Fix to perform full init only when needed

2018-07-16 Thread Mark Thompson
On 16/07/18 14:26, Maxym Dmytrychenko wrote:
> Not used VPP sessions, like for hwupload/hwdownload handling,
> can increase CPU utilization and this patch fixes it.
> thank you,Joe, for the contribution.
> 
> Signed-off-by: Maxym Dmytrychenko 
> ---
>  libavutil/hwcontext_qsv.c | 35 ++-
>  1 file changed, 26 insertions(+), 9 deletions(-)

This makes sense, but it looks like it might need some sort of 'once' 
construction for thread-safety?

I believe the current API intent is that performing simultaneous transfer 
operations on different frames in the same frames context should be safe.


> diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
> index b3eb4a3ea..3e6c38037 100644
> --- a/libavutil/hwcontext_qsv.c
> +++ b/libavutil/hwcontext_qsv.c
> @@ -56,7 +56,9 @@ typedef struct QSVDeviceContext {
>  
>  typedef struct QSVFramesContext {
>  mfxSession session_download;
> +int session_download_init;
>  mfxSession session_upload;
> +int session_upload_init;
>  
>  AVBufferRef *child_frames_ref;
>  mfxFrameSurface1 *surfaces_internal;
> @@ -146,13 +148,15 @@ static void qsv_frames_uninit(AVHWFramesContext *ctx)
>  MFXVideoVPP_Close(s->session_download);
>  MFXClose(s->session_download);
>  }
> -s->session_download = NULL;
> +s->session_download  = NULL;
> +s->session_download_init = 0;
>  
>  if (s->session_upload) {
>  MFXVideoVPP_Close(s->session_upload);
>  MFXClose(s->session_upload);
>  }
> -s->session_upload = NULL;
> +s->session_upload  = NULL;
> +s->session_upload_init = 0;
>  
>  av_freep(>mem_ids);
>  av_freep(>surface_ptrs);
> @@ -535,13 +539,10 @@ static int qsv_frames_init(AVHWFramesContext *ctx)
>  s->mem_ids[i] = frames_hwctx->surfaces[i].Data.MemId;
>  }
>  
> -ret = qsv_init_internal_session(ctx, >session_download, 0);
> -if (ret < 0)
> -return ret;
> -
> -ret = qsv_init_internal_session(ctx, >session_upload, 1);
> -if (ret < 0)
> -return ret;
> +s->session_download  = NULL;
> +s->session_upload= NULL;
> +s->session_download_init = 0;
> +s->session_upload_init   = 0;
>  
>  return 0;
>  }
> @@ -740,6 +741,14 @@ static int qsv_transfer_data_from(AVHWFramesContext 
> *ctx, AVFrame *dst,
>  
>  mfxSyncPoint sync = NULL;
>  mfxStatus err;
> +int ret = -1;

The initialisation is redundant?  The -1 confused me, but I don't think it's 
ever read anywhere.

> +
> +if (!s->session_download_init) {
> +s->session_download_init = 1;
> +ret = qsv_init_internal_session(ctx, >session_download, 0);
> +if (ret < 0)
> +return ret;
> +}
>  
>  if (!s->session_download) {
>  if (s->child_frames_ref)
> @@ -787,6 +796,14 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, 
> AVFrame *dst,
>  
>  mfxSyncPoint sync = NULL;
>  mfxStatus err;
> +int ret = -1;
Likewise this one.

> +
> +if (!s->session_upload_init) {
> +s->session_upload_init = 1;
> +ret = qsv_init_internal_session(ctx, >session_upload, 1);
> +if (ret < 0)
> +return ret;
> +}
>  
>  if (!s->session_upload) {
>  if (s->child_frames_ref)
> 

Thanks,

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

Re: [libav-devel] [PATCH V2 2/3] lavu/hwcontext_qsv: Add support for pix_fmt RGB32.

2018-04-02 Thread Mark Thompson
On 02/04/18 10:32, Li, Zhong wrote:
>>> diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
>>> index 5018a05..0db446b 100644
>>> --- a/libavutil/hwcontext_qsv.c
>>> +++ b/libavutil/hwcontext_qsv.c
>>> ...
>>> +surface->Data.Y  = frame->data[0];
>>> +surface->Data.UV = frame->data[1];
>>> +break;
>>> +
>>> +case AV_PIX_FMT_YUV420P:
>>> +surface->Data.Y = frame->data[0];
>>> +surface->Data.U = frame->data[1];
>>> +surface->Data.V = frame->data[2];
>>> +break;
>>> +
>>> +case AV_PIX_FMT_RGB32:
>>> +surface->Data.B = frame->data[0];
>>> +surface->Data.G = frame->data[0] + 1;
>>> +surface->Data.R = frame->data[0] + 2;
>>> +surface->Data.A = frame->data[0] + 3;
>>> +break;
>>> +
>>> +default:
>>> +return MFX_ERR_UNSUPPORTED;
>>> +}
>>> +surface->Data.Pitch = frame->linesize[0];
>>
>> What happens if linesize[0] != linesize[1]?  (You aren't introducing that
>> problem, but I hadn't seen it before.)
> 
> I don't think MSDK can handle this case perfectly since there is only one 
> pitch.
> Take YUV420p as example, IMHO it is required linesize of Y must be twice of U 
> and V.

That isn't going to be true for a general frame in libav - the pitches for each 
plane are independent.  Since they are usually created by taking the width of 
the plane and rounding up to the appropriate alignment (usually 32, I think) it 
will work for widths which are multiples of large powers of two - e.g. 1920 
width will work because both 1920 and 960 are already aligned to a 32-byte 
boundary.  It won't work for less aligned widths (e.g. 720 width from NTSC or 
PAL will give luma pitch = align(720, 32) = 736 but chroma pitch = align(360, 
32) = 384), nor will it work for other ways of laying out the frame such as 
line-interleaving.

This problem was preexisting, though, so I guess it isn't necessary to deal 
with it in this patch.  Not sure what the right answer is - maybe it could just 
reject non-matching pitches and return an error?  Or it could make a temporary 
frame with the stricter alignment and copy to that before uploading?  (Though 
that might be slow and defeat the point of this upload path.)

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

Re: [libav-devel] [PATCH V2 2/3] lavu/hwcontext_qsv: Add support for pix_fmt RGB32.

2018-03-29 Thread Mark Thompson
On 22/03/18 14:41, Zhong Li wrote:
> RGB32 format may be used as overlay with alpha blending.
> So add RGB32 format support.
> 
> Signed-off-by: ChaoX A Liu 
> Signed-off-by: Zhong Li 
> ---
>  libavutil/hwcontext_qsv.c | 43 +--
>  1 file changed, 33 insertions(+), 10 deletions(-)

Please write BGRA rather than RGB32.  I doubt this will ever run on a 
big-endian machine, but it would be clearer.

> diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
> index 5018a05..0db446b 100644
> --- a/libavutil/hwcontext_qsv.c
> +++ b/libavutil/hwcontext_qsv.c
> @@ -90,6 +90,7 @@ static const struct {
>  uint32_t   fourcc;
>  } supported_pixel_formats[] = {
>  { AV_PIX_FMT_NV12, MFX_FOURCC_NV12 },
> +{ AV_PIX_FMT_RGB32,MFX_FOURCC_RGB4 },
>  { AV_PIX_FMT_P010, MFX_FOURCC_P010 },
>  { AV_PIX_FMT_PAL8, MFX_FOURCC_P8   },
>  };
> @@ -730,6 +731,36 @@ static int qsv_transfer_data_child(AVHWFramesContext 
> *ctx, AVFrame *dst,
>  return ret;
>  }
>  
> +static int map_frame_to_surface(const AVFrame *frame, mfxFrameSurface1 
> *surface)
> +{
> +switch (frame->format) {
> +case AV_PIX_FMT_NV12:

Indentation - case labels should be at the same level as switch.

> +surface->Data.Y  = frame->data[0];
> +surface->Data.UV = frame->data[1];
> +break;
> +
> +case AV_PIX_FMT_YUV420P:
> +surface->Data.Y = frame->data[0];
> +surface->Data.U = frame->data[1];
> +surface->Data.V = frame->data[2];
> +break;
> +
> +case AV_PIX_FMT_RGB32:
> +surface->Data.B = frame->data[0];
> +surface->Data.G = frame->data[0] + 1;
> +surface->Data.R = frame->data[0] + 2;
> +surface->Data.A = frame->data[0] + 3;
> +break;
> +
> +default:
> +return MFX_ERR_UNSUPPORTED;
> +}
> +surface->Data.Pitch = frame->linesize[0];

What happens if linesize[0] != linesize[1]?  (You aren't introducing that 
problem, but I hadn't seen it before.)

> +surface->Data.TimeStamp = frame->pts;
> +
> +return 0;
> +}
> +
>  static int qsv_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst,
>const AVFrame *src)
>  {
> @@ -749,11 +780,7 @@ static int qsv_transfer_data_from(AVHWFramesContext 
> *ctx, AVFrame *dst,
>  }
>  
>  out.Info = in->Info;
> -out.Data.PitchLow = dst->linesize[0];
> -out.Data.Y= dst->data[0];
> -out.Data.U= dst->data[1];
> -out.Data.V= dst->data[2];
> -out.Data.A= dst->data[3];
> +map_frame_to_surface(dst, );
>  
>  do {
>  err = MFXVideoVPP_RunFrameVPPAsync(s->session_download, in, , 
> NULL, );
> @@ -796,11 +823,7 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, 
> AVFrame *dst,
>  }
>  
>  in.Info = out->Info;
> -in.Data.PitchLow = src->linesize[0];
> -in.Data.Y= src->data[0];
> -in.Data.U= src->data[1];
> -in.Data.V= src->data[2];
> -in.Data.A= src->data[3];
> +map_frame_to_surface(src, );
>  
>  do {
>  err = MFXVideoVPP_RunFrameVPPAsync(s->session_upload, , out, 
> NULL, );
> 

This has slightly changed what gets passed for YUV420P and NV12 - it no longer 
sets the unused pointers to NULL.  Presumably that's always ok, even with old 
versions?

Thanks,

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

Re: [libav-devel] [PATCH] qsv: adding Multi Frame Encode support

2018-03-28 Thread Mark Thompson
On 27/03/18 23:07, Maxym Dmytrychenko wrote:
> On Tue, Mar 27, 2018 at 12:47 AM, Mark Thompson <s...@jkqxz.net> wrote:
> 
>> On 26/03/18 21:18, Maxym Dmytrychenko wrote:
>>> Starting from API 1.25 helps to improve performance of the simultaneous
>> encode,
>>> 1:N scenario, like:
>>>
>>> ./avconv  -y -hwaccel qsv -c:v h264_qsv -r 3/1001 -i
>>> ~/bbb_sunflower_1080p_60fps_normal.mp4  -vframes 600 -an \
>>> -filter_complex "split=2[s1][s2]; [s1]scale_qsv=1280:720[o1];
>>> [s2]scale_qsv=960:540[o2]" \
>>> -map [o1] -c:v h264_qsv -b:v 3200k -minrate 3200k -maxrate 3200k -f
>>> rawvideo /tmp/3200a.264 \
>>> -map [o2] -c:v h264_qsv -b:v 1750k -minrate 1750k -maxrate 1750k -f
>>> rawvideo /tmp/1750a.264
>>
>> Having seen this interface being added form the VAAPI side, I got the
>> impression that this only makes sense if the parallel streams are actually
>> in lock-step (as in your example).  What will happen if this isn't the case?
>>
> thanks for the points, Mark.
> it is actually testing phase but can you share more details over example(s)
> you mean?

Well, your example has two streams which encode exactly in parallel - in every 
step both streams encode one frame.

I don't know what the implementation inside libmfx is, but suppose the streams 
don't run at the same rate, e.g. if one stream is twice as fast as the other as 
in (with libx264):

./avconv -y -i in.mp4 -an -filter_complex 'split=2[a][b]' -map '[a]' -r 10 -c:v 
libx264 out_10.mp4 -map '[b]' -r 20 -c:v libx264 out_20.mp4

Does everything still work as expected?

As a worse case, suppose you have multiple input streams with unknown 
properties (including framerate) which want to be encoded with low-latency, 
does setting this option affect that latency because some streams wait for new 
frames to appear on others?

(These questions are primarily trying to assess whether this should be enabled 
by default.)

>> I'm also curious what the gain from this is, if you happen to have some
>> numbers...
>>
> Actually depends on exact HW SKU and resolution/scenario, however, can be
> well above 10%
> 
> 
>>> ---
>>>  libavcodec/qsv.c | 10 ++
>>>  libavcodec/qsv_internal.h|  3 +++
>>>  libavcodec/qsvdec.c  |  1 -
>>>  libavcodec/qsvenc.c  | 16 +++-
>>>  libavcodec/qsvenc.h  | 12 ++--
>>>  libavcodec/qsvenc_h264.c |  4 
>>>  libavfilter/qsvvpp.c |  9 ++---
>>>  libavfilter/qsvvpp.h |  7 +++
>>>  libavfilter/vf_deinterlace_qsv.c |  6 ++
>>>  libavfilter/vf_scale_qsv.c   |  6 ++
>>>  libavutil/hwcontext_qsv.c|  5 +
>>>  libavutil/hwcontext_qsv.h|  3 +++
>>>  12 files changed, 71 insertions(+), 11 deletions(-)
>>>
>>> diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
>>> index e78633d62..bab32836e 100644
>>> --- a/libavcodec/qsv.c
>>> +++ b/libavcodec/qsv.c
>>> @@ -593,10 +593,12 @@ int ff_qsv_init_session_device(AVCodecContext
>> *avctx, mfxSession *psession,
>>>"Error setting a HW handle");
>>>  }
>>>
>>> -err = MFXJoinSession(parent_session, session);
>>> -if (err != MFX_ERR_NONE)
>>> -return ff_qsv_print_error(avctx, err,
>>> -  "Error joining session");
>>> +if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
>>> +err = MFXJoinSession(parent_session, session);
>>> +if (err != MFX_ERR_NONE)
>>> +return ff_qsv_print_error(avctx, err,
>>> +  "Error joining session");
>>> +}
>>>
>>>  ret = qsv_load_plugins(session, load_plugins, avctx);
>>>  if (ret < 0) {
>>> diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
>>> index 975c8de44..516994a64 100644
>>> --- a/libavcodec/qsv_internal.h
>>> +++ b/libavcodec/qsv_internal.h
>>> @@ -36,6 +36,9 @@
>>>  (MFX_VERSION_MAJOR > (MAJOR) || \
>>>   MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
>>>
>>> +#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR) \
>>> +(MFX_VERSION.Major == MAJOR  && MFX_VERSION.Minor >= MINOR)
>>> +
>>>  typedef struct QSVMid {
>>>  AVBufferRef *hw_frames_ref;
>>>  mfxHDL handle;
>>

Re: [libav-devel] [PATCH] qsv: adding Multi Frame Encode support

2018-03-26 Thread Mark Thompson
On 26/03/18 21:18, Maxym Dmytrychenko wrote:
> Starting from API 1.25 helps to improve performance of the simultaneous 
> encode,
> 1:N scenario, like:
> 
> ./avconv  -y -hwaccel qsv -c:v h264_qsv -r 3/1001 -i
> ~/bbb_sunflower_1080p_60fps_normal.mp4  -vframes 600 -an \
> -filter_complex "split=2[s1][s2]; [s1]scale_qsv=1280:720[o1];
> [s2]scale_qsv=960:540[o2]" \
> -map [o1] -c:v h264_qsv -b:v 3200k -minrate 3200k -maxrate 3200k -f
> rawvideo /tmp/3200a.264 \
> -map [o2] -c:v h264_qsv -b:v 1750k -minrate 1750k -maxrate 1750k -f
> rawvideo /tmp/1750a.264

Having seen this interface being added form the VAAPI side, I got the 
impression that this only makes sense if the parallel streams are actually in 
lock-step (as in your example).  What will happen if this isn't the case?

I'm also curious what the gain from this is, if you happen to have some 
numbers...

> ---
>  libavcodec/qsv.c | 10 ++
>  libavcodec/qsv_internal.h|  3 +++
>  libavcodec/qsvdec.c  |  1 -
>  libavcodec/qsvenc.c  | 16 +++-
>  libavcodec/qsvenc.h  | 12 ++--
>  libavcodec/qsvenc_h264.c |  4 
>  libavfilter/qsvvpp.c |  9 ++---
>  libavfilter/qsvvpp.h |  7 +++
>  libavfilter/vf_deinterlace_qsv.c |  6 ++
>  libavfilter/vf_scale_qsv.c   |  6 ++
>  libavutil/hwcontext_qsv.c|  5 +
>  libavutil/hwcontext_qsv.h|  3 +++
>  12 files changed, 71 insertions(+), 11 deletions(-)
> 
> diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
> index e78633d62..bab32836e 100644
> --- a/libavcodec/qsv.c
> +++ b/libavcodec/qsv.c
> @@ -593,10 +593,12 @@ int ff_qsv_init_session_device(AVCodecContext *avctx, 
> mfxSession *psession,
>"Error setting a HW handle");
>  }
>  
> -err = MFXJoinSession(parent_session, session);
> -if (err != MFX_ERR_NONE)
> -return ff_qsv_print_error(avctx, err,
> -  "Error joining session");
> +if (QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 25)) {
> +err = MFXJoinSession(parent_session, session);
> +if (err != MFX_ERR_NONE)
> +return ff_qsv_print_error(avctx, err,
> +  "Error joining session");
> +}
>  
>  ret = qsv_load_plugins(session, load_plugins, avctx);
>  if (ret < 0) {
> diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
> index 975c8de44..516994a64 100644
> --- a/libavcodec/qsv_internal.h
> +++ b/libavcodec/qsv_internal.h
> @@ -36,6 +36,9 @@
>  (MFX_VERSION_MAJOR > (MAJOR) || \
>   MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
>  
> +#define QSV_RUNTIME_VERSION_ATLEAST(MFX_VERSION, MAJOR, MINOR) \
> +(MFX_VERSION.Major == MAJOR  && MFX_VERSION.Minor >= MINOR)
> +
>  typedef struct QSVMid {
>  AVBufferRef *hw_frames_ref;
>  mfxHDL handle;
> diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
> index f31172de2..b45216291 100644
> --- a/libavcodec/qsvdec.c
> +++ b/libavcodec/qsvdec.c
> @@ -332,7 +332,6 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext 
> *q,
>  av_freep();
>  return ret;
>  }
> -

Stray change.

>  ret = MFXVideoDECODE_DecodeFrameAsync(q->session, avpkt->size ?  
> : NULL,
>insurf, , sync);
>  if (ret == MFX_WRN_DEVICE_BUSY)
> diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
> index f6b1a0d67..a8b446c5b 100644
> --- a/libavcodec/qsvenc.c
> +++ b/libavcodec/qsvenc.c
> @@ -135,7 +135,7 @@ static void dump_video_param(AVCodecContext *avctx, 
> QSVEncContext *q,
>  #if QSV_HAVE_CO2
>  mfxExtCodingOption2 *co2 = (mfxExtCodingOption2*)coding_opts[1];
>  #endif
> -#if QSV_HAVE_CO3
> +#if QSV_HAVE_CO3 && QSV_HAVE_QVBR
>  mfxExtCodingOption3 *co3 = (mfxExtCodingOption3*)coding_opts[2];
>  #endif
>  
> @@ -656,6 +656,20 @@ FF_ENABLE_DEPRECATION_WARNINGS
>  
>  q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer 
> *)>extco2;
>  }
> +#endif
> +#if QSV_HAVE_MF
> +if (avctx->codec_id == AV_CODEC_ID_H264) {
> +mfxVersionver;
> +ret = MFXQueryVersion(q->session,);
> +if (ret >= MFX_ERR_NONE && QSV_RUNTIME_VERSION_ATLEAST(ver, 1, 
> 25)) {
> +q->extmfp.Header.BufferId = 
> MFX_EXTBUFF_MULTI_FRAME_PARAM;
> +q->extmfp.Header.BufferSz = sizeof(q->extmfp);
> +
> +q->extmfp.MFMode = q->mfmode;
> +av_log(avctx,AV_LOG_VERBOSE,"MFMode:%d\n", q->extmfp.MFMode);
> +q->extparam_internal[q->nb_extparam_internal++] = 
> (mfxExtBuffer *)>extmfp;
> +}
> +}

Why is this conditioned on H.264?  The API won't be different for other codecs, 
will it?

>  #endif
>  }
>  
> diff --git a/libavcodec/qsvenc.h b/libavcodec/qsvenc.h
> index 

[libav-devel] [PATCH 4/5] vf_crop: Add support for cropping VAAPI hardware frames

2018-03-06 Thread Mark Thompson
---
 libavfilter/vf_crop.c | 51 +--
 1 file changed, 33 insertions(+), 18 deletions(-)

diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c
index 4122d52f8..abc27c8de 100644
--- a/libavfilter/vf_crop.c
+++ b/libavfilter/vf_crop.c
@@ -107,6 +107,7 @@ static int query_formats(AVFilterContext *ctx)
 AV_PIX_FMT_RGB8, AV_PIX_FMT_BGR8,
 AV_PIX_FMT_RGB4_BYTE,AV_PIX_FMT_BGR4_BYTE,
 AV_PIX_FMT_PAL8, AV_PIX_FMT_GRAY8,
+AV_PIX_FMT_VAAPI,
 AV_PIX_FMT_NONE
 };
 
@@ -162,8 +163,14 @@ static int config_input(AVFilterLink *link)
 s->var_values[VAR_T] = NAN;
 
 av_image_fill_max_pixsteps(s->max_step, NULL, pix_desc);
-s->hsub = pix_desc->log2_chroma_w;
-s->vsub = pix_desc->log2_chroma_h;
+
+if (pix_desc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
+s->hsub = 1;
+s->vsub = 1;
+} else {
+s->hsub = pix_desc->log2_chroma_w;
+s->vsub = pix_desc->log2_chroma_h;
+}
 
 if ((ret = av_expr_parse_and_eval(, (expr = s->ow_expr),
   var_names, s->var_values,
@@ -242,9 +249,6 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame)
 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
 int i;
 
-frame->width  = s->w;
-frame->height = s->h;
-
 s->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ?
 NAN : frame->pts * av_q2d(link->time_base);
 s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, NULL);
@@ -269,22 +273,33 @@ static int filter_frame(AVFilterLink *link, AVFrame 
*frame)
 (int)s->var_values[VAR_N], s->var_values[VAR_T], s->x,
 s->y, s->x+s->w, s->y+s->h);
 
-frame->data[0] += s->y * frame->linesize[0];
-frame->data[0] += s->x * s->max_step[0];
-
-if (!(desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & 
AV_PIX_FMT_FLAG_PSEUDOPAL)) {
-for (i = 1; i < 3; i ++) {
-if (frame->data[i]) {
-frame->data[i] += (s->y >> s->vsub) * frame->linesize[i];
-frame->data[i] += (s->x * s->max_step[i]) >> s->hsub;
+if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
+frame->crop_top   += s->y;
+frame->crop_left  += s->x;
+frame->crop_bottom = frame->height - frame->crop_top - 
frame->crop_bottom - s->h;
+frame->crop_right  = frame->width  - frame->crop_left - 
frame->crop_right - s->w;
+
+} else {
+frame->width  = s->w;
+frame->height = s->h;
+
+frame->data[0] += s->y * frame->linesize[0];
+frame->data[0] += s->x * s->max_step[0];
+
+if (!(desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & 
AV_PIX_FMT_FLAG_PSEUDOPAL)) {
+for (i = 1; i < 3; i ++) {
+if (frame->data[i]) {
+frame->data[i] += (s->y >> s->vsub) * frame->linesize[i];
+frame->data[i] += (s->x * s->max_step[i]) >> s->hsub;
+}
 }
 }
-}
 
-/* alpha plane */
-if (frame->data[3]) {
-frame->data[3] += s->y * frame->linesize[3];
-frame->data[3] += s->x * s->max_step[3];
+/* alpha plane */
+if (frame->data[3]) {
+frame->data[3] += s->y * frame->linesize[3];
+frame->data[3] += s->x * s->max_step[3];
+}
 }
 
 s->var_values[VAR_N] += 1.0;
-- 
2.16.1

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

[libav-devel] [PATCH 5/5] vf_scale_vaapi: Apply cropping rectangle to input

2018-03-06 Thread Mark Thompson
---
 libavfilter/vf_scale_vaapi.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c
index e92df44ba..6bd54d822 100644
--- a/libavfilter/vf_scale_vaapi.c
+++ b/libavfilter/vf_scale_vaapi.c
@@ -74,13 +74,13 @@ static int scale_vaapi_filter_frame(AVFilterLink *inlink, 
AVFrame *input_frame)
 
 memset(, 0, sizeof(params));
 
-// If there were top/left cropping, it could be taken into
-// account here.
 input_region = (VARectangle) {
-.x  = 0,
-.y  = 0,
-.width  = input_frame->width,
-.height = input_frame->height,
+.x  = input_frame->crop_left,
+.y  = input_frame->crop_top,
+.width  = input_frame->width -
+ (input_frame->crop_left + input_frame->crop_right),
+.height = input_frame->height -
+ (input_frame->crop_top + input_frame->crop_bottom),
 };
 
 params.surface = input_surface;
-- 
2.16.1

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

[libav-devel] [PATCH 3/5] lavfi: use common VAAPI VPP infrastructure for vf_deinterlace_vaapi

2018-03-06 Thread Mark Thompson
From: Jun Zhao <jun.z...@intel.com>

From ffmpeg commit 92704c480e811e0bd2a605173559d2baa974119f.

Signed-off-by: Mark Thompson <s...@jkqxz.net>
---
 libavfilter/Makefile   |   2 +-
 libavfilter/vf_deinterlace_vaapi.c | 341 +
 2 files changed, 46 insertions(+), 297 deletions(-)

diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 4e86b8112..7701c7235 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -52,7 +52,7 @@ OBJS-$(CONFIG_COPY_FILTER)   += vf_copy.o
 OBJS-$(CONFIG_CROP_FILTER)   += vf_crop.o
 OBJS-$(CONFIG_CROPDETECT_FILTER) += vf_cropdetect.o
 OBJS-$(CONFIG_DEINTERLACE_QSV_FILTER)+= vf_deinterlace_qsv.o
-OBJS-$(CONFIG_DEINTERLACE_VAAPI_FILTER)  += vf_deinterlace_vaapi.o
+OBJS-$(CONFIG_DEINTERLACE_VAAPI_FILTER)  += vf_deinterlace_vaapi.o 
vaapi_vpp.o
 OBJS-$(CONFIG_DELOGO_FILTER) += vf_delogo.o
 OBJS-$(CONFIG_DRAWBOX_FILTER)+= vf_drawbox.o
 OBJS-$(CONFIG_DRAWTEXT_FILTER)   += vf_drawtext.o
diff --git a/libavfilter/vf_deinterlace_vaapi.c 
b/libavfilter/vf_deinterlace_vaapi.c
index 082df8914..154bdcdcb 100644
--- a/libavfilter/vf_deinterlace_vaapi.c
+++ b/libavfilter/vf_deinterlace_vaapi.c
@@ -18,13 +18,8 @@
 
 #include 
 
-#include 
-#include 
-
 #include "libavutil/avassert.h"
 #include "libavutil/common.h"
-#include "libavutil/hwcontext.h"
-#include "libavutil/hwcontext_vaapi.h"
 #include "libavutil/mem.h"
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
@@ -33,29 +28,17 @@
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
+#include "vaapi_vpp.h"
 
 #define MAX_REFERENCES 8
 
 typedef struct DeintVAAPIContext {
-const AVClass *class;
-
-AVVAAPIDeviceContext *hwctx;
-AVBufferRef   *device_ref;
+VAAPIVPPContext vpp_ctx; // must be the first field
 
 intmode;
 intfield_rate;
 intauto_enable;
 
-intvalid_ids;
-VAConfigID va_config;
-VAContextIDva_context;
-
-AVBufferRef   *input_frames_ref;
-AVHWFramesContext *input_frames;
-
-intoutput_height;
-intoutput_width;
-
 VAProcFilterCapDeinterlacing
deint_caps[VAProcDeinterlacingCount];
 int nb_deint_caps;
@@ -65,8 +48,6 @@ typedef struct DeintVAAPIContext {
 intqueue_count;
 AVFrame   *frame_queue[MAX_REFERENCES];
 intextra_delay_for_timestamps;
-
-VABufferID filter_buffer;
 } DeintVAAPIContext;
 
 static const char *deint_vaapi_mode_name(int mode)
@@ -83,21 +64,7 @@ static const char *deint_vaapi_mode_name(int mode)
 }
 }
 
-static int deint_vaapi_query_formats(AVFilterContext *avctx)
-{
-enum AVPixelFormat pix_fmts[] = {
-AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE,
-};
-
-ff_formats_ref(ff_make_format_list(pix_fmts),
-   >inputs[0]->out_formats);
-ff_formats_ref(ff_make_format_list(pix_fmts),
-   >outputs[0]->in_formats);
-
-return 0;
-}
-
-static int deint_vaapi_pipeline_uninit(AVFilterContext *avctx)
+static void deint_vaapi_pipeline_uninit(AVFilterContext *avctx)
 {
 DeintVAAPIContext *ctx = avctx->priv;
 int i;
@@ -106,56 +73,20 @@ static int deint_vaapi_pipeline_uninit(AVFilterContext 
*avctx)
 av_frame_free(>frame_queue[i]);
 ctx->queue_count = 0;
 
-if (ctx->filter_buffer != VA_INVALID_ID) {
-vaDestroyBuffer(ctx->hwctx->display, ctx->filter_buffer);
-ctx->filter_buffer = VA_INVALID_ID;
-}
-
-if (ctx->va_context != VA_INVALID_ID) {
-vaDestroyContext(ctx->hwctx->display, ctx->va_context);
-ctx->va_context = VA_INVALID_ID;
-}
-
-if (ctx->va_config != VA_INVALID_ID) {
-vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
-ctx->va_config = VA_INVALID_ID;
-}
-
-av_buffer_unref(>device_ref);
-ctx->hwctx = NULL;
-
-return 0;
-}
-
-static int deint_vaapi_config_input(AVFilterLink *inlink)
-{
-AVFilterContext   *avctx = inlink->dst;
-DeintVAAPIContext *ctx = avctx->priv;
-
-deint_vaapi_pipeline_uninit(avctx);
-
-if (!inlink->hw_frames_ctx) {
-av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
-   "required to associate the processing device.\n");
-return AVERROR(EINVAL);
-}
-
-ctx->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx);
-ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data;
-
-return 0;
+ff_vaapi_vpp_pipeline_uninit(avctx);
 }
 
 static int deint_vaapi_build_filter_params(AVFil

[libav-devel] [PATCH 1/5] lavfi: VAAPI VPP common infrastructure.

2018-03-06 Thread Mark Thompson
From: Jun Zhao <jun.z...@intel.com>

Re-work the VAAPI common infrastructure to avoid code duplication
between filters.

From ffmpeg commit dfdeed5a2c8f432d6c5eda1a3a6a1f333f3d4604.

Signed-off-by: Mark Thompson <s...@jkqxz.net>
---
 libavfilter/Makefile|   1 +
 libavfilter/vaapi_vpp.c | 365 
 libavfilter/vaapi_vpp.h |  79 +++
 3 files changed, 445 insertions(+)
 create mode 100644 libavfilter/vaapi_vpp.c
 create mode 100644 libavfilter/vaapi_vpp.h

diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 827762677..def485d86 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -110,6 +110,7 @@ OBJS-$(CONFIG_RGBTESTSRC_FILTER) += 
vsrc_testsrc.o
 OBJS-$(CONFIG_TESTSRC_FILTER)+= vsrc_testsrc.o
 
 SKIPHEADERS-$(CONFIG_QSVVPP) += qsvvpp.h
+SKIPHEADERS-$(CONFIG_VAAPI)  += vaapi_vpp.h
 
 TOOLS = graph2dot
 TESTPROGS = filtfmts
diff --git a/libavfilter/vaapi_vpp.c b/libavfilter/vaapi_vpp.c
new file mode 100644
index 0..66a053471
--- /dev/null
+++ b/libavfilter/vaapi_vpp.c
@@ -0,0 +1,365 @@
+/*
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include 
+
+#include "config.h"
+
+#include "libavutil/avassert.h"
+#include "libavutil/mem.h"
+#include "libavutil/pixdesc.h"
+
+#include "formats.h"
+#include "internal.h"
+#include "vaapi_vpp.h"
+
+int ff_vaapi_vpp_query_formats(AVFilterContext *avctx)
+{
+enum AVPixelFormat pix_fmts[] = {
+AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE,
+};
+
+ff_set_common_formats(avctx, ff_make_format_list(pix_fmts));
+
+return 0;
+}
+
+void ff_vaapi_vpp_pipeline_uninit(AVFilterContext *avctx)
+{
+VAAPIVPPContext *ctx = avctx->priv;
+int i;
+for (i = 0; i < ctx->nb_filter_buffers; i++) {
+if (ctx->filter_buffers[i] != VA_INVALID_ID) {
+vaDestroyBuffer(ctx->hwctx->display, ctx->filter_buffers[i]);
+ctx->filter_buffers[i] = VA_INVALID_ID;
+}
+}
+ctx->nb_filter_buffers = 0;
+
+if (ctx->va_context != VA_INVALID_ID) {
+vaDestroyContext(ctx->hwctx->display, ctx->va_context);
+ctx->va_context = VA_INVALID_ID;
+}
+
+if (ctx->va_config != VA_INVALID_ID) {
+vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
+ctx->va_config = VA_INVALID_ID;
+}
+
+av_buffer_unref(>device_ref);
+ctx->hwctx = NULL;
+}
+
+int ff_vaapi_vpp_config_input(AVFilterLink *inlink)
+{
+AVFilterContext *avctx = inlink->dst;
+VAAPIVPPContext *ctx   = avctx->priv;
+
+if (ctx->pipeline_uninit)
+ctx->pipeline_uninit(avctx);
+
+if (!inlink->hw_frames_ctx) {
+av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
+   "required to associate the processing device.\n");
+return AVERROR(EINVAL);
+}
+
+ctx->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx);
+if (!ctx->input_frames_ref)
+return AVERROR(ENOMEM);
+ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data;
+
+return 0;
+}
+
+int ff_vaapi_vpp_config_output(AVFilterLink *outlink)
+{
+AVFilterContext *avctx = outlink->src;
+VAAPIVPPContext *ctx   = avctx->priv;
+AVVAAPIHWConfig *hwconfig = NULL;
+AVHWFramesConstraints *constraints = NULL;
+AVHWFramesContext *output_frames;
+AVVAAPIFramesContext *va_frames;
+VAStatus vas;
+int err, i;
+
+if (ctx->pipeline_uninit)
+ctx->pipeline_uninit(avctx);
+
+if (!ctx->output_width)
+ctx->output_width  = avctx->inputs[0]->w;
+if (!ctx->output_height)
+ctx->output_height = avctx->inputs[0]->h;
+
+av_assert0(ctx->input_frames);
+ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref);
+if (!ctx->device_ref)
+return AVERROR(ENOMEM);
+ctx->hwctx = ((AVHWDeviceContext*)ctx->device_ref->data)->hwctx;
+
+av_assert0(ctx->va_config == VA_INVALID_ID);
+vas = vaCreateConfig(ctx->hwctx-

[libav-devel] [PATCH 2/5] lavfi: use common VAAPI VPP infrastructure for vf_scale_vaapi

2018-03-06 Thread Mark Thompson
From: Jun Zhao <jun.z...@intel.com>

From ffmpeg commit 19214f005140b0ee7f706509bd3fab47f4af9b90.

Signed-off-by: Mark Thompson <s...@jkqxz.net>
---
 libavfilter/Makefile |   2 +-
 libavfilter/vf_scale_vaapi.c | 333 +--
 2 files changed, 34 insertions(+), 301 deletions(-)

diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index def485d86..4e86b8112 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -84,7 +84,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER)+= 
vf_pixdesctest.o
 OBJS-$(CONFIG_SCALE_FILTER)  += vf_scale.o
 OBJS-$(CONFIG_SCALE_NPP_FILTER)  += vf_scale_npp.o
 OBJS-$(CONFIG_SCALE_QSV_FILTER)  += vf_scale_qsv.o
-OBJS-$(CONFIG_SCALE_VAAPI_FILTER)+= vf_scale_vaapi.o
+OBJS-$(CONFIG_SCALE_VAAPI_FILTER)+= vf_scale_vaapi.o vaapi_vpp.o
 OBJS-$(CONFIG_SELECT_FILTER) += vf_select.o
 OBJS-$(CONFIG_SETDAR_FILTER) += vf_aspect.o
 OBJS-$(CONFIG_SETPTS_FILTER) += setpts.o
diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c
index 0ab5518b5..e92df44ba 100644
--- a/libavfilter/vf_scale_vaapi.c
+++ b/libavfilter/vf_scale_vaapi.c
@@ -18,13 +18,7 @@
 
 #include 
 
-#include 
-#include 
-
 #include "libavutil/avassert.h"
-#include "libavutil/common.h"
-#include "libavutil/hwcontext.h"
-#include "libavutil/hwcontext_vaapi.h"
 #include "libavutil/mem.h"
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
@@ -33,250 +27,49 @@
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
+#include "vaapi_vpp.h"
 
 typedef struct ScaleVAAPIContext {
-const AVClass *class;
-
-AVVAAPIDeviceContext *hwctx;
-AVBufferRef *device_ref;
-
-int valid_ids;
-VAConfigID  va_config;
-VAContextID va_context;
-
-AVBufferRef   *input_frames_ref;
-AVHWFramesContext *input_frames;
+VAAPIVPPContext vpp_ctx; // must be the first field
 
 char *output_format_string;
 enum AVPixelFormat output_format;
 int output_width;
 int output_height;
-
 } ScaleVAAPIContext;
 
 
-static int scale_vaapi_query_formats(AVFilterContext *avctx)
-{
-enum AVPixelFormat pix_fmts[] = {
-AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE,
-};
-
-ff_formats_ref(ff_make_format_list(pix_fmts),
-   >inputs[0]->out_formats);
-ff_formats_ref(ff_make_format_list(pix_fmts),
-   >outputs[0]->in_formats);
-
-return 0;
-}
-
-static int scale_vaapi_pipeline_uninit(ScaleVAAPIContext *ctx)
-{
-if (ctx->va_context != VA_INVALID_ID) {
-vaDestroyContext(ctx->hwctx->display, ctx->va_context);
-ctx->va_context = VA_INVALID_ID;
-}
-
-if (ctx->va_config != VA_INVALID_ID) {
-vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
-ctx->va_config = VA_INVALID_ID;
-}
-
-av_buffer_unref(>device_ref);
-ctx->hwctx = 0;
-
-return 0;
-}
-
-static int scale_vaapi_config_input(AVFilterLink *inlink)
-{
-AVFilterContext *avctx = inlink->dst;
-ScaleVAAPIContext *ctx = avctx->priv;
-
-scale_vaapi_pipeline_uninit(ctx);
-
-if (!inlink->hw_frames_ctx) {
-av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
-   "required to associate the processing device.\n");
-return AVERROR(EINVAL);
-}
-
-ctx->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx);
-ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data;
-
-return 0;
-}
-
-static int scale_vaapi_config_output(AVFilterLink *outlink)
-{
-AVFilterContext *avctx = outlink->src;
-ScaleVAAPIContext *ctx = avctx->priv;
-AVVAAPIHWConfig *hwconfig = NULL;
-AVHWFramesConstraints *constraints = NULL;
-AVHWFramesContext *output_frames;
-AVVAAPIFramesContext *va_frames;
-VAStatus vas;
-int err, i;
-
-scale_vaapi_pipeline_uninit(ctx);
-
-ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref);
-ctx->hwctx = ((AVHWDeviceContext*)ctx->device_ref->data)->hwctx;
-
-av_assert0(ctx->va_config == VA_INVALID_ID);
-vas = vaCreateConfig(ctx->hwctx->display, VAProfileNone,
- VAEntrypointVideoProc, 0, 0, >va_config);
-if (vas != VA_STATUS_SUCCESS) {
-av_log(ctx, AV_LOG_ERROR, "Failed to create processing pipeline "
-   "config: %d (%s).\n", vas, vaErrorStr(vas));
-err = AVERROR(EIO);
-goto fail;
-}
-
-hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref);
-if (!hwconfig) {
-err = AVERROR(ENOMEM);
-goto fail;
-}
-hwconfig->config_id = ctx->va_config;
-
-constraints = av_hwdevice_get_hw

Re: [libav-devel] [libav-commits] qsvenc: Provide a detailed error message if the parameters are invalid

2018-03-05 Thread Mark Thompson
On 05/03/18 09:40, Zhong Li  wrote:
> Module: libav
> Branch: master
> Commit: 2d6b3f3a9dce409ca51d70ef4b85c0593bb4b109
> 
> Author:Zhong Li 
> Committer: Luca Barbato 
> Date:  Fri Mar  2 11:26:27 2018 +0800
> 
> qsvenc: Provide a detailed error message if the parameters are invalid
> 
> Currently it always shows "Selected ratecontrol mode is not supported
> by the QSV runtime. Choose a different mode", but sometimes it is not
> accurate.
> 
> Signed-off-by: Zhong Li 
> Signed-off-by: Luca Barbato 
> 
> ---
> 
>  libavcodec/qsvenc.c | 31 +--
>  1 file changed, 25 insertions(+), 6 deletions(-)
> 
> diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c
> index 16d942f..d4dd4a3 100644
> --- a/libavcodec/qsvenc.c
> +++ b/libavcodec/qsvenc.c
> @@ -356,15 +356,34 @@ static int select_rc_mode(AVCodecContext *avctx, 
> QSVEncContext *q)
>  return 0;
>  }
>  
> -static int rc_supported(QSVEncContext *q)
> +static int check_enc_param(AVCodecContext *avctx, QSVEncContext *q)
>  {
>  mfxVideoParam param_out = { .mfx.CodecId = q->param.mfx.CodecId };
>  mfxStatus ret;
>  
> +#define UNMATCH(x) (param_out.mfx.x != q->param.mfx.x)
> +
>  ret = MFXVideoENCODE_Query(q->session, >param, _out);
> -if (ret < 0 ||
> -param_out.mfx.RateControlMethod != q->param.mfx.RateControlMethod)
> +
> +if (ret < 0) {
> +if (UNMATCH(CodecId))
> +av_log(avctx, AV_LOG_ERROR, "Current codec type is 
> unsupported\n");
> +if (UNMATCH(CodecProfile))
> +av_log(avctx, AV_LOG_ERROR, "Current profile is unsupported\n");
> +if (UNMATCH(RateControlMethod))
> +av_log(avctx, AV_LOG_ERROR, "Selected ratecontrol mode is 
> unsupported\n");
> +if (UNMATCH(LowPower))
> +  av_log(avctx, AV_LOG_ERROR, "Low power mode is unsupported\n");
> +if (UNMATCH(FrameInfo.FrameRateExtN) || 
> UNMATCH(FrameInfo.FrameRateExtN))
> +  av_log(avctx, AV_LOG_ERROR, "Current frame rate is 
> unsupported\n");
> +if (UNMATCH(FrameInfo.PicStruct))
> +  av_log(avctx, AV_LOG_ERROR, "Current picture structure is 
> unsupported\n");
> +if (UNMATCH(FrameInfo.Width) || UNMATCH(FrameInfo.Height))
> +  av_log(avctx, AV_LOG_ERROR, "Current resolution is 
> unsupported\n");
> +if (UNMATCH(FrameInfo.FourCC))
> +  av_log(avctx, AV_LOG_ERROR, "Current pixel format is 
> unsupported\n");
>  return 0;
> +}
>  return 1;
>  }
>  
> @@ -639,10 +658,10 @@ FF_ENABLE_DEPRECATION_WARNINGS
>  #endif
>  }
>  
> -if (!rc_supported(q)) {
> +if (!check_enc_param(avctx,q)) {
>  av_log(avctx, AV_LOG_ERROR,
> -   "Selected ratecontrol mode is not supported by the QSV "
> -   "runtime. Choose a different mode.\n");
> +   "some encoding parameters are not supported by the QSV "
> +   "runtime. Please double check the input parameters.\n");
>  return AVERROR(ENOSYS);
>  }
>  

Testing this a bit, I'm not entirely sure that it's acting in the expected way. 
 For example:

"""
$ LIBVA_DRIVER_NAME=iHD LIBVA_DRIVERS_PATH=/opt/intel/mediasdk/lib64/ DISPLAY= 
./avconv -v 55 -y -i bbb_1080_264.mp4 -an -vf 'scale=7680:4320' -c:v h264_qsv 
-b:v 5M -la_depth 50 -frames:v 1000 out.mp4
avconv version v13_dev0-1487-g2d6b3f3, Copyright (c) 2000-2018 the Libav 
developers
...
[buffer @ 0x375eca0] w:1920 h:1080 pixfmt:yuv420p tb:1/6 sar:1/1
[fps @ 0x3aac380] fps=60/1
[buffersink @ 0x37c79e0] auto-inserting filter 'auto-inserted fifo 0' between 
the filter 'fps for output stream 0:0' and the filter 'output stream 0:0'
[scale @ 0x3ab0300] w:1920 h:1080 fmt:yuv420p -> w:7680 h:4320 fmt:nv12 
flags:0x4
[h264_qsv @ 0x381e660] Initialized an internal MFX session using hardware 
accelerated implementation
[h264_qsv @ 0x381e660] Using the VBR with lookahead (LA) ratecontrol method
libva info: VA-API version 0.99.0
libva info: va_getDriverName() returns 0
libva info: User requested driver 'iHD'
libva info: Trying to open /opt/intel/mediasdk/lib64//iHD_drv_video.so
libva info: Found init function __vaDriverInit_0_32
libva info: va_openDriver() returns 0
[h264_qsv @ 0x381e660] Current profile is unsupported
[h264_qsv @ 0x381e660] Selected ratecontrol mode is unsupported
[h264_qsv @ 0x381e660] Current frame rate is unsupported
[h264_qsv @ 0x381e660] some encoding parameters are not supported by the QSV 
runtime. Please double check the input parameters.
Error initializing output stream 0:0 -- Error while opening encoder for output 
stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height
"""

I was hoping for "resolution is unsupported" there, but that's one thing which 
it didn't reject:

"""
(gdb) p q->param.mfx
$4 = {reserved = {0, 0, 0, 0, 0, 0, 0}, LowPower = 0, BRCParamMultiplier = 0, 
FrameInfo = {reserved 

Re: [libav-devel] [PATCH 1/7] avcodec: Always fill the encoder target framerate

2018-02-21 Thread Mark Thompson
On 16/02/18 17:02, Luca Barbato wrote:
> In preparation of using it in the encoders.
> ---
>  libavcodec/avcodec.h | 3 ++-
>  libavcodec/utils.c   | 5 +
>  2 files changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index 7eaa0c9277..f86ae0b8d6 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -2638,7 +2638,8 @@ typedef struct AVCodecContext {
>   * bitstream, the decoder may export it here. { 0, 1} when
>   * unknown.
>   * - encoding: May be used to signal the framerate of CFR content to an
> - * encoder.
> + * encoder or the target average framerate for rate-control
> + * tuning.
>   */
>  AVRational framerate;
>  
> diff --git a/libavcodec/utils.c b/libavcodec/utils.c
> index ba3457664a..887c5618e2 100644
> --- a/libavcodec/utils.c
> +++ b/libavcodec/utils.c
> @@ -539,6 +539,11 @@ FF_ENABLE_DEPRECATION_WARNINGS
>  goto free_and_end;
>  }
>  
> +if (avctx->framerate.num <= 0) {
> +avctx->framerate.num = avctx->time_base.den;
> +avctx->framerate.den = avctx->time_base.num;
> +}
> +
>  if (avctx->codec->sample_fmts) {
>  for (i = 0; avctx->codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; 
> i++) {
>  if (avctx->sample_fmt == avctx->codec->sample_fmts[i])
> 

How should an encoder detect that its input is actually variable framerate 
after this change and the following one?  Currently it can check for 
!(framerate.{num,den} > 0), but after this change it can't distinguish that 
from the given constrant framerate until it gets some frames (possibly 
arbitrarily many).

Perhaps there should be a flag somewhere (AVCodecContext.flags2, I guess) which 
would distinguish between the two cases?

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

Re: [libav-devel] [PATCH 5/6] vf_crop: Reindent after previous commit

2018-02-15 Thread Mark Thompson
On 15/02/18 09:29, Diego Biurrun wrote:
> On Wed, Feb 14, 2018 at 10:54:30PM +0000, Mark Thompson wrote:
>> ---
>>  libavfilter/vf_crop.c | 30 +++---
>>  1 file changed, 15 insertions(+), 15 deletions(-)
> 
> Just squash it with 4/6 IMO.

Ok, sure.  (The diff is easier to read in this form, at least.)

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

Re: [libav-devel] [PATCH 1/6] lavfi: VAAPI VPP common infrastructure.

2018-02-15 Thread Mark Thompson
On 15/02/18 09:27, Diego Biurrun wrote:
> On Wed, Feb 14, 2018 at 10:54:26PM +0000, Mark Thompson wrote:
>> --- /dev/null
>> +++ b/libavfilter/vaapi_vpp.c
>> @@ -0,0 +1,370 @@
>> +
>> +#include 
>> +
>> +#include "config.h"
> 
> This does not appear to use config.h.

...
+if (HAVE_VAAPI_1 || ctx->hwctx->driver_quirks &
...

>> +#include "libavutil/avassert.h"
>> +#include "libavutil/mem.h"
>> +#include "libavutil/pixdesc.h"
>> +#include "formats.h"
>> +#include "internal.h"
>> +#include "vaapi_vpp.h"
> 
> nit: empty line between header groups
> 
>> +int ff_vaapi_vpp_config_input(AVFilterLink *inlink)
>> +{
>> +ctx->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx);
>> +if (!ctx->input_frames_ref) {
>> +av_log(avctx, AV_LOG_ERROR, "A input frames reference create "
>> +   "failed.\n");
> 
> That sentence sounds ungrammatical to me.

It's ENOMEM, I've just removed the message.

>> +ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data;
> 
> nit: space before *
> 
>> +ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref);
>> +if (!ctx->device_ref) {
>> +av_log(avctx, AV_LOG_ERROR, "A device reference create "
>> +   "failed.\n");
> 
> see above

Likewise.

>> +ctx->hwctx = ((AVHWDeviceContext*)ctx->device_ref->data)->hwctx;
> 
> see above
> 
>> +int ff_vaapi_vpp_colour_standard(enum AVColorSpace av_cs)
>> +{
>> +switch(av_cs) {
> 
> switch (
> 
>> +#define CS(av, va) case AVCOL_SPC_ ## av: return VAProcColorStandard ## va;
>> +CS(BT709, BT709);
>> +CS(BT470BG,   BT601);
>> +CS(SMPTE170M, SMPTE170M);
>> +CS(SMPTE240M, SMPTE240M);
>> +#undef CS
>> +default:
>> +return VAProcColorStandardNone;
>> +}
>> +}
> 
> I don't think the #define eases readability, on the contrary.

Disagree?  In any case, this function isn't really correct because it doesn't 
make use of all of the colour information, and there are also many more cases 
in libva 2.0.  I'll send a fix for that at some point, but for now it's just 
factorising out the code which was previously in individual filters.

>> +int ff_vaapi_vpp_render_picture(AVFilterContext *avctx,
>> +VAProcPipelineParameterBuffer *params,
>> +VASurfaceID output_surface)
>> +{
>> +int err = 0;
>> +VAAPIVPPContext *ctx   = avctx->priv;
> 
> odd extra space
> 
>> +void ff_vaapi_vpp_ctx_init(AVFilterContext *avctx)
>> +{
>> +int i;
>> +VAAPIVPPContext *ctx   = avctx->priv;
> 
> same
> 
>> +void ff_vaapi_vpp_ctx_uninit(AVFilterContext *avctx)
>> +{
>> +VAAPIVPPContext *ctx   = avctx->priv;
> 
> same

Sure, all removed.

>> --- /dev/null
>> +++ b/libavfilter/vaapi_vpp.h
>> @@ -0,0 +1,79 @@
>> +#ifndef AVFILTER_VAAPI_VPP_H
>> +#define AVFILTER_VAAPI_VPP_H
>> +
>> +#include 
>> +#include 
> 
> I think this needs to go in SKIPHEADERS.

Yes.

Thanks,

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

[libav-devel] [PATCH 1/6] lavfi: VAAPI VPP common infrastructure.

2018-02-14 Thread Mark Thompson
From: Jun Zhao <jun.z...@intel.com>

Re-work the VAAPI common infrastructure to avoid code duplication
between filters.

From ffmpeg commit dfdeed5a2c8f432d6c5eda1a3a6a1f333f3d4604.

Signed-off-by: Mark Thompson <s...@jkqxz.net>
---
 libavfilter/vaapi_vpp.c | 370 
 libavfilter/vaapi_vpp.h |  79 +++
 2 files changed, 449 insertions(+)
 create mode 100644 libavfilter/vaapi_vpp.c
 create mode 100644 libavfilter/vaapi_vpp.h

diff --git a/libavfilter/vaapi_vpp.c b/libavfilter/vaapi_vpp.c
new file mode 100644
index 0..5522e1242
--- /dev/null
+++ b/libavfilter/vaapi_vpp.c
@@ -0,0 +1,370 @@
+/*
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include 
+
+#include "config.h"
+
+#include "libavutil/avassert.h"
+#include "libavutil/mem.h"
+#include "libavutil/pixdesc.h"
+#include "formats.h"
+#include "internal.h"
+#include "vaapi_vpp.h"
+
+int ff_vaapi_vpp_query_formats(AVFilterContext *avctx)
+{
+enum AVPixelFormat pix_fmts[] = {
+AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE,
+};
+
+ff_set_common_formats(avctx, ff_make_format_list(pix_fmts));
+
+return 0;
+}
+
+void ff_vaapi_vpp_pipeline_uninit(AVFilterContext *avctx)
+{
+VAAPIVPPContext *ctx   = avctx->priv;
+int i;
+for (i = 0; i < ctx->nb_filter_buffers; i++) {
+if (ctx->filter_buffers[i] != VA_INVALID_ID) {
+vaDestroyBuffer(ctx->hwctx->display, ctx->filter_buffers[i]);
+ctx->filter_buffers[i] = VA_INVALID_ID;
+}
+}
+ctx->nb_filter_buffers = 0;
+
+if (ctx->va_context != VA_INVALID_ID) {
+vaDestroyContext(ctx->hwctx->display, ctx->va_context);
+ctx->va_context = VA_INVALID_ID;
+}
+
+if (ctx->va_config != VA_INVALID_ID) {
+vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
+ctx->va_config = VA_INVALID_ID;
+}
+
+av_buffer_unref(>device_ref);
+ctx->hwctx = NULL;
+}
+
+int ff_vaapi_vpp_config_input(AVFilterLink *inlink)
+{
+AVFilterContext *avctx = inlink->dst;
+VAAPIVPPContext *ctx   = avctx->priv;
+
+if (ctx->pipeline_uninit)
+ctx->pipeline_uninit(avctx);
+
+if (!inlink->hw_frames_ctx) {
+av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
+   "required to associate the processing device.\n");
+return AVERROR(EINVAL);
+}
+
+ctx->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx);
+if (!ctx->input_frames_ref) {
+av_log(avctx, AV_LOG_ERROR, "A input frames reference create "
+   "failed.\n");
+return AVERROR(ENOMEM);
+}
+ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data;
+
+return 0;
+}
+
+int ff_vaapi_vpp_config_output(AVFilterLink *outlink)
+{
+AVFilterContext *avctx = outlink->src;
+VAAPIVPPContext *ctx   = avctx->priv;
+AVVAAPIHWConfig *hwconfig = NULL;
+AVHWFramesConstraints *constraints = NULL;
+AVHWFramesContext *output_frames;
+AVVAAPIFramesContext *va_frames;
+VAStatus vas;
+int err, i;
+
+if (ctx->pipeline_uninit)
+ctx->pipeline_uninit(avctx);
+
+if (!ctx->output_width)
+ctx->output_width  = avctx->inputs[0]->w;
+if (!ctx->output_height)
+ctx->output_height = avctx->inputs[0]->h;
+
+av_assert0(ctx->input_frames);
+ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref);
+if (!ctx->device_ref) {
+av_log(avctx, AV_LOG_ERROR, "A device reference create "
+   "failed.\n");
+return AVERROR(ENOMEM);
+}
+ctx->hwctx = ((AVHWDeviceContext*)ctx->device_ref->data)->hwctx;
+
+av_assert0(ctx->va_config == VA_INVALID_ID);
+vas = vaCreateConfig(ctx->hwctx->display, VAProfileNone,
+ VAEntrypointVideoProc, NULL, 0, >va_config);
+if (vas != VA_STATUS_SUCCESS) {
+av_log(avctx, AV_LOG_ERROR, "Failed to create processing pipeline "

[libav-devel] [PATCH 4/6] vf_crop: Add support for cropping VAAPI hardware frames

2018-02-14 Thread Mark Thompson
---
Just VAAPI here because with the following patch it has support to actually use 
it in libavfilter.  If wanted it could be enabled for all hardware formats, or 
maybe a specific whitelist?


 libavfilter/vf_crop.c | 21 ++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c
index 4122d52f8..dc7fa0dde 100644
--- a/libavfilter/vf_crop.c
+++ b/libavfilter/vf_crop.c
@@ -107,6 +107,7 @@ static int query_formats(AVFilterContext *ctx)
 AV_PIX_FMT_RGB8, AV_PIX_FMT_BGR8,
 AV_PIX_FMT_RGB4_BYTE,AV_PIX_FMT_BGR4_BYTE,
 AV_PIX_FMT_PAL8, AV_PIX_FMT_GRAY8,
+AV_PIX_FMT_VAAPI,
 AV_PIX_FMT_NONE
 };
 
@@ -162,8 +163,14 @@ static int config_input(AVFilterLink *link)
 s->var_values[VAR_T] = NAN;
 
 av_image_fill_max_pixsteps(s->max_step, NULL, pix_desc);
+
+if (pix_desc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
+s->hsub = 1;
+s->vsub = 1;
+} else {
 s->hsub = pix_desc->log2_chroma_w;
 s->vsub = pix_desc->log2_chroma_h;
+}
 
 if ((ret = av_expr_parse_and_eval(, (expr = s->ow_expr),
   var_names, s->var_values,
@@ -242,9 +249,6 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame)
 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
 int i;
 
-frame->width  = s->w;
-frame->height = s->h;
-
 s->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ?
 NAN : frame->pts * av_q2d(link->time_base);
 s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, NULL);
@@ -269,6 +273,16 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame)
 (int)s->var_values[VAR_N], s->var_values[VAR_T], s->x,
 s->y, s->x+s->w, s->y+s->h);
 
+if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
+frame->crop_top   += s->y;
+frame->crop_left  += s->x;
+frame->crop_bottom = frame->height - frame->crop_top - 
frame->crop_bottom - s->h;
+frame->crop_right  = frame->width  - frame->crop_left - 
frame->crop_right - s->w;
+
+} else {
+frame->width  = s->w;
+frame->height = s->h;
+
 frame->data[0] += s->y * frame->linesize[0];
 frame->data[0] += s->x * s->max_step[0];
 
@@ -286,6 +300,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *frame)
 frame->data[3] += s->y * frame->linesize[3];
 frame->data[3] += s->x * s->max_step[3];
 }
+}
 
 s->var_values[VAR_N] += 1.0;
 
-- 
2.15.1

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

[libav-devel] [PATCH 6/6] vf_scale_vaapi: Apply cropping rectangle to input

2018-02-14 Thread Mark Thompson
---
 libavfilter/vf_scale_vaapi.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c
index e92df44ba..6bd54d822 100644
--- a/libavfilter/vf_scale_vaapi.c
+++ b/libavfilter/vf_scale_vaapi.c
@@ -74,13 +74,13 @@ static int scale_vaapi_filter_frame(AVFilterLink *inlink, 
AVFrame *input_frame)
 
 memset(, 0, sizeof(params));
 
-// If there were top/left cropping, it could be taken into
-// account here.
 input_region = (VARectangle) {
-.x  = 0,
-.y  = 0,
-.width  = input_frame->width,
-.height = input_frame->height,
+.x  = input_frame->crop_left,
+.y  = input_frame->crop_top,
+.width  = input_frame->width -
+ (input_frame->crop_left + input_frame->crop_right),
+.height = input_frame->height -
+ (input_frame->crop_top + input_frame->crop_bottom),
 };
 
 params.surface = input_surface;
-- 
2.15.1

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

[libav-devel] [PATCH 3/6] lavfi: use common VAAPI VPP infrastructure for vf_deinterlace_vaapi

2018-02-14 Thread Mark Thompson
From: Jun Zhao <jun.z...@intel.com>

From ffmpeg commit 92704c480e811e0bd2a605173559d2baa974119f.

Signed-off-by: Mark Thompson <s...@jkqxz.net>
---
 libavfilter/Makefile   |   2 +-
 libavfilter/vf_deinterlace_vaapi.c | 339 +
 2 files changed, 45 insertions(+), 296 deletions(-)

diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index ad8f7b8eb..11e460c03 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -52,7 +52,7 @@ OBJS-$(CONFIG_COPY_FILTER)   += vf_copy.o
 OBJS-$(CONFIG_CROP_FILTER)   += vf_crop.o
 OBJS-$(CONFIG_CROPDETECT_FILTER) += vf_cropdetect.o
 OBJS-$(CONFIG_DEINTERLACE_QSV_FILTER)+= vf_deinterlace_qsv.o
-OBJS-$(CONFIG_DEINTERLACE_VAAPI_FILTER)  += vf_deinterlace_vaapi.o
+OBJS-$(CONFIG_DEINTERLACE_VAAPI_FILTER)  += vf_deinterlace_vaapi.o 
vaapi_vpp.o
 OBJS-$(CONFIG_DELOGO_FILTER) += vf_delogo.o
 OBJS-$(CONFIG_DRAWBOX_FILTER)+= vf_drawbox.o
 OBJS-$(CONFIG_DRAWTEXT_FILTER)   += vf_drawtext.o
diff --git a/libavfilter/vf_deinterlace_vaapi.c 
b/libavfilter/vf_deinterlace_vaapi.c
index 082df8914..d13332631 100644
--- a/libavfilter/vf_deinterlace_vaapi.c
+++ b/libavfilter/vf_deinterlace_vaapi.c
@@ -18,13 +18,8 @@
 
 #include 
 
-#include 
-#include 
-
 #include "libavutil/avassert.h"
 #include "libavutil/common.h"
-#include "libavutil/hwcontext.h"
-#include "libavutil/hwcontext_vaapi.h"
 #include "libavutil/mem.h"
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
@@ -33,29 +28,17 @@
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
+#include "vaapi_vpp.h"
 
 #define MAX_REFERENCES 8
 
 typedef struct DeintVAAPIContext {
-const AVClass *class;
-
-AVVAAPIDeviceContext *hwctx;
-AVBufferRef   *device_ref;
+VAAPIVPPContext vpp_ctx; // must be the first field
 
 intmode;
 intfield_rate;
 intauto_enable;
 
-intvalid_ids;
-VAConfigID va_config;
-VAContextIDva_context;
-
-AVBufferRef   *input_frames_ref;
-AVHWFramesContext *input_frames;
-
-intoutput_height;
-intoutput_width;
-
 VAProcFilterCapDeinterlacing
deint_caps[VAProcDeinterlacingCount];
 int nb_deint_caps;
@@ -65,8 +48,6 @@ typedef struct DeintVAAPIContext {
 intqueue_count;
 AVFrame   *frame_queue[MAX_REFERENCES];
 intextra_delay_for_timestamps;
-
-VABufferID filter_buffer;
 } DeintVAAPIContext;
 
 static const char *deint_vaapi_mode_name(int mode)
@@ -83,21 +64,7 @@ static const char *deint_vaapi_mode_name(int mode)
 }
 }
 
-static int deint_vaapi_query_formats(AVFilterContext *avctx)
-{
-enum AVPixelFormat pix_fmts[] = {
-AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE,
-};
-
-ff_formats_ref(ff_make_format_list(pix_fmts),
-   >inputs[0]->out_formats);
-ff_formats_ref(ff_make_format_list(pix_fmts),
-   >outputs[0]->in_formats);
-
-return 0;
-}
-
-static int deint_vaapi_pipeline_uninit(AVFilterContext *avctx)
+static void deint_vaapi_pipeline_uninit(AVFilterContext *avctx)
 {
 DeintVAAPIContext *ctx = avctx->priv;
 int i;
@@ -106,56 +73,20 @@ static int deint_vaapi_pipeline_uninit(AVFilterContext 
*avctx)
 av_frame_free(>frame_queue[i]);
 ctx->queue_count = 0;
 
-if (ctx->filter_buffer != VA_INVALID_ID) {
-vaDestroyBuffer(ctx->hwctx->display, ctx->filter_buffer);
-ctx->filter_buffer = VA_INVALID_ID;
-}
-
-if (ctx->va_context != VA_INVALID_ID) {
-vaDestroyContext(ctx->hwctx->display, ctx->va_context);
-ctx->va_context = VA_INVALID_ID;
-}
-
-if (ctx->va_config != VA_INVALID_ID) {
-vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
-ctx->va_config = VA_INVALID_ID;
-}
-
-av_buffer_unref(>device_ref);
-ctx->hwctx = NULL;
-
-return 0;
-}
-
-static int deint_vaapi_config_input(AVFilterLink *inlink)
-{
-AVFilterContext   *avctx = inlink->dst;
-DeintVAAPIContext *ctx = avctx->priv;
-
-deint_vaapi_pipeline_uninit(avctx);
-
-if (!inlink->hw_frames_ctx) {
-av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
-   "required to associate the processing device.\n");
-return AVERROR(EINVAL);
-}
-
-ctx->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx);
-ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data;
-
-return 0;
+ff_vaapi_vpp_pipeline_uninit(avctx);
 }
 
 static int deint_vaapi_build_filter_params(AVFil

[libav-devel] [PATCH 2/6] lavfi: use common VAAPI VPP infrastructure for vf_scale_vaapi

2018-02-14 Thread Mark Thompson
From: Jun Zhao <jun.z...@intel.com>

From ffmpeg commit 19214f005140b0ee7f706509bd3fab47f4af9b90.

Signed-off-by: Mark Thompson <s...@jkqxz.net>
---
 libavfilter/Makefile |   2 +-
 libavfilter/vf_scale_vaapi.c | 333 +--
 2 files changed, 34 insertions(+), 301 deletions(-)

diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 827762677..ad8f7b8eb 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -84,7 +84,7 @@ OBJS-$(CONFIG_PIXDESCTEST_FILTER)+= 
vf_pixdesctest.o
 OBJS-$(CONFIG_SCALE_FILTER)  += vf_scale.o
 OBJS-$(CONFIG_SCALE_NPP_FILTER)  += vf_scale_npp.o
 OBJS-$(CONFIG_SCALE_QSV_FILTER)  += vf_scale_qsv.o
-OBJS-$(CONFIG_SCALE_VAAPI_FILTER)+= vf_scale_vaapi.o
+OBJS-$(CONFIG_SCALE_VAAPI_FILTER)+= vf_scale_vaapi.o vaapi_vpp.o
 OBJS-$(CONFIG_SELECT_FILTER) += vf_select.o
 OBJS-$(CONFIG_SETDAR_FILTER) += vf_aspect.o
 OBJS-$(CONFIG_SETPTS_FILTER) += setpts.o
diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c
index 0ab5518b5..e92df44ba 100644
--- a/libavfilter/vf_scale_vaapi.c
+++ b/libavfilter/vf_scale_vaapi.c
@@ -18,13 +18,7 @@
 
 #include 
 
-#include 
-#include 
-
 #include "libavutil/avassert.h"
-#include "libavutil/common.h"
-#include "libavutil/hwcontext.h"
-#include "libavutil/hwcontext_vaapi.h"
 #include "libavutil/mem.h"
 #include "libavutil/opt.h"
 #include "libavutil/pixdesc.h"
@@ -33,250 +27,49 @@
 #include "formats.h"
 #include "internal.h"
 #include "video.h"
+#include "vaapi_vpp.h"
 
 typedef struct ScaleVAAPIContext {
-const AVClass *class;
-
-AVVAAPIDeviceContext *hwctx;
-AVBufferRef *device_ref;
-
-int valid_ids;
-VAConfigID  va_config;
-VAContextID va_context;
-
-AVBufferRef   *input_frames_ref;
-AVHWFramesContext *input_frames;
+VAAPIVPPContext vpp_ctx; // must be the first field
 
 char *output_format_string;
 enum AVPixelFormat output_format;
 int output_width;
 int output_height;
-
 } ScaleVAAPIContext;
 
 
-static int scale_vaapi_query_formats(AVFilterContext *avctx)
-{
-enum AVPixelFormat pix_fmts[] = {
-AV_PIX_FMT_VAAPI, AV_PIX_FMT_NONE,
-};
-
-ff_formats_ref(ff_make_format_list(pix_fmts),
-   >inputs[0]->out_formats);
-ff_formats_ref(ff_make_format_list(pix_fmts),
-   >outputs[0]->in_formats);
-
-return 0;
-}
-
-static int scale_vaapi_pipeline_uninit(ScaleVAAPIContext *ctx)
-{
-if (ctx->va_context != VA_INVALID_ID) {
-vaDestroyContext(ctx->hwctx->display, ctx->va_context);
-ctx->va_context = VA_INVALID_ID;
-}
-
-if (ctx->va_config != VA_INVALID_ID) {
-vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
-ctx->va_config = VA_INVALID_ID;
-}
-
-av_buffer_unref(>device_ref);
-ctx->hwctx = 0;
-
-return 0;
-}
-
-static int scale_vaapi_config_input(AVFilterLink *inlink)
-{
-AVFilterContext *avctx = inlink->dst;
-ScaleVAAPIContext *ctx = avctx->priv;
-
-scale_vaapi_pipeline_uninit(ctx);
-
-if (!inlink->hw_frames_ctx) {
-av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
-   "required to associate the processing device.\n");
-return AVERROR(EINVAL);
-}
-
-ctx->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx);
-ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data;
-
-return 0;
-}
-
-static int scale_vaapi_config_output(AVFilterLink *outlink)
-{
-AVFilterContext *avctx = outlink->src;
-ScaleVAAPIContext *ctx = avctx->priv;
-AVVAAPIHWConfig *hwconfig = NULL;
-AVHWFramesConstraints *constraints = NULL;
-AVHWFramesContext *output_frames;
-AVVAAPIFramesContext *va_frames;
-VAStatus vas;
-int err, i;
-
-scale_vaapi_pipeline_uninit(ctx);
-
-ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref);
-ctx->hwctx = ((AVHWDeviceContext*)ctx->device_ref->data)->hwctx;
-
-av_assert0(ctx->va_config == VA_INVALID_ID);
-vas = vaCreateConfig(ctx->hwctx->display, VAProfileNone,
- VAEntrypointVideoProc, 0, 0, >va_config);
-if (vas != VA_STATUS_SUCCESS) {
-av_log(ctx, AV_LOG_ERROR, "Failed to create processing pipeline "
-   "config: %d (%s).\n", vas, vaErrorStr(vas));
-err = AVERROR(EIO);
-goto fail;
-}
-
-hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref);
-if (!hwconfig) {
-err = AVERROR(ENOMEM);
-goto fail;
-}
-hwconfig->config_id = ctx->va_config;
-
-constraints = av_hwdevice_get_hw

[libav-devel] [PATCH 5/6] vf_crop: Reindent after previous commit

2018-02-14 Thread Mark Thompson
---
 libavfilter/vf_crop.c | 30 +++---
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c
index dc7fa0dde..abc27c8de 100644
--- a/libavfilter/vf_crop.c
+++ b/libavfilter/vf_crop.c
@@ -168,8 +168,8 @@ static int config_input(AVFilterLink *link)
 s->hsub = 1;
 s->vsub = 1;
 } else {
-s->hsub = pix_desc->log2_chroma_w;
-s->vsub = pix_desc->log2_chroma_h;
+s->hsub = pix_desc->log2_chroma_w;
+s->vsub = pix_desc->log2_chroma_h;
 }
 
 if ((ret = av_expr_parse_and_eval(, (expr = s->ow_expr),
@@ -283,23 +283,23 @@ static int filter_frame(AVFilterLink *link, AVFrame 
*frame)
 frame->width  = s->w;
 frame->height = s->h;
 
-frame->data[0] += s->y * frame->linesize[0];
-frame->data[0] += s->x * s->max_step[0];
+frame->data[0] += s->y * frame->linesize[0];
+frame->data[0] += s->x * s->max_step[0];
 
-if (!(desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & 
AV_PIX_FMT_FLAG_PSEUDOPAL)) {
-for (i = 1; i < 3; i ++) {
-if (frame->data[i]) {
-frame->data[i] += (s->y >> s->vsub) * frame->linesize[i];
-frame->data[i] += (s->x * s->max_step[i]) >> s->hsub;
+if (!(desc->flags & AV_PIX_FMT_FLAG_PAL || desc->flags & 
AV_PIX_FMT_FLAG_PSEUDOPAL)) {
+for (i = 1; i < 3; i ++) {
+if (frame->data[i]) {
+frame->data[i] += (s->y >> s->vsub) * frame->linesize[i];
+frame->data[i] += (s->x * s->max_step[i]) >> s->hsub;
+}
 }
 }
-}
 
-/* alpha plane */
-if (frame->data[3]) {
-frame->data[3] += s->y * frame->linesize[3];
-frame->data[3] += s->x * s->max_step[3];
-}
+/* alpha plane */
+if (frame->data[3]) {
+frame->data[3] += s->y * frame->linesize[3];
+frame->data[3] += s->x * s->max_step[3];
+}
 }
 
 s->var_values[VAR_N] += 1.0;
-- 
2.15.1

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

Re: [libav-devel] [PATCH 04/16] vaapi_encode: Allocate slice structures and parameter buffers dynamically

2018-02-14 Thread Mark Thompson
On 11/02/18 18:14, Mark Thompson wrote:
> From: Jun Zhao <mypopy...@gmail.com>
> 
> This removes the arbitrary limit on the allowed number of slices and
> parameter buffers.
> 
> From ffmpeg commit e4a6eb70f471eda36592078e8fa1bad87fc9df73.
> 
> Signed-off-by: Mark Thompson <s...@jkqxz.net>
> ---
>  libavcodec/vaapi_encode.c | 42 ++
>  libavcodec/vaapi_encode.h |  6 ++
>  2 files changed, 32 insertions(+), 16 deletions(-)
> 
> diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
> index 47795ba73..8cba847f7 100644
> --- a/libavcodec/vaapi_encode.c
> +++ b/libavcodec/vaapi_encode.c
> ...
> @@ -313,15 +321,14 @@ static int vaapi_encode_issue(AVCodecContext *avctx,
>  }
>  }
>  
> -av_assert0(pic->nb_slices <= MAX_PICTURE_SLICES);
> +pic->slices = av_mallocz_array(pic->nb_slices, sizeof(*pic->slices));
> +if (!pic->slices) {
> +err = AVERROR(ENOMEM);
> +goto fail;
> +}

This fails for non-slice codecs (VP8, VP9) because av_mallocz_array() returns 
NULL when asked for zero array elements.  (ffmpeg has a hack marked "OS X on 
SDK 10.6 has a broken posix_memalign implementation" which makes this case call 
malloc(1) and return a real pointer instead.)

Changed locally to only do the allocation if nb_slices > 0.

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

Re: [libav-devel] [PATCH 10/16] cbs: Refcount all the things!

2018-02-11 Thread Mark Thompson
On 12/02/18 00:31, James Almer wrote:
> On 2/11/2018 3:14 PM, Mark Thompson wrote:
>> +int ff_cbs_alloc_unit_content(CodedBitstreamContext *ctx,
>> +  CodedBitstreamUnit *unit,
>> +  size_t size,
>> +  void (*free)(void *opaque, uint8_t *data))
>> +{
>> +av_assert0(!unit->content && !unit->content_ref);
>> +
>> +unit->content = av_mallocz(size);
>> +if (!unit->content)
>> +return AVERROR(ENOMEM);
>> +
>> +unit->content_ref = av_buffer_create(unit->content, size,
>> + free ? free
>> +  : _buffer_default_free,
> 
> av_buffer_create() defaults to av_buffer_default_free() on its own if
> free is NULL, so no need to do it here.

Aha, so it does!  Fixed in all three places I used it explicitly.

Thanks,

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

Re: [libav-devel] [PATCH 6/8] vf_hwupload/hwmap: Support setting a fixed pool size

2018-02-11 Thread Mark Thompson
On 11/02/18 23:30, wm4 wrote:
> On Sun, 11 Feb 2018 23:09:51 +
> Mark Thompson <s...@jkqxz.net> wrote:
> 
>> On 11/02/18 07:21, Song, Ruiling wrote:
>>> I have run some test against the patches. It works as described.  
>>
>> Great - there is general agreement on that part now so I've applied that 
>> series.
>>
>>> Are you still against setting a default value within qsv_init_pool()?
>>> Users can easily override the default value through the interface you added.
>>> And if they did not set a value, the default value will be used.  
>>
>> I don't mind the idea but I'm against the specificity of it, I guess.  The 
>> single value will help in the isolated hwupload case, but it would be 
>> inconsistent with other APIs and doesn't suggest a sensible value to anyone 
>> who does need to set a fixed pool size.
>>
>>> If you are OK, I will re-submit the patch and add more comment on the magic 
>>> value.
>>> If you are against, we can discuss it further for a better solution.  
>>
>> Returning to suggestions made before, how would you feel about adding some 
>> way to determine from a device how big a frames context should be for it?
>>
>> The simplest method to do that would be to add a new element to 
>> HWContextType containing a sensible value.  If it's zero, dynamic allocation 
>> is supported and noone needs to care any further.  If it's nonzero, then it 
>> becomes the default value for pool size used in the absence of any other 
>> choice.  It would be used in av_hwframe_ctx_init() if it's set on the type 
>> and initial_pool_size is zero, which would fix our hwupload case.  Probably 
>> it would want some way for the user to access it as well - new API for 
>> retrieving property values somehow, maybe?  (Not sure about that bit.)
>>
>> Would that work for you?  Anyone want to offer any criticism / other ideas 
>> which don't depend on semi-mythical rewrites of lavfi link negotiation?
> 
> Still feels kind of arbitrary. 

Yeah, but we need something arbitrary to get around this problem.

> What exactly determines the size the
> hwcontext will propose?

It would be something like the largest number of frames that the worst consumer 
of that frame type might need in some nebulous "typical" case, plus the number 
that a non-decoder producer might need (probably two).

But, more importantly, the arbitrary value can be set for each API 
independently...

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

Re: [libav-devel] [PATCH 6/8] vf_hwupload/hwmap: Support setting a fixed pool size

2018-02-11 Thread Mark Thompson
On 11/02/18 07:21, Song, Ruiling wrote:
> I have run some test against the patches. It works as described.

Great - there is general agreement on that part now so I've applied that series.

> Are you still against setting a default value within qsv_init_pool()?
> Users can easily override the default value through the interface you added.
> And if they did not set a value, the default value will be used.

I don't mind the idea but I'm against the specificity of it, I guess.  The 
single value will help in the isolated hwupload case, but it would be 
inconsistent with other APIs and doesn't suggest a sensible value to anyone who 
does need to set a fixed pool size.

> If you are OK, I will re-submit the patch and add more comment on the magic 
> value.
> If you are against, we can discuss it further for a better solution.

Returning to suggestions made before, how would you feel about adding some way 
to determine from a device how big a frames context should be for it?

The simplest method to do that would be to add a new element to HWContextType 
containing a sensible value.  If it's zero, dynamic allocation is supported and 
noone needs to care any further.  If it's nonzero, then it becomes the default 
value for pool size used in the absence of any other choice.  It would be used 
in av_hwframe_ctx_init() if it's set on the type and initial_pool_size is zero, 
which would fix our hwupload case.  Probably it would want some way for the 
user to access it as well - new API for retrieving property values somehow, 
maybe?  (Not sure about that bit.)

Would that work for you?  Anyone want to offer any criticism / other ideas 
which don't depend on semi-mythical rewrites of lavfi link negotiation?

Thanks,

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

Re: [libav-devel] [PATCH 10/16] cbs: Refcount all the things!

2018-02-11 Thread Mark Thompson
On 11/02/18 20:13, wm4 wrote:
> On Sun, 11 Feb 2018 18:14:34 +
> Mark Thompson <s...@jkqxz.net> wrote:
> 
>> ---
>>  libavcodec/cbs.c   | 168 +---
>>  libavcodec/cbs.h   |  51 -
>>  libavcodec/cbs_h264.h  |   4 +
>>  libavcodec/cbs_h2645.c | 341 
>> +++--
>>  libavcodec/cbs_h265.h  |   2 +
>>  libavcodec/cbs_internal.h  |   3 -
>>  libavcodec/cbs_mpeg2.c |  91 -
>>  libavcodec/cbs_mpeg2.h |   5 +
>>  libavcodec/cbs_mpeg2_syntax_template.c |   5 +-
>>  libavcodec/h264_metadata_bsf.c |   6 +-
>>  libavcodec/h265_metadata_bsf.c |   2 +-
>>  libavcodec/mpeg2_metadata_bsf.c|   3 +-
>>  libavcodec/vaapi_encode_h264.c |   2 +-
>>  libavcodec/vaapi_encode_h265.c |   2 +-
>>  libavcodec/vaapi_encode_mpeg2.c|   2 +-
>>  15 files changed, 408 insertions(+), 279 deletions(-)
>>
> 
> What does it do, and does it help with anything? I'm find it a bit
> suspicious, because our refcount stuff has a lot of overhead (multiple
> mallocs...).

The immediate intent is to make it easier to get alloc/free right - all 
subelements use the buffer API so that it's clear how to free them.  That is 
particularly helpful for stream-editing cases when you add or remove elements; 
VAAPI mostly doesn't mind because it points to the same fixed structures 
repeatedly.

It also elides some redundant copies, which are a much greater overhead than 
the additional small reference allocations.  The packet -> fragment copy is 
removed here if the input packet is refcounted.  The fragment -> unit copy can 
be elided for MPEG-2, but I haven't yet done that because the details are 
slightly subtle.  H.26[45] is trickier because it also undoes the emulation 
prevention, but there is a redundant copy NAL RBSP -> unit which should be 
removable with suitable changes to ff_h2645_packet_split() as well.

It also lets me move the slice_group_id element out of the PPS structure - 
having a >100k array there that was ~never used was kindof stupid.

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

Re: [libav-devel] [PATCH] Add AV1 video decoding support through libaom

2018-02-11 Thread Mark Thompson
On 10/02/18 16:29, Luca Barbato wrote:
> On 10/02/2018 16:59, Diego Biurrun wrote:
>> Looks OK in general.
>>
>> On Fri, Feb 09, 2018 at 10:51:36AM +0100, Luca Barbato wrote:
>>> --- /dev/null
>>> +++ b/libavcodec/libaom.c
>>> @@ -0,0 +1,90 @@
>>> +
>>> +#define HIGH_DEPTH(fmt)   \
>>> +    case AOM_IMG_FMT_I ## fmt ## 16: switch (depth) { \
>>> +    case 10: return AV_PIX_FMT_YUV ## fmt ## P10; \
>>> +    case 12: return AV_PIX_FMT_YUV ## fmt ## P12; \
>>> +    default: return AV_PIX_FMT_NONE;  \
>>
>> Move the switch statement to the next line for better readability please.
> 
> Sure
> 
>>
>>> +enum AVPixelFormat ff_aom_imgfmt_to_pixfmt(aom_img_fmt_t img, int depth)
>>> +{
>>> +    switch (img) {
>>> +    case AOM_IMG_FMT_RGB24: return AV_PIX_FMT_RGB24;
>>> +    case AOM_IMG_FMT_RGB565:    return AV_PIX_FMT_RGB565BE;
>>> +    case AOM_IMG_FMT_RGB555:    return AV_PIX_FMT_RGB555BE;
>>> +    case AOM_IMG_FMT_UYVY:  return AV_PIX_FMT_UYVY422;
>>> +    case AOM_IMG_FMT_YUY2:  return AV_PIX_FMT_YUYV422;
>>> +    case AOM_IMG_FMT_YVYU:  return AV_PIX_FMT_YVYU422;
>>> +    case AOM_IMG_FMT_BGR24: return AV_PIX_FMT_BGR24;
>>> +    case AOM_IMG_FMT_ARGB:  return AV_PIX_FMT_ARGB;
>>> +    case AOM_IMG_FMT_ARGB_LE:   return AV_PIX_FMT_BGRA;
>>> +    case AOM_IMG_FMT_RGB565_LE: return AV_PIX_FMT_RGB565LE;
>>> +    case AOM_IMG_FMT_RGB555_LE: return AV_PIX_FMT_RGB555LE;
>>> +    case AOM_IMG_FMT_I420:  return AV_PIX_FMT_YUV420P;
>>> +    case AOM_IMG_FMT_I422:  return AV_PIX_FMT_YUV422P;
>>> +    case AOM_IMG_FMT_I444:  return AV_PIX_FMT_YUV444P;
>>> +    case AOM_IMG_FMT_444A:  return AV_PIX_FMT_YUVA444P;
>>> +    case AOM_IMG_FMT_I440:  return AV_PIX_FMT_YUV440P;
>>
>> I'd break those lines.
> 
> I can run uncrustify to break it, is that the outcome you'd expect?
> 
>>> +/*    case AOM_IMG_FMT_I42016:    return AV_PIX_FMT_YUV420P16;
>>> +    case AOM_IMG_FMT_I42216:    return AV_PIX_FMT_YUV422P16;
>>> +    case AOM_IMG_FMT_I44416:    return AV_PIX_FMT_YUV444P16; */
>>
>> Why is this commented out?
> 
> I should just remove it, thanks for reminding me.
> 
>>> +aom_img_fmt_t ff_aom_pixfmt_to_imgfmt(enum AVPixelFormat pix)
>>> +{
>>> +    switch (pix) {
>>> +    case AV_PIX_FMT_RGB24:    return AOM_IMG_FMT_RGB24;
>>> +    case AV_PIX_FMT_RGB565BE: return AOM_IMG_FMT_RGB565;
>>> +    case AV_PIX_FMT_RGB555BE: return AOM_IMG_FMT_RGB555;
>>> +    case AV_PIX_FMT_UYVY422:  return AOM_IMG_FMT_UYVY;
>>> +    case AV_PIX_FMT_YUYV422:  return AOM_IMG_FMT_YUY2;
>>> +    case AV_PIX_FMT_YVYU422:  return AOM_IMG_FMT_YVYU;
>>> +    case AV_PIX_FMT_BGR24:    return AOM_IMG_FMT_BGR24;
>>> +    case AV_PIX_FMT_ARGB: return AOM_IMG_FMT_ARGB;
>>> +    case AV_PIX_FMT_BGRA: return AOM_IMG_FMT_ARGB_LE;
>>> +    case AV_PIX_FMT_RGB565LE: return AOM_IMG_FMT_RGB565_LE;
>>> +    case AV_PIX_FMT_RGB555LE: return AOM_IMG_FMT_RGB555_LE;
>>> +    case AV_PIX_FMT_YUV420P:  return AOM_IMG_FMT_I420;
>>> +    case AV_PIX_FMT_YUV422P:  return AOM_IMG_FMT_I422;
>>> +    case AV_PIX_FMT_YUV444P:  return AOM_IMG_FMT_I444;
>>> +    case AV_PIX_FMT_YUVA444P: return AOM_IMG_FMT_444A;
>>> +    case AV_PIX_FMT_YUV440P:  return AOM_IMG_FMT_I440;
>>> +    case AV_PIX_FMT_YUV420P10:    return AOM_IMG_FMT_I42016;
>>> +    case AV_PIX_FMT_YUV422P10:    return AOM_IMG_FMT_I42216;
>>> +    case AV_PIX_FMT_YUV444P10:    return AOM_IMG_FMT_I44416;
>>> +    case AV_PIX_FMT_YUV420P12:    return AOM_IMG_FMT_I42016;
>>> +    case AV_PIX_FMT_YUV422P12:    return AOM_IMG_FMT_I42216;
>>> +    case AV_PIX_FMT_YUV444P12:    return AOM_IMG_FMT_I44416;
>>
>> same
> 
> Ok.

If you feel like tearing down the bikeshed and building a different one: I 
think this would be nicer as a single table with the two functions reading it, 
rather than two functions which duplicate a lot of the information.

(Or ignore this if you prefer how the bikeshed is currently made...)

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

[libav-devel] [PATCH 16/16] h264_metadata: Add option to delete filler data

2018-02-11 Thread Mark Thompson
Deletes both filler NAL units and filler SEI messages.  (Annex B zero_bytes
between NAL units are already discarded by the read/write process.)
---
 libavcodec/h264_metadata_bsf.c | 43 ++
 1 file changed, 43 insertions(+)

diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c
index 88e1a7750..f888be761 100644
--- a/libavcodec/h264_metadata_bsf.c
+++ b/libavcodec/h264_metadata_bsf.c
@@ -63,6 +63,8 @@ typedef struct H264MetadataContext {
 
 const char *sei_user_data;
 int sei_first_au;
+
+int delete_filler;
 } H264MetadataContext;
 
 
@@ -347,6 +349,44 @@ static int h264_metadata_filter(AVBSFContext *bsf, 
AVPacket *out)
 }
 }
 
+if (ctx->delete_filler) {
+for (i = 0; i < au->nb_units; i++) {
+if (au->units[i].type == H264_NAL_FILLER_DATA) {
+// Filler NAL units.
+err = ff_cbs_delete_unit(ctx->cbc, au, i);
+if (err < 0) {
+av_log(bsf, AV_LOG_ERROR, "Failed to delete "
+   "filler NAL.\n");
+goto fail;
+}
+--i;
+continue;
+}
+
+if (au->units[i].type == H264_NAL_SEI) {
+// Filler SEI messages.
+H264RawSEI *sei = au->units[i].content;
+
+for (j = 0; j < sei->payload_count; j++) {
+if (sei->payload[j].payload_type ==
+H264_SEI_TYPE_FILLER_PAYLOAD) {
+err = ff_cbs_h264_delete_sei_message(ctx->cbc, au,
+ >units[i], j);
+if (err < 0) {
+av_log(bsf, AV_LOG_ERROR, "Failed to delete "
+   "filler SEI message.\n");
+goto fail;
+}
+// Renumbering might have happened, start again at
+// the same NAL unit position.
+--i;
+break;
+}
+}
+}
+}
+}
+
 err = ff_cbs_write_packet(ctx->cbc, out, au);
 if (err < 0) {
 av_log(bsf, AV_LOG_ERROR, "Failed to write packet.\n");
@@ -467,6 +507,9 @@ static const AVOption h264_metadata_options[] = {
 { "sei_user_data", "Insert SEI user data (UUID+string)",
 OFFSET(sei_user_data), AV_OPT_TYPE_STRING, { .str = NULL } },
 
+{ "delete_filler", "Delete all filler (both NAL and SEI)",
+OFFSET(delete_filler), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1 },
+
 { NULL }
 };
 
-- 
2.15.1

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

[libav-devel] [PATCH 13/16] h264_metadata: Always add the SEI user data to the first access unit

2018-02-11 Thread Mark Thompson
This should be added even if the first access unit does not contain
parameter sets.
---
E.g. this is helpful for the "-bsf:v 
'h264_metadata=sei_user_data=dc45e9bde6d948b7962cd820d923eeef+x264 - core 150'" 
hack workaround for old files with stripped metadata.


 libavcodec/h264_metadata_bsf.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c
index ce85781c6..88e1a7750 100644
--- a/libavcodec/h264_metadata_bsf.c
+++ b/libavcodec/h264_metadata_bsf.c
@@ -62,6 +62,7 @@ typedef struct H264MetadataContext {
 int crop_bottom;
 
 const char *sei_user_data;
+int sei_first_au;
 } H264MetadataContext;
 
 
@@ -288,14 +289,17 @@ static int h264_metadata_filter(AVBSFContext *bsf, 
AVPacket *out)
 }
 }
 
-// Only insert the SEI in access units containing SPSs.
-if (has_sps && ctx->sei_user_data) {
+// Only insert the SEI in access units containing SPSs, and also
+// unconditionally in the first access unit we ever see.
+if (ctx->sei_user_data && (has_sps || !ctx->sei_first_au)) {
 H264RawSEIPayload payload = {
 .payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED,
 };
 H264RawSEIUserDataUnregistered *udu =
 _data_unregistered;
 
+ctx->sei_first_au = 1;
+
 for (i = j = 0; j < 32 && ctx->sei_user_data[i]; i++) {
 int c, v;
 c = ctx->sei_user_data[i];
-- 
2.15.1

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

[libav-devel] [PATCH 10/16] cbs: Refcount all the things!

2018-02-11 Thread Mark Thompson
---
 libavcodec/cbs.c   | 168 +---
 libavcodec/cbs.h   |  51 -
 libavcodec/cbs_h264.h  |   4 +
 libavcodec/cbs_h2645.c | 341 +++--
 libavcodec/cbs_h265.h  |   2 +
 libavcodec/cbs_internal.h  |   3 -
 libavcodec/cbs_mpeg2.c |  91 -
 libavcodec/cbs_mpeg2.h |   5 +
 libavcodec/cbs_mpeg2_syntax_template.c |   5 +-
 libavcodec/h264_metadata_bsf.c |   6 +-
 libavcodec/h265_metadata_bsf.c |   2 +-
 libavcodec/mpeg2_metadata_bsf.c|   3 +-
 libavcodec/vaapi_encode_h264.c |   2 +-
 libavcodec/vaapi_encode_h265.c |   2 +-
 libavcodec/vaapi_encode_mpeg2.c|   2 +-
 15 files changed, 408 insertions(+), 279 deletions(-)

diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c
index a8d252f6c..9d191130f 100644
--- a/libavcodec/cbs.c
+++ b/libavcodec/cbs.c
@@ -21,6 +21,7 @@
 #include "config.h"
 
 #include "libavutil/avassert.h"
+#include "libavutil/buffer.h"
 #include "libavutil/common.h"
 
 #include "cbs.h"
@@ -95,11 +96,12 @@ void ff_cbs_close(CodedBitstreamContext **ctx_ptr)
 static void cbs_unit_uninit(CodedBitstreamContext *ctx,
 CodedBitstreamUnit *unit)
 {
-if (ctx->codec->free_unit && unit->content && !unit->content_external)
-ctx->codec->free_unit(unit);
+av_buffer_unref(>content_ref);
+unit->content = NULL;
 
-av_freep(>data);
-unit->data_size = 0;
+av_buffer_unref(>data_ref);
+unit->data = NULL;
+unit->data_size= 0;
 unit->data_bit_padding = 0;
 }
 
@@ -113,7 +115,8 @@ void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx,
 av_freep(>units);
 frag->nb_units = 0;
 
-av_freep(>data);
+av_buffer_unref(>data_ref);
+frag->data = NULL;
 frag->data_size= 0;
 frag->data_bit_padding = 0;
 }
@@ -133,6 +136,9 @@ static int cbs_read_fragment_content(CodedBitstreamContext 
*ctx,
 continue;
 }
 
+av_buffer_unref(>units[i].content_ref);
+frag->units[i].content = NULL;
+
 err = ctx->codec->read_unit(ctx, >units[i]);
 if (err == AVERROR(ENOSYS)) {
 av_log(ctx->log_ctx, AV_LOG_VERBOSE,
@@ -169,6 +175,27 @@ int ff_cbs_read_extradata(CodedBitstreamContext *ctx,
 return cbs_read_fragment_content(ctx, frag);
 }
 
+static int cbs_fill_fragment_data(CodedBitstreamContext *ctx,
+  CodedBitstreamFragment *frag,
+  const uint8_t *data, size_t size)
+{
+av_assert0(!frag->data && !frag->data_ref);
+
+frag->data_ref =
+av_buffer_alloc(size + AV_INPUT_BUFFER_PADDING_SIZE);
+if (!frag->data_ref)
+return AVERROR(ENOMEM);
+
+frag->data  = frag->data_ref->data;
+frag->data_size = size;
+
+memcpy(frag->data, data, size);
+memset(frag->data + size, 0,
+   AV_INPUT_BUFFER_PADDING_SIZE);
+
+return 0;
+}
+
 int ff_cbs_read_packet(CodedBitstreamContext *ctx,
CodedBitstreamFragment *frag,
const AVPacket *pkt)
@@ -177,16 +204,24 @@ int ff_cbs_read_packet(CodedBitstreamContext *ctx,
 
 memset(frag, 0, sizeof(*frag));
 
-frag->data  = pkt->data;
-frag->data_size = pkt->size;
+if (pkt->buf) {
+frag->data_ref = av_buffer_ref(pkt->buf);
+if (!frag->data_ref)
+return AVERROR(ENOMEM);
+
+frag->data  = pkt->data;
+frag->data_size = pkt->size;
+
+} else {
+err = cbs_fill_fragment_data(ctx, frag, pkt->data, pkt->size);
+if (err < 0)
+return err;
+}
 
 err = ctx->codec->split_fragment(ctx, frag, 0);
 if (err < 0)
 return err;
 
-frag->data  = NULL;
-frag->data_size = 0;
-
 return cbs_read_fragment_content(ctx, frag);
 }
 
@@ -198,17 +233,14 @@ int ff_cbs_read(CodedBitstreamContext *ctx,
 
 memset(frag, 0, sizeof(*frag));
 
-// (We won't write to this during split.)
-frag->data  = (uint8_t*)data;
-frag->data_size = size;
+err = cbs_fill_fragment_data(ctx, frag, data, size);
+if (err < 0)
+return err;
 
 err = ctx->codec->split_fragment(ctx, frag, 0);
 if (err < 0)
 return err;
 
-frag->data  = NULL;
-frag->data_size = 0;
-
 return cbs_read_fragment_content(ctx, frag);
 }
 
@@ -219,17 +251,25 @@ int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
 int err, i;
 
 for (i = 0; i < frag->nb_units; i++) {
-if (!frag->units[i].content)
+CodedBitstreamUnit *unit = >units[i];
+
+if (!unit->content)
 continue;
 
-err = ctx->codec->write_unit(ctx, >units[i]);
+av_buffer_unref(>data_ref);
+unit->data = NULL;
+
+err = ctx->codec->write_unit(ctx, unit);
 if (err < 0) {
 

[libav-devel] [PATCH 11/16] cbs_h264: Add utility functions to insert/delete SEI messages

2018-02-11 Thread Mark Thompson
---
 libavcodec/cbs_h264.h  | 19 +++
 libavcodec/cbs_h2645.c | 89 ++
 2 files changed, 108 insertions(+)

diff --git a/libavcodec/cbs_h264.h b/libavcodec/cbs_h264.h
index 14ea69ae2..8c17680bb 100644
--- a/libavcodec/cbs_h264.h
+++ b/libavcodec/cbs_h264.h
@@ -22,6 +22,7 @@
 #include 
 #include 
 
+#include "cbs.h"
 #include "cbs_h2645.h"
 #include "h264.h"
 
@@ -428,4 +429,22 @@ typedef struct CodedBitstreamH264Context {
 } CodedBitstreamH264Context;
 
 
+/**
+ * Add an SEI message to an access unit.
+ */
+int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx,
+CodedBitstreamFragment *access_unit,
+const H264RawSEIPayload *payload);
+
+/**
+ * Delete an SEI message from an access unit.
+ *
+ * Deletes from nal_unit, which must be an SEI NAL unit.  If this is the
+ * last message in nal_unit, also deletes it from access_unit.
+ */
+int ff_cbs_h264_delete_sei_message(CodedBitstreamContext *ctx,
+   CodedBitstreamFragment *access_unit,
+   CodedBitstreamUnit *nal_unit,
+   int position);
+
 #endif /* AVCODEC_CBS_H264_H */
diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
index c98bab998..7b2e1b532 100644
--- a/libavcodec/cbs_h2645.c
+++ b/libavcodec/cbs_h2645.c
@@ -1394,3 +1394,92 @@ const CodedBitstreamType ff_cbs_type_h265 = {
 
 .close = _h265_close,
 };
+
+int ff_cbs_h264_add_sei_message(CodedBitstreamContext *ctx,
+CodedBitstreamFragment *au,
+const H264RawSEIPayload *payload)
+{
+H264RawSEI *sei;
+CodedBitstreamUnit *nal = NULL;
+int err, i;
+
+// Find an existing SEI NAL unit to add to.
+for (i = 0; i < au->nb_units; i++) {
+if (au->units[i].type == H264_NAL_SEI) {
+nal = >units[i];
+break;
+}
+}
+if (nal) {
+sei = nal->content;
+
+} else {
+// Need to make a new SEI NAL unit.  Insert it before the first
+// slice data NAL unit; if no slice data, add at the end.
+AVBufferRef *sei_ref;
+
+sei_ref = av_buffer_allocz(sizeof(*sei));
+if (!sei_ref)
+return AVERROR(ENOMEM);
+sei = (H264RawSEI*)sei_ref->data;
+
+sei->nal_unit_header.nal_unit_type = H264_NAL_SEI;
+sei->nal_unit_header.nal_ref_idc   = 0;
+
+for (i = 0; i < au->nb_units; i++) {
+if (au->units[i].type == H264_NAL_SLICE ||
+au->units[i].type == H264_NAL_IDR_SLICE)
+break;
+}
+
+err = ff_cbs_insert_unit_content(ctx, au, i, H264_NAL_SEI,
+ sei, sei_ref);
+av_buffer_unref(_ref);
+if (err < 0)
+return err;
+}
+
+if (sei->payload_count >= H264_MAX_SEI_PAYLOADS) {
+av_log(ctx->log_ctx, AV_LOG_ERROR, "Too many payloads in "
+   "SEI NAL unit.\n");
+return AVERROR(EINVAL);
+}
+
+memcpy(>payload[sei->payload_count], payload, sizeof(*payload));
+++sei->payload_count;
+
+return 0;
+}
+
+int ff_cbs_h264_delete_sei_message(CodedBitstreamContext *ctx,
+   CodedBitstreamFragment *au,
+   CodedBitstreamUnit *nal,
+   int position)
+{
+H264RawSEI *sei = nal->content;
+
+av_assert0(nal->type == H264_NAL_SEI);
+av_assert0(position >= 0 && position < sei->payload_count);
+
+if (position == 0 && sei->payload_count == 1) {
+// Deleting NAL unit entirely.
+int i;
+
+for (i = 0; i < au->nb_units; i++) {
+if (>units[i] == nal)
+break;
+}
+av_assert0(i < au->nb_units && "NAL unit not in access unit.");
+
+return ff_cbs_delete_unit(ctx, au, i);
+} else {
+cbs_h264_free_sei_payload(>payload[position]);
+
+--sei->payload_count;
+memmove(sei->payload + position,
+sei->payload + position + 1,
+(sei->payload_count - position) * sizeof(*sei->payload));
+
+return 0;
+}
+}
-- 
2.15.1

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

[libav-devel] [PATCH 07/16] cbs: Demote the "decomposition unimplemented" warning

2018-02-11 Thread Mark Thompson
This is harmless and should not be a warning - unknown units are passed
through to the write functions unchanged, and no other code will interact
with them.
---
 libavcodec/cbs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c
index e5819afce..a8d252f6c 100644
--- a/libavcodec/cbs.c
+++ b/libavcodec/cbs.c
@@ -135,7 +135,7 @@ static int cbs_read_fragment_content(CodedBitstreamContext 
*ctx,
 
 err = ctx->codec->read_unit(ctx, >units[i]);
 if (err == AVERROR(ENOSYS)) {
-av_log(ctx->log_ctx, AV_LOG_WARNING,
+av_log(ctx->log_ctx, AV_LOG_VERBOSE,
"Decomposition unimplemented for unit %d "
"(type %"PRIu32").\n", i, frag->units[i].type);
 } else if (err < 0) {
-- 
2.15.1

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

[libav-devel] [PATCH 12/16] h264_metadata: Use common SEI addition function

2018-02-11 Thread Mark Thompson
---
 libavcodec/h264_metadata_bsf.c | 70 --
 1 file changed, 19 insertions(+), 51 deletions(-)

diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c
index 6a1904e31..ce85781c6 100644
--- a/libavcodec/h264_metadata_bsf.c
+++ b/libavcodec/h264_metadata_bsf.c
@@ -290,42 +290,11 @@ static int h264_metadata_filter(AVBSFContext *bsf, 
AVPacket *out)
 
 // Only insert the SEI in access units containing SPSs.
 if (has_sps && ctx->sei_user_data) {
-H264RawSEI *sei;
-H264RawSEIPayload *payload;
-H264RawSEIUserDataUnregistered *udu;
-int sei_pos, sei_new;
-
-for (i = 0; i < au->nb_units; i++) {
-if (au->units[i].type == H264_NAL_SEI ||
-au->units[i].type == H264_NAL_SLICE ||
-au->units[i].type == H264_NAL_IDR_SLICE)
-break;
-}
-sei_pos = i;
-
-if (sei_pos < au->nb_units &&
-au->units[sei_pos].type == H264_NAL_SEI) {
-sei_new = 0;
-sei = au->units[sei_pos].content;
-} else {
-sei_new = 1;
-sei = >sei_nal;
-memset(sei, 0, sizeof(*sei));
-
-sei->nal_unit_header.nal_unit_type = H264_NAL_SEI;
-
-err = ff_cbs_insert_unit_content(ctx->cbc, au, sei_pos,
- H264_NAL_SEI, sei, NULL);
-if (err < 0) {
-av_log(bsf, AV_LOG_ERROR, "Failed to insert SEI.\n");
-goto fail;
-}
-}
-
-payload = >payload[sei->payload_count];
-
-payload->payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED;
-udu = >payload.user_data_unregistered;
+H264RawSEIPayload payload = {
+.payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED,
+};
+H264RawSEIUserDataUnregistered *udu =
+_data_unregistered;
 
 for (i = j = 0; j < 32 && ctx->sei_user_data[i]; i++) {
 int c, v;
@@ -345,21 +314,25 @@ static int h264_metadata_filter(AVBSFContext *bsf, 
AVPacket *out)
 ++j;
 }
 if (j == 32 && ctx->sei_user_data[i] == '+') {
-sei_udu_string = av_strdup(ctx->sei_user_data + i + 1);
-if (!sei_udu_string) {
+size_t len = strlen(ctx->sei_user_data + i + 1);
+
+udu->data_ref = av_buffer_alloc(len + 1);
+if (!udu->data_ref) {
 err = AVERROR(ENOMEM);
-goto sei_fail;
+goto fail;
 }
 
-udu->data = sei_udu_string;
-udu->data_length = strlen(sei_udu_string);
+udu->data= udu->data_ref->data;
+udu->data_length = len + 1;
+memcpy(udu->data, ctx->sei_user_data + i + 1, len + 1);
 
-payload->payload_size = 16 + udu->data_length;
+payload.payload_size = 16 + udu->data_length;
 
-if (!sei_new) {
-// This will be freed by the existing internal
-// reference in fragment_uninit().
-sei_udu_string = NULL;
+err = ff_cbs_h264_add_sei_message(ctx->cbc, au, );
+if (err < 0) {
+av_log(bsf, AV_LOG_ERROR, "Failed to add user data SEI "
+   "message to access unit.\n");
+goto fail;
 }
 
 } else {
@@ -367,12 +340,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, 
AVPacket *out)
 av_log(bsf, AV_LOG_ERROR, "Invalid user data: "
"must be \"UUID+string\".\n");
 err = AVERROR(EINVAL);
-sei_fail:
-memset(payload, 0, sizeof(*payload));
-goto fail;
 }
-
-++sei->payload_count;
 }
 
 err = ff_cbs_write_packet(ctx->cbc, out, au);
-- 
2.15.1

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

[libav-devel] [PATCH 15/16] cbs_h264: Add support for filler NAL units

2018-02-11 Thread Mark Thompson
---
 libavcodec/cbs_h264.h |  6 ++
 libavcodec/cbs_h2645.c| 21 +
 libavcodec/cbs_h264_syntax_template.c | 29 +
 3 files changed, 56 insertions(+)

diff --git a/libavcodec/cbs_h264.h b/libavcodec/cbs_h264.h
index a59b7be1b..5a7dc2769 100644
--- a/libavcodec/cbs_h264.h
+++ b/libavcodec/cbs_h264.h
@@ -408,6 +408,12 @@ typedef struct H264RawSlice {
 AVBufferRef *data_ref;
 } H264RawSlice;
 
+typedef struct H264RawFiller {
+H264RawNALUnitHeader nal_unit_header;
+
+uint32_t filler_size;
+} H264RawFiller;
+
 
 typedef struct CodedBitstreamH264Context {
 // Reader/writer context in common with the H.265 implementation.
diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
index 7f5972cd7..bb3a11949 100644
--- a/libavcodec/cbs_h2645.c
+++ b/libavcodec/cbs_h2645.c
@@ -815,6 +815,19 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext 
*ctx,
 }
 break;
 
+case H264_NAL_FILLER_DATA:
+{
+err = ff_cbs_alloc_unit_content(ctx, unit,
+sizeof(H264RawFiller), NULL);
+if (err < 0)
+return err;
+
+err = cbs_h264_read_filler(ctx, , unit->content);
+if (err < 0)
+return err;
+}
+break;
+
 default:
 return AVERROR(ENOSYS);
 }
@@ -1070,6 +1083,14 @@ static int cbs_h264_write_nal_unit(CodedBitstreamContext 
*ctx,
 }
 break;
 
+case H264_NAL_FILLER_DATA:
+{
+err = cbs_h264_write_filler(ctx, pbc, unit->content);
+if (err < 0)
+return err;
+}
+break;
+
 default:
 av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for "
"NAL unit type %"PRIu32".\n", unit->type);
diff --git a/libavcodec/cbs_h264_syntax_template.c 
b/libavcodec/cbs_h264_syntax_template.c
index 29e973598..1aa788858 100644
--- a/libavcodec/cbs_h264_syntax_template.c
+++ b/libavcodec/cbs_h264_syntax_template.c
@@ -1247,3 +1247,32 @@ static int FUNC(slice_header)(CodedBitstreamContext 
*ctx, RWContext *rw,
 
 return 0;
 }
+
+static int FUNC(filler)(CodedBitstreamContext *ctx, RWContext *rw,
+H264RawFiller *current)
+{
+av_unused int ff_byte = 0xff;
+int err;
+
+HEADER("Filler Data");
+
+CHECK(FUNC(nal_unit_header)(ctx, rw, >nal_unit_header,
+1 << H264_NAL_FILLER_DATA));
+
+#ifdef READ
+while (bitstream_peek(rw, 8) == 0xff) {
+xu(8, ff_byte, ff_byte, 0xff, 0xff);
+++current->filler_size;
+}
+#else
+{
+uint32_t i;
+for (i = 0; i < current->filler_size; i++)
+xu(8, ff_byte, ff_byte, 0xff, 0xff);
+}
+#endif
+
+CHECK(FUNC(rbsp_trailing_bits)(ctx, rw));
+
+return 0;
+}
-- 
2.15.1

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

[libav-devel] [PATCH 08/16] cbs_h2645: Remove active ps references when it is replaced

2018-02-11 Thread Mark Thompson
---
 libavcodec/cbs_h2645.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
index e3b5bf618..9d05d5915 100644
--- a/libavcodec/cbs_h2645.c
+++ b/libavcodec/cbs_h2645.c
@@ -674,6 +674,8 @@ static int cbs_h26 ## h26n ## _replace_ ## 
ps_var(CodedBitstreamContext *ctx, \
" id : %d.\n", id); \
 return AVERROR_INVALIDDATA; \
 } \
+if (priv->ps_var[id] == priv->active_ ## ps_var) \
+priv->active_ ## ps_var = NULL ; \
 av_freep(>ps_var[id]); \
 priv->ps_var[id] = av_malloc(sizeof(*ps_var)); \
 if (!priv->ps_var[id]) \
-- 
2.15.1

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

[libav-devel] [PATCH 14/16] cbs_h264: Move slice_group_id array out of PPS structure

2018-02-11 Thread Mark Thompson
It's very large, and is only used in some FMO streams.
---
 libavcodec/cbs_h264.h |  4 +++-
 libavcodec/cbs_h2645.c| 10 +-
 libavcodec/cbs_h264_syntax_template.c |  3 +++
 3 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/libavcodec/cbs_h264.h b/libavcodec/cbs_h264.h
index 8c17680bb..a59b7be1b 100644
--- a/libavcodec/cbs_h264.h
+++ b/libavcodec/cbs_h264.h
@@ -195,7 +195,9 @@ typedef struct H264RawPPS {
 uint8_t slice_group_change_direction_flag;
 uint16_t slice_group_change_rate_minus1;
 uint16_t pic_size_in_map_units_minus1;
-uint8_t slice_group_id[H264_MAX_MB_PIC_SIZE];
+
+uint8_t *slice_group_id;
+AVBufferRef *slice_group_id_ref;
 
 uint8_t num_ref_idx_l0_default_active_minus1;
 uint8_t num_ref_idx_l1_default_active_minus1;
diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
index 7b2e1b532..7f5972cd7 100644
--- a/libavcodec/cbs_h2645.c
+++ b/libavcodec/cbs_h2645.c
@@ -394,6 +394,13 @@ static int cbs_h2645_read_more_rbsp_data(BitstreamContext 
*bc)
 #undef allocate
 
 
+static void cbs_h264_free_pps(void *unit, uint8_t *content)
+{
+H264RawPPS *pps = (H264RawPPS*)content;
+av_buffer_unref(>slice_group_id_ref);
+av_freep();
+}
+
 static void cbs_h264_free_sei_payload(H264RawSEIPayload *payload)
 {
 switch (payload->payload_type) {
@@ -725,7 +732,8 @@ static int cbs_h264_read_nal_unit(CodedBitstreamContext 
*ctx,
 {
 H264RawPPS *pps;
 
-err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*pps), NULL);
+err = ff_cbs_alloc_unit_content(ctx, unit, sizeof(*pps),
+_h264_free_pps);
 if (err < 0)
 return err;
 pps = unit->content;
diff --git a/libavcodec/cbs_h264_syntax_template.c 
b/libavcodec/cbs_h264_syntax_template.c
index c2fd54682..29e973598 100644
--- a/libavcodec/cbs_h264_syntax_template.c
+++ b/libavcodec/cbs_h264_syntax_template.c
@@ -404,6 +404,9 @@ static int FUNC(pps)(CodedBitstreamContext *ctx, RWContext 
*rw,
 ue(slice_group_change_rate_minus1, 0, pic_size - 1);
 } else if (current->slice_group_map_type == 6) {
 ue(pic_size_in_map_units_minus1, pic_size - 1, pic_size - 1);
+
+allocate(current->slice_group_id,
+ current->pic_size_in_map_units_minus1 + 1);
 for (i = 0; i <= current->pic_size_in_map_units_minus1; i++)
 u(av_log2(2 * current->num_slice_groups_minus1 + 1),
   slice_group_id[i], 0, current->num_slice_groups_minus1);
-- 
2.15.1

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

[libav-devel] [PATCH 09/16] cbs_h264: Add hack for pic_timing with no active SPS

2018-02-11 Thread Mark Thompson
If there is exactly one possible SPS but it is not yet active then just
assume that it should be the active one.
---
 libavcodec/cbs_h264_syntax_template.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/libavcodec/cbs_h264_syntax_template.c 
b/libavcodec/cbs_h264_syntax_template.c
index 0fe18441c..c2fd54682 100644
--- a/libavcodec/cbs_h264_syntax_template.c
+++ b/libavcodec/cbs_h264_syntax_template.c
@@ -560,6 +560,22 @@ static int FUNC(sei_pic_timing)(CodedBitstreamContext 
*ctx, RWContext *rw,
 int err;
 
 sps = h264->active_sps;
+if (!sps) {
+// If there is exactly one possible SPS but it is not yet active
+// then just assume that it should be the active one.
+int i, k = -1;
+for (i = 0; i < H264_MAX_SPS_COUNT; i++) {
+if (h264->sps[i]) {
+if (k >= 0) {
+k = -1;
+break;
+}
+k = i;
+}
+}
+if (k >= 0)
+sps = h264->sps[k];
+}
 if (!sps) {
 av_log(ctx->log_ctx, AV_LOG_ERROR,
"No active SPS for pic_timing.\n");
-- 
2.15.1

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

[libav-devel] [PATCH 04/16] vaapi_encode: Allocate slice structures and parameter buffers dynamically

2018-02-11 Thread Mark Thompson
From: Jun Zhao <mypopy...@gmail.com>

This removes the arbitrary limit on the allowed number of slices and
parameter buffers.

From ffmpeg commit e4a6eb70f471eda36592078e8fa1bad87fc9df73.

Signed-off-by: Mark Thompson <s...@jkqxz.net>
---
 libavcodec/vaapi_encode.c | 42 ++
 libavcodec/vaapi_encode.h |  6 ++
 2 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
index 47795ba73..8cba847f7 100644
--- a/libavcodec/vaapi_encode.c
+++ b/libavcodec/vaapi_encode.c
@@ -36,13 +36,17 @@ static int vaapi_encode_make_packed_header(AVCodecContext 
*avctx,
 VAAPIEncodeContext *ctx = avctx->priv_data;
 VAStatus vas;
 VABufferID param_buffer, data_buffer;
+VABufferID *tmp;
 VAEncPackedHeaderParameterBuffer params = {
 .type = type,
 .bit_length = bit_len,
 .has_emulation_bytes = 1,
 };
 
-av_assert0(pic->nb_param_buffers + 2 <= MAX_PARAM_BUFFERS);
+tmp = av_realloc_array(pic->param_buffers, sizeof(*tmp), 
pic->nb_param_buffers + 2);
+if (!tmp)
+return AVERROR(ENOMEM);
+pic->param_buffers = tmp;
 
 vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
  VAEncPackedHeaderParameterBufferType,
@@ -77,9 +81,13 @@ static int vaapi_encode_make_param_buffer(AVCodecContext 
*avctx,
 {
 VAAPIEncodeContext *ctx = avctx->priv_data;
 VAStatus vas;
+VABufferID *tmp;
 VABufferID buffer;
 
-av_assert0(pic->nb_param_buffers + 1 <= MAX_PARAM_BUFFERS);
+tmp = av_realloc_array(pic->param_buffers, sizeof(*tmp), 
pic->nb_param_buffers + 1);
+if (!tmp)
+return AVERROR(ENOMEM);
+pic->param_buffers = tmp;
 
 vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
  type, len, 1, data, );
@@ -313,15 +321,14 @@ static int vaapi_encode_issue(AVCodecContext *avctx,
 }
 }
 
-av_assert0(pic->nb_slices <= MAX_PICTURE_SLICES);
+pic->slices = av_mallocz_array(pic->nb_slices, sizeof(*pic->slices));
+if (!pic->slices) {
+err = AVERROR(ENOMEM);
+goto fail;
+}
 for (i = 0; i < pic->nb_slices; i++) {
-slice = av_mallocz(sizeof(*slice));
-if (!slice) {
-err = AVERROR(ENOMEM);
-goto fail;
-}
+slice = >slices[i];
 slice->index = i;
-pic->slices[i] = slice;
 
 if (ctx->codec->slice_params_size > 0) {
 slice->codec_slice_params = 
av_mallocz(ctx->codec->slice_params_size);
@@ -425,8 +432,16 @@ fail_with_picture:
 fail:
 for(i = 0; i < pic->nb_param_buffers; i++)
 vaDestroyBuffer(ctx->hwctx->display, pic->param_buffers[i]);
+for (i = 0; i < pic->nb_slices; i++) {
+if (pic->slices) {
+av_freep(>slices[i].priv_data);
+av_freep(>slices[i].codec_slice_params);
+}
+}
 fail_at_end:
 av_freep(>codec_picture_params);
+av_freep(>param_buffers);
+av_freep(>slices);
 av_frame_free(>recon_image);
 av_buffer_unref(>output_buffer_ref);
 pic->output_buffer = VA_INVALID_ID;
@@ -535,15 +550,18 @@ static int vaapi_encode_free(AVCodecContext *avctx,
 vaapi_encode_discard(avctx, pic);
 
 for (i = 0; i < pic->nb_slices; i++) {
-av_freep(>slices[i]->priv_data);
-av_freep(>slices[i]->codec_slice_params);
-av_freep(>slices[i]);
+if (pic->slices) {
+av_freep(>slices[i].priv_data);
+av_freep(>slices[i].codec_slice_params);
+}
 }
 av_freep(>codec_picture_params);
 
 av_frame_free(>input_image);
 av_frame_free(>recon_image);
 
+av_freep(>param_buffers);
+av_freep(>slices);
 // Output buffer should already be destroyed.
 av_assert0(pic->output_buffer == VA_INVALID_ID);
 
diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h
index 1b0fed80e..31c379053 100644
--- a/libavcodec/vaapi_encode.h
+++ b/libavcodec/vaapi_encode.h
@@ -35,8 +35,6 @@ enum {
 MAX_CONFIG_ATTRIBUTES  = 4,
 MAX_GLOBAL_PARAMS  = 4,
 MAX_PICTURE_REFERENCES = 2,
-MAX_PICTURE_SLICES = 112,
-MAX_PARAM_BUFFERS  = 128,
 MAX_REORDER_DELAY  = 16,
 MAX_PARAM_BUFFER_SIZE  = 1024,
 };
@@ -73,7 +71,7 @@ typedef struct VAAPIEncodePicture {
 VASurfaceID recon_surface;
 
 int  nb_param_buffers;
-VABufferID  param_buffers[MAX_PARAM_BUFFERS];
+VABufferID *param_buffers;
 
 AVBufferRef*output_buffer_ref;
 VABufferID  output_buffer;
@@ -85,7 +83,7 @@ typedef struct VAAPIEncodePicture {
 struct VAAPIEncodePicture *refs[MAX_PICTURE_REFERENCES];
 
 int  nb_slices;
-VAAPIEncodeSlice *slices[MAX_PICTURE_S

[libav-devel] [PATCH 01/16] cbs: Allocate the context inside the init function

2018-02-11 Thread Mark Thompson
... instead of making the caller allocate it themselves.  This is
more consistent with other APIs in libav.
---
This one and the following two have been hanging around for a while (they came 
from the merge into the other tine).


 libavcodec/cbs.c| 20 +---
 libavcodec/cbs.h|  6 +++---
 libavcodec/h264_metadata_bsf.c  | 20 ++--
 libavcodec/h264_redundant_pps_bsf.c | 18 +-
 libavcodec/h265_metadata_bsf.c  | 18 +-
 libavcodec/mpeg2_metadata_bsf.c | 16 
 libavcodec/trace_headers_bsf.c  | 14 +++---
 libavcodec/vaapi_encode_h264.c  | 14 +++---
 libavcodec/vaapi_encode_h265.c  | 10 +-
 libavcodec/vaapi_encode_mpeg2.c | 10 +-
 10 files changed, 80 insertions(+), 66 deletions(-)

diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c
index 3baa31a4d..fd9baa299 100644
--- a/libavcodec/cbs.c
+++ b/libavcodec/cbs.c
@@ -39,9 +39,10 @@ static const CodedBitstreamType *cbs_type_table[] = {
 #endif
 };
 
-int ff_cbs_init(CodedBitstreamContext *ctx,
+int ff_cbs_init(CodedBitstreamContext **ctx_ptr,
 enum AVCodecID codec_id, void *log_ctx)
 {
+CodedBitstreamContext *ctx;
 const CodedBitstreamType *type;
 int i;
 
@@ -55,27 +56,40 @@ int ff_cbs_init(CodedBitstreamContext *ctx,
 if (!type)
 return AVERROR(EINVAL);
 
+ctx = av_mallocz(sizeof(*ctx));
+if (!ctx)
+return AVERROR(ENOMEM);
+
 ctx->log_ctx = log_ctx;
 ctx->codec   = type;
 
 ctx->priv_data = av_mallocz(ctx->codec->priv_data_size);
-if (!ctx->priv_data)
+if (!ctx->priv_data) {
+av_freep();
 return AVERROR(ENOMEM);
+}
 
 ctx->decompose_unit_types = NULL;
 
 ctx->trace_enable = 0;
 ctx->trace_level  = AV_LOG_TRACE;
 
+*ctx_ptr = ctx;
 return 0;
 }
 
-void ff_cbs_close(CodedBitstreamContext *ctx)
+void ff_cbs_close(CodedBitstreamContext **ctx_ptr)
 {
+CodedBitstreamContext *ctx = *ctx_ptr;
+
+if (!ctx)
+return;
+
 if (ctx->codec && ctx->codec->close)
 ctx->codec->close(ctx);
 
 av_freep(>priv_data);
+av_freep(ctx_ptr);
 }
 
 static void cbs_unit_uninit(CodedBitstreamContext *ctx,
diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h
index 01b2239b7..34ee78be3 100644
--- a/libavcodec/cbs.h
+++ b/libavcodec/cbs.h
@@ -169,15 +169,15 @@ typedef struct CodedBitstreamContext {
 
 
 /**
- * Initialise a new context for the given codec.
+ * Create and initialise a new context for the given codec.
  */
-int ff_cbs_init(CodedBitstreamContext *ctx,
+int ff_cbs_init(CodedBitstreamContext **ctx,
 enum AVCodecID codec_id, void *log_ctx);
 
 /**
  * Close a context and free all internal state.
  */
-void ff_cbs_close(CodedBitstreamContext *ctx);
+void ff_cbs_close(CodedBitstreamContext **ctx);
 
 
 /**
diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c
index ac0b9823b..2b579e9d3 100644
--- a/libavcodec/h264_metadata_bsf.c
+++ b/libavcodec/h264_metadata_bsf.c
@@ -35,7 +35,7 @@ enum {
 typedef struct H264MetadataContext {
 const AVClass *class;
 
-CodedBitstreamContext cbc;
+CodedBitstreamContext *cbc;
 CodedBitstreamFragment access_unit;
 
 H264RawAUD aud_nal;
@@ -214,7 +214,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket 
*out)
 if (err < 0)
 goto fail;
 
-err = ff_cbs_read_packet(>cbc, au, in);
+err = ff_cbs_read_packet(ctx->cbc, au, in);
 if (err < 0) {
 av_log(bsf, AV_LOG_ERROR, "Failed to read packet.\n");
 goto fail;
@@ -229,7 +229,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket 
*out)
 // If an AUD is present, it must be the first NAL unit.
 if (au->units[0].type == H264_NAL_AUD) {
 if (ctx->aud == REMOVE)
-ff_cbs_delete_unit(>cbc, au, 0);
+ff_cbs_delete_unit(ctx->cbc, au, 0);
 } else {
 if (ctx->aud == INSERT) {
 static const int primary_pic_type_table[] = {
@@ -269,7 +269,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket 
*out)
 aud->nal_unit_header.nal_unit_type = H264_NAL_AUD;
 aud->primary_pic_type = j;
 
-err = ff_cbs_insert_unit_content(>cbc, au,
+err = ff_cbs_insert_unit_content(ctx->cbc, au,
  0, H264_NAL_AUD, aud);
 if (err < 0) {
 av_log(bsf, AV_LOG_ERROR, "Failed to insert AUD.\n");
@@ -314,7 +314,7 @@ static int h264_metadata_filter(AVBSFContext *bsf, AVPacket 
*out)
 
 sei->nal_unit_header.nal_unit_type = H264_NAL_SEI;
 
-err = ff_cbs_insert_unit_content(>cbc, au,
+err = ff_cbs_insert_unit_content(ctx->cbc, au,
  sei_pos, H264_NAL_SEI, sei);
 if (err < 0) {
 av_log(bsf, AV_LOG_ERROR, "Failed to insert SEI.\n");
@@ 

[libav-devel] [PATCH 03/16] cbs: Minor comment fixes / cosmetics

2018-02-11 Thread Mark Thompson
---
 libavcodec/cbs.h  | 35 +++
 libavcodec/cbs_internal.h |  3 +++
 2 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h
index 85c7b5557..ffeca057a 100644
--- a/libavcodec/cbs.h
+++ b/libavcodec/cbs.h
@@ -25,6 +25,19 @@
 #include "avcodec.h"
 
 
+/*
+ * This defines a framework for converting between a coded bitstream
+ * and structures defining all individual syntax elements found in
+ * such a stream.
+ *
+ * Conversion in both directions is possible.  Given a coded bitstream
+ * (any meaningful fragment), it can be parsed and decomposed into
+ * syntax elements stored in a set of codec-specific structures.
+ * Similarly, given a set of those same codec-specific structures the
+ * syntax elements can be serialised and combined to create a coded
+ * bitstream.
+ */
+
 struct CodedBitstreamType;
 
 /**
@@ -39,7 +52,7 @@ typedef uint32_t CodedBitstreamUnitType;
 /**
  * Coded bitstream unit structure.
  *
- * A bitstream unit the the smallest element of a bitstream which
+ * A bitstream unit the smallest element of a bitstream which
  * is meaningful on its own.  For example, an H.264 NAL unit.
  *
  * See the codec-specific header for the meaning of this for any
@@ -52,7 +65,7 @@ typedef struct CodedBitstreamUnit {
 CodedBitstreamUnitType type;
 
 /**
- * Pointer to the bitstream form of this unit.
+ * Pointer to the directly-parsable bitstream form of this unit.
  *
  * May be NULL if the unit currently only exists in decomposed form.
  */
@@ -114,7 +127,7 @@ typedef struct CodedBitstreamFragment {
 /**
  * Number of units in this fragment.
  *
- * This may be zero if the fragment only exists in bistream form
+ * This may be zero if the fragment only exists in bitstream form
  * and has not been decomposed.
  */
 int  nb_units;
@@ -162,7 +175,7 @@ typedef struct CodedBitstreamContext {
 /**
  * Length of the decompose_unit_types array.
  */
-intnb_decompose_unit_types;
+int nb_decompose_unit_types;
 
 /**
  * Enable trace output during read/write operations.
@@ -204,6 +217,10 @@ int ff_cbs_read_extradata(CodedBitstreamContext *ctx,
 /**
  * Read the data bitstream from a packet into a fragment, then
  * split into units and decompose.
+ *
+ * This also updates the internal state of the coded bitstream context
+ * with any persistent data from the fragment which may be required to
+ * read following fragments (e.g. parameter sets).
  */
 int ff_cbs_read_packet(CodedBitstreamContext *ctx,
CodedBitstreamFragment *frag,
@@ -212,6 +229,10 @@ int ff_cbs_read_packet(CodedBitstreamContext *ctx,
 /**
  * Read a bitstream from a memory region into a fragment, then
  * split into units and decompose.
+ *
+ * This also updates the internal state of the coded bitstream context
+ * with any persistent data from the fragment which may be required to
+ * read following fragments (e.g. parameter sets).
  */
 int ff_cbs_read(CodedBitstreamContext *ctx,
 CodedBitstreamFragment *frag,
@@ -225,12 +246,18 @@ int ff_cbs_read(CodedBitstreamContext *ctx,
  * data buffer.  When modifying the content of decomposed units, this
  * can be used to regenerate the bitstream form of units or the whole
  * fragment so that it can be extracted for other use.
+ *
+ * This also updates the internal state of the coded bitstream context
+ * with any persistent data from the fragment which may be required to
+ * write following fragments (e.g. parameter sets).
  */
 int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
CodedBitstreamFragment *frag);
 
 /**
  * Write the bitstream of a fragment to the extradata in codec parameters.
+ *
+ * This replaces any existing extradata in the structure.
  */
 int ff_cbs_write_extradata(CodedBitstreamContext *ctx,
AVCodecParameters *par,
diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h
index dddeae9d5..1a1c22f06 100644
--- a/libavcodec/cbs_internal.h
+++ b/libavcodec/cbs_internal.h
@@ -32,6 +32,9 @@ typedef struct CodedBitstreamType {
 
 // Split frag->data into coded bitstream units, creating the
 // frag->units array.  Fill data but not content on each unit.
+// The header argument should be set if the fragment came from
+// a header block, which may require different parsing for some
+// codecs (e.g. the AVCC header in H.264).
 int (*split_fragment)(CodedBitstreamContext *ctx,
   CodedBitstreamFragment *frag,
   int header);
-- 
2.15.1

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

[libav-devel] [PATCH 05/16] vaapi_encode: Destroy output buffer pool before VA context

2018-02-11 Thread Mark Thompson
The buffers are created associated with the context, so they should be
destroyed before the context is.  This is enforced by the iHD driver.
---
This patch and the following one were posted late last year, but there was no 
conclusion.  There is some suggestion that the driver might be fixed for either 
or both of them, but I think it would be best to apply them anyway.


 libavcodec/vaapi_encode.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
index 8cba847f7..7063c6877 100644
--- a/libavcodec/vaapi_encode.c
+++ b/libavcodec/vaapi_encode.c
@@ -1554,6 +1554,8 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx)
 vaapi_encode_free(avctx, pic);
 }
 
+av_buffer_pool_uninit(>output_buffer_pool);
+
 if (ctx->va_context != VA_INVALID_ID) {
 vaDestroyContext(ctx->hwctx->display, ctx->va_context);
 ctx->va_context = VA_INVALID_ID;
@@ -1564,8 +1566,6 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx)
 ctx->va_config = VA_INVALID_ID;
 }
 
-av_buffer_pool_uninit(>output_buffer_pool);
-
 av_freep(>codec_sequence_params);
 av_freep(>codec_picture_params);
 
-- 
2.15.1

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

[libav-devel] [PATCH 02/16] cbs: Add an explicit type for coded bitstream unit types

2018-02-11 Thread Mark Thompson
Also fix conversion specifiers used for the unit type.
---
 libavcodec/cbs.c   | 12 +++-
 libavcodec/cbs.h   | 19 +++
 libavcodec/cbs_h2645.c |  2 +-
 libavcodec/cbs_mpeg2.c |  4 ++--
 4 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c
index fd9baa299..e5819afce 100644
--- a/libavcodec/cbs.c
+++ b/libavcodec/cbs.c
@@ -137,10 +137,10 @@ static int 
cbs_read_fragment_content(CodedBitstreamContext *ctx,
 if (err == AVERROR(ENOSYS)) {
 av_log(ctx->log_ctx, AV_LOG_WARNING,
"Decomposition unimplemented for unit %d "
-   "(type %d).\n", i, frag->units[i].type);
+   "(type %"PRIu32").\n", i, frag->units[i].type);
 } else if (err < 0) {
 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d "
-   "(type %d).\n", i, frag->units[i].type);
+   "(type %"PRIu32").\n", i, frag->units[i].type);
 return err;
 }
 }
@@ -225,7 +225,7 @@ int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
 err = ctx->codec->write_unit(ctx, >units[i]);
 if (err < 0) {
 av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d "
-   "(type %d).\n", i, frag->units[i].type);
+   "(type %"PRIu32").\n", i, frag->units[i].type);
 return err;
 }
 }
@@ -421,7 +421,8 @@ static int cbs_insert_unit(CodedBitstreamContext *ctx,
 
 int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx,
CodedBitstreamFragment *frag,
-   int position, uint32_t type,
+   int position,
+   CodedBitstreamUnitType type,
void *content)
 {
 int err;
@@ -443,7 +444,8 @@ int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx,
 
 int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx,
 CodedBitstreamFragment *frag,
-int position, uint32_t type,
+int position,
+CodedBitstreamUnitType type,
 uint8_t *data, size_t data_size)
 {
 int err;
diff --git a/libavcodec/cbs.h b/libavcodec/cbs.h
index 34ee78be3..85c7b5557 100644
--- a/libavcodec/cbs.h
+++ b/libavcodec/cbs.h
@@ -27,6 +27,15 @@
 
 struct CodedBitstreamType;
 
+/**
+ * The codec-specific type of a bitstream unit.
+ *
+ * H.264 / AVC: nal_unit_type
+ * H.265 / HEVC: nal_unit_type
+ * MPEG-2: start code value (without prefix)
+ */
+typedef uint32_t CodedBitstreamUnitType;
+
 /**
  * Coded bitstream unit structure.
  *
@@ -40,7 +49,7 @@ typedef struct CodedBitstreamUnit {
 /**
  * Codec-specific type of this unit.
  */
-uint32_t type;
+CodedBitstreamUnitType type;
 
 /**
  * Pointer to the bitstream form of this unit.
@@ -149,7 +158,7 @@ typedef struct CodedBitstreamContext {
  * Types not in this list will be available in bitstream form only.
  * If NULL, all supported types will be decomposed.
  */
-uint32_t *decompose_unit_types;
+CodedBitstreamUnitType *decompose_unit_types;
 /**
  * Length of the decompose_unit_types array.
  */
@@ -250,7 +259,8 @@ void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx,
  */
 int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx,
CodedBitstreamFragment *frag,
-   int position, uint32_t type,
+   int position,
+   CodedBitstreamUnitType type,
void *content);
 
 /**
@@ -260,7 +270,8 @@ int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx,
  */
 int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx,
 CodedBitstreamFragment *frag,
-int position, uint32_t type,
+int position,
+CodedBitstreamUnitType type,
 uint8_t *data, size_t data_size);
 
 /**
diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
index 00eed0f28..e3b5bf618 100644
--- a/libavcodec/cbs_h2645.c
+++ b/libavcodec/cbs_h2645.c
@@ -1213,7 +1213,7 @@ static int cbs_h265_write_nal_unit(CodedBitstreamContext 
*ctx,
 
 default:
 av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for "
-   "NAL unit type %d.\n", unit->type);
+   "NAL unit type %"PRIu32".\n", unit->type);
 return AVERROR_PATCHWELCOME;
 }
 
diff --git a/libavcodec/cbs_mpeg2.c b/libavcodec/cbs_mpeg2.c
index 54875c2e1..5956f3933 100644
--- a/libavcodec/cbs_mpeg2.c
+++ b/libavcodec/cbs_mpeg2.c
@@ -220,7 +220,7 @@ static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx,
 START(0xb8, MPEG2RawGroupOfPicturesHeader, 
group_of_pictures_header);
 

[libav-devel] [PATCH 06/16] vaapi_h265: Mark unused entries in RefPicList[01] as explicitly invalid

2018-02-11 Thread Mark Thompson
The iHD driver looks at entries beyond num_ref_idx_l[01]_active_minus1
for unknown reasons.
---
 libavcodec/vaapi_encode_h265.c | 21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
index 38c9e2521..52ac4a687 100644
--- a/libavcodec/vaapi_encode_h265.c
+++ b/libavcodec/vaapi_encode_h265.c
@@ -767,8 +767,6 @@ static int 
vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
 
 .num_ref_idx_l0_active_minus1 = sh->num_ref_idx_l0_active_minus1,
 .num_ref_idx_l1_active_minus1 = sh->num_ref_idx_l1_active_minus1,
-.ref_pic_list0[0] = vpic->reference_frames[0],
-.ref_pic_list1[0] = vpic->reference_frames[1],
 
 .luma_log2_weight_denom = sh->luma_log2_weight_denom,
 .delta_chroma_log2_weight_denom = sh->delta_chroma_log2_weight_denom,
@@ -802,6 +800,25 @@ static int 
vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
 },
 };
 
+for (i = 0; i < FF_ARRAY_ELEMS(vslice->ref_pic_list0); i++) {
+vslice->ref_pic_list0[i].picture_id = VA_INVALID_ID;
+vslice->ref_pic_list0[i].flags  = VA_PICTURE_HEVC_INVALID;
+vslice->ref_pic_list1[i].picture_id = VA_INVALID_ID;
+vslice->ref_pic_list1[i].flags  = VA_PICTURE_HEVC_INVALID;
+}
+
+av_assert0(pic->nb_refs <= 2);
+if (pic->nb_refs >= 1) {
+// Backward reference for P- or B-frame.
+av_assert0(pic->type == PICTURE_TYPE_P ||
+   pic->type == PICTURE_TYPE_B);
+vslice->ref_pic_list0[0] = vpic->reference_frames[0];
+}
+if (pic->nb_refs >= 2) {
+// Forward reference for B-frame.
+av_assert0(pic->type == PICTURE_TYPE_B);
+vslice->ref_pic_list1[0] = vpic->reference_frames[1];
+}
 
 return 0;
 }
-- 
2.15.1

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

Re: [libav-devel] Add HW H.264 and HEVC encoding for AMD GPUs based on AMF SDK

2018-02-04 Thread Mark Thompson
On 03/02/18 17:23, Diego Biurrun wrote:
> On Thu, Jan 04, 2018 at 02:59:02PM +, Mironov, Mikhail wrote:
>>> On 1/3/2018 7:53 PM, Sean McGovern wrote:
 2 things:

 - does this actually depend on dlopen directly, or should it be libdl,
 like the entries below it?
>>>
>>> If this is Windows only as the doxy states, then LoadLibrary should be the
>>> only dep. But otherwise you're right, it should be libdl and not dlopen.
>>
>> We plan to add Linux support so eventually libdl will be needed. For now I 
>> am OK with either solution.
> 
> If this is Windows-only (for now at least), then there is no need for all the
> ifdeffery. We can add complexity if and when it is needed, no need to clutter
> the code for an uncertain and possibly distant future.

On 04/02/18 14:08, Diego Biurrun wrote:
> Do we have coverage for this on FATE?

This is why the vestigial libdl etc. support is useful - given the headers on 
Linux, it's just another external library you can build anywhere.

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

[libav-devel] [PATCH 6/8] vf_hwupload/hwmap: Support setting a fixed pool size

2018-02-04 Thread Mark Thompson
These filters do not directly know whether the API they are using will
support dynamic frame pools, so this is somewhat tricky.  If the user
sets extra_hw_frames, we assume that they are aware of the problem and
set a fixed size based on that.  If not, most cases use dynamic sizing
just like they did previously.  The hardware-reverse-mapping case for
hwmap previously had a large fixed size (64) here, primarily as a hack
for QSV use - this is removed and extra_hw_frames will need to be set
for QSV to work since it requires fixed-size pools (as the other cases
do, and which didn't work before).
---
 libavfilter/vf_hwmap.c| 7 ++-
 libavfilter/vf_hwupload.c | 3 +++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c
index b28cb2145..d5ad2768f 100644
--- a/libavfilter/vf_hwmap.c
+++ b/libavfilter/vf_hwmap.c
@@ -138,7 +138,9 @@ static int hwmap_config_output(AVFilterLink *outlink)
 frames->sw_format = hwfc->sw_format;
 frames->width = hwfc->width;
 frames->height= hwfc->height;
-frames->initial_pool_size = 64;
+
+if (avctx->extra_hw_frames >= 0)
+frames->initial_pool_size = 2 + avctx->extra_hw_frames;
 
 err = av_hwframe_ctx_init(ctx->hwframes_ref);
 if (err < 0) {
@@ -218,6 +220,9 @@ static int hwmap_config_output(AVFilterLink *outlink)
 hwfc->width = inlink->w;
 hwfc->height= inlink->h;
 
+if (avctx->extra_hw_frames >= 0)
+hwfc->initial_pool_size = 2 + avctx->extra_hw_frames;
+
 err = av_hwframe_ctx_init(ctx->hwframes_ref);
 if (err < 0) {
 av_log(avctx, AV_LOG_ERROR, "Failed to create frame "
diff --git a/libavfilter/vf_hwupload.c b/libavfilter/vf_hwupload.c
index 8cca9f42e..af4ff9b81 100644
--- a/libavfilter/vf_hwupload.c
+++ b/libavfilter/vf_hwupload.c
@@ -133,6 +133,9 @@ static int hwupload_config_output(AVFilterLink *outlink)
 ctx->hwframes->width = inlink->w;
 ctx->hwframes->height= inlink->h;
 
+if (avctx->extra_hw_frames >= 0)
+ctx->hwframes->initial_pool_size = 2 + avctx->extra_hw_frames;
+
 err = av_hwframe_ctx_init(ctx->hwframes_ref);
 if (err < 0)
 goto fail;
-- 
2.11.0

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

[libav-devel] [PATCH 2/8] lavc: Add per-thread surfaces in get_hw_frame_parameters()

2018-02-04 Thread Mark Thompson
This number is definitely required when frame threading is enabled, so
add it here rather than forcing all users to handle it themselves.

DXVA2 contained this addition in specific code as well (therefore being
added twice in the internal case) - just remove it from there.
---
 libavcodec/decode.c | 9 +
 libavcodec/dxva2.c  | 4 
 2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index e024a3232..8635aec94 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -748,10 +748,6 @@ int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx,
 // We guarantee 4 base work surfaces. The function above guarantees 1
 // (the absolute minimum), so add the missing count.
 frames_ctx->initial_pool_size += 3;
-
-// Add an additional surface per thread is frame threading is enabled.
-if (avctx->active_thread_type & FF_THREAD_FRAME)
-frames_ctx->initial_pool_size += avctx->thread_count;
 }
 
 ret = av_hwframe_ctx_init(avctx->hw_frames_ctx);
@@ -798,6 +794,11 @@ int avcodec_get_hw_frames_parameters(AVCodecContext *avctx,
 // available then add them here.
 if (avctx->extra_hw_frames > 0)
 frames_ctx->initial_pool_size += avctx->extra_hw_frames;
+
+// If frame threading is enabled then an extra surface per thread
+// is also required.
+if (avctx->active_thread_type & FF_THREAD_FRAME)
+frames_ctx->initial_pool_size += avctx->thread_count;
 }
 
 *out_frames_ref = frames_ref;
diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
index e34409d44..939b45a65 100644
--- a/libavcodec/dxva2.c
+++ b/libavcodec/dxva2.c
@@ -608,10 +608,6 @@ int ff_dxva2_common_frame_params(AVCodecContext *avctx,
 else
 num_surfaces += 2;
 
-/* add extra surfaces for frame threading */
-if (avctx->active_thread_type & FF_THREAD_FRAME)
-num_surfaces += avctx->thread_count;
-
 frames_ctx->sw_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
 AV_PIX_FMT_P010 : AV_PIX_FMT_NV12;
 frames_ctx->width = FFALIGN(avctx->coded_width, surface_alignment);
-- 
2.11.0

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

[libav-devel] [PATCH 4/8] vf_*_vaapi: Support increasing hardware frame pool size

2018-02-04 Thread Mark Thompson
Defaults to 10 frames to preserve compatibility, but can allocate
fewer if extra_hw_frames is set explicitly.
---
 libavfilter/vf_deinterlace_vaapi.c | 39 +++
 libavfilter/vf_scale_vaapi.c   | 42 +++---
 2 files changed, 33 insertions(+), 48 deletions(-)

diff --git a/libavfilter/vf_deinterlace_vaapi.c 
b/libavfilter/vf_deinterlace_vaapi.c
index 95a0f4041..082df8914 100644
--- a/libavfilter/vf_deinterlace_vaapi.c
+++ b/libavfilter/vf_deinterlace_vaapi.c
@@ -53,8 +53,6 @@ typedef struct DeintVAAPIContext {
 AVBufferRef   *input_frames_ref;
 AVHWFramesContext *input_frames;
 
-AVBufferRef   *output_frames_ref;
-AVHWFramesContext *output_frames;
 intoutput_height;
 intoutput_width;
 
@@ -236,6 +234,7 @@ static int deint_vaapi_config_output(AVFilterLink *outlink)
 DeintVAAPIContext*ctx = avctx->priv;
 AVVAAPIHWConfig *hwconfig = NULL;
 AVHWFramesConstraints *constraints = NULL;
+AVHWFramesContext *output_frames;
 AVVAAPIFramesContext *va_frames;
 VAStatus vas;
 int err;
@@ -287,34 +286,35 @@ static int deint_vaapi_config_output(AVFilterLink 
*outlink)
 goto fail;
 }
 
-ctx->output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref);
-if (!ctx->output_frames_ref) {
+outlink->hw_frames_ctx = av_hwframe_ctx_alloc(ctx->device_ref);
+if (!outlink->hw_frames_ctx) {
 av_log(avctx, AV_LOG_ERROR, "Failed to create HW frame context "
"for output.\n");
 err = AVERROR(ENOMEM);
 goto fail;
 }
 
-ctx->output_frames = (AVHWFramesContext*)ctx->output_frames_ref->data;
+output_frames = (AVHWFramesContext*)outlink->hw_frames_ctx->data;
 
-ctx->output_frames->format= AV_PIX_FMT_VAAPI;
-ctx->output_frames->sw_format = ctx->input_frames->sw_format;
-ctx->output_frames->width = ctx->output_width;
-ctx->output_frames->height= ctx->output_height;
+output_frames->format= AV_PIX_FMT_VAAPI;
+output_frames->sw_format = ctx->input_frames->sw_format;
+output_frames->width = ctx->output_width;
+output_frames->height= ctx->output_height;
 
-// The number of output frames we need is determined by what follows
-// the filter.  If it's an encoder with complex frame reference
-// structures then this could be very high.
-ctx->output_frames->initial_pool_size = 10;
+output_frames->initial_pool_size = 4;
+
+err = ff_filter_init_hw_frames(avctx, outlink, 10);
+if (err < 0)
+goto fail;
 
-err = av_hwframe_ctx_init(ctx->output_frames_ref);
+err = av_hwframe_ctx_init(outlink->hw_frames_ctx);
 if (err < 0) {
 av_log(avctx, AV_LOG_ERROR, "Failed to initialise VAAPI frame "
"context for output: %d\n", err);
 goto fail;
 }
 
-va_frames = ctx->output_frames->hwctx;
+va_frames = output_frames->hwctx;
 
 av_assert0(ctx->va_context == VA_INVALID_ID);
 vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
@@ -340,18 +340,12 @@ static int deint_vaapi_config_output(AVFilterLink 
*outlink)
 outlink->frame_rate = av_mul_q(inlink->frame_rate,
(AVRational) { ctx->field_rate, 1 });
 
-outlink->hw_frames_ctx = av_buffer_ref(ctx->output_frames_ref);
-if (!outlink->hw_frames_ctx) {
-err = AVERROR(ENOMEM);
-goto fail;
-}
-
 av_freep();
 av_hwframe_constraints_free();
 return 0;
 
 fail:
-av_buffer_unref(>output_frames_ref);
+av_buffer_unref(>hw_frames_ctx);
 av_freep();
 av_hwframe_constraints_free();
 return err;
@@ -601,7 +595,6 @@ static av_cold void deint_vaapi_uninit(AVFilterContext 
*avctx)
 deint_vaapi_pipeline_uninit(avctx);
 
 av_buffer_unref(>input_frames_ref);
-av_buffer_unref(>output_frames_ref);
 av_buffer_unref(>device_ref);
 }
 
diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c
index 4c8f2cf4e..0ab5518b5 100644
--- a/libavfilter/vf_scale_vaapi.c
+++ b/libavfilter/vf_scale_vaapi.c
@@ -22,6 +22,7 @@
 #include 
 
 #include "libavutil/avassert.h"
+#include "libavutil/common.h"
 #include "libavutil/hwcontext.h"
 #include "libavutil/hwcontext_vaapi.h"
 #include "libavutil/mem.h"
@@ -46,9 +47,6 @@ typedef struct ScaleVAAPIContext {
 AVBufferRef   *input_frames_ref;
 AVHWFramesContext *input_frames;
 
-AVBufferRef   *output_frames_ref;
-AVHWFramesContext *output_frames;
-
 char *output_format_string;
 enum AVPixelFormat output_format;
 int output_width;
@@ -83,7 +81,6 @@ static int scale_vaapi_pipeline_uninit(ScaleVAAPIContext *ctx)
 ctx->va_config = VA_INVALID_ID;
 }
 
-av_buffer_unref(>output_frames_ref);
 av_buffer_unref(>device_ref);
 ctx->hwctx = 0;
 
@@ -115,6 +112,7 @@ static int scale_vaapi_config_output(AVFilterLink *outlink)
 ScaleVAAPIContext *ctx = 

[libav-devel] [PATCH 7/8] hwcontext: Perform usual initialisation on derived device contexts

2018-02-04 Thread Mark Thompson
The initialisation should be common.  For libmfx, it was previously
happening in the derivation function and this moves it out.
---
 libavutil/hwcontext.c |  4 
 libavutil/hwcontext_qsv.c | 11 ---
 2 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index 2630087b5..cccbd6234 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -645,6 +645,10 @@ int av_hwdevice_ctx_create_derived(AVBufferRef 
**dst_ref_ptr,
 goto fail;
 
 done:
+ret = av_hwdevice_ctx_init(dst_ref);
+if (ret < 0)
+goto fail;
+
 *dst_ref_ptr = dst_ref;
 return 0;
 
diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index 9270b2258..9fa603c35 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -989,7 +989,6 @@ static int qsv_device_derive_from_child(AVHWDeviceContext 
*ctx,
 int flags)
 {
 AVQSVDeviceContext *hwctx = ctx->hwctx;
-QSVDeviceContext   *s = ctx->internal->priv;
 
 mfxVersionver = { { 3, 1 } };
 mfxHDLhandle;
@@ -1058,16 +1057,6 @@ static int 
qsv_device_derive_from_child(AVHWDeviceContext *ctx,
 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:
-- 
2.11.0

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

[libav-devel] [PATCH 3/8] lavfi: Add support for increasing hardware frame pool sizes

2018-02-04 Thread Mark Thompson
AVFilterContext.extra_hw_frames functions identically to the field of
the same name in AVCodecContext.
---
 doc/APIchanges |  3 +++
 libavfilter/avfilter.c | 23 +++
 libavfilter/avfilter.h | 16 
 libavfilter/internal.h | 16 
 4 files changed, 58 insertions(+)

diff --git a/doc/APIchanges b/doc/APIchanges
index 62c7a17e5..824333b9a 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,9 @@ libavutil: 2017-03-23
 
 API changes, most recent first:
 
+2018-xx-xx - xxx - lavfi 7.x+1.0 - avfilter.h
+  Add AVFilterContext.extra_hw_frames.
+
 2018-xx-xx - xxx - lavc 58.x+1.0 - avcodec.h
   Add AVCodecContext.extra_hw_frames.
 
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 83c1a7c20..2c4a385ea 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -368,6 +368,8 @@ static const AVOption avfilter_options[] = {
 { "thread_type", "Allowed thread types", OFFSET(thread_type), 
AV_OPT_TYPE_FLAGS,
 { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, FLAGS, "thread_type" },
 { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE 
}, .unit = "thread_type" },
+{ "extra_hw_frames", "Number of extra hardware frames to allocate for the 
user",
+OFFSET(extra_hw_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, 
FLAGS },
 { NULL },
 };
 
@@ -707,3 +709,24 @@ const AVClass *avfilter_get_class(void)
 {
 return _class;
 }
+
+int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link,
+ int default_pool_size)
+{
+AVHWFramesContext *frames;
+
+// Must already be set by caller.
+av_assert0(link->hw_frames_ctx);
+
+frames = (AVHWFramesContext*)link->hw_frames_ctx->data;
+
+if (frames->initial_pool_size == 0) {
+// Dynamic allocation is necessarily supported.
+} else if (avctx->extra_hw_frames >= 0) {
+frames->initial_pool_size += avctx->extra_hw_frames;
+} else {
+frames->initial_pool_size = default_pool_size;
+}
+
+return 0;
+}
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 6df69dbbb..66cc23ce8 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -311,6 +311,22 @@ struct AVFilterContext {
  * hardware context information.
  */
 AVBufferRef *hw_device_ctx;
+
+/**
+ * Sets the number of extra hardware frames which the filter will
+ * allocate on its output links for use in following filters or by
+ * the caller.
+ *
+ * Some hardware filters require all frames that they will use for
+ * output to be defined in advance before filtering starts.  For such
+ * filters, any hardware frame pools used for output must therefore be
+ * of fixed size.  The extra frames set here are on top of any number
+ * that the filter needs internally in order to operate normally.
+ *
+ * This field must be set before the graph containing this filer is
+ * configured.
+ */
+int extra_hw_frames;
 };
 
 /**
diff --git a/libavfilter/internal.h b/libavfilter/internal.h
index a377f9b2b..d17f917c6 100644
--- a/libavfilter/internal.h
+++ b/libavfilter/internal.h
@@ -226,4 +226,20 @@ void ff_filter_graph_remove_filter(AVFilterGraph *graph, 
AVFilterContext *filter
  */
 #define FF_FILTER_FLAG_HWFRAME_AWARE (1 << 0)
 
+/**
+ * Perform any additional setup required for hardware frames.
+ *
+ * link->hw_frames_ctx must be set before calling this function.
+ * Inside link->hw_frames_ctx, the fields format, sw_format, width and
+ * height must be set.  If dynamically allocated pools are not supported,
+ * then initial_pool_size must also be set, to the minimum hardware frame
+ * pool size necessary for decode (taking into account reference frames
+ * and delay as appropriate).  If default_pool_size is nonzero, then it
+ * will be used as the pool size if no other modification takes place
+ * (this can be used to preserve compatibility).
+ */
+int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link,
+ int default_pool_size);
+
+
 #endif /* AVFILTER_INTERNAL_H */
-- 
2.11.0

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

[libav-devel] [PATCH 8/8] hwcontext: Perform usual uninitialisation on derived frames contexts

2018-02-04 Thread Mark Thompson
---
 libavutil/hwcontext.c | 17 +++--
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index cccbd6234..34fb720a7 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -205,19 +205,16 @@ static void hwframe_ctx_free(void *opaque, uint8_t *data)
 {
 AVHWFramesContext *ctx = (AVHWFramesContext*)data;
 
-if (ctx->internal->source_frames) {
-av_buffer_unref(>internal->source_frames);
+if (ctx->internal->pool_internal)
+av_buffer_pool_uninit(>internal->pool_internal);
 
-} else {
-if (ctx->internal->pool_internal)
-av_buffer_pool_uninit(>internal->pool_internal);
+if (ctx->internal->hw_type->frames_uninit)
+ctx->internal->hw_type->frames_uninit(ctx);
 
-if (ctx->internal->hw_type->frames_uninit)
-ctx->internal->hw_type->frames_uninit(ctx);
+if (ctx->free)
+ctx->free(ctx);
 
-if (ctx->free)
-ctx->free(ctx);
-}
+av_buffer_unref(>internal->source_frames);
 
 av_buffer_unref(>device_ref);
 
-- 
2.11.0

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

[libav-devel] [PATCH 1/8] lavc: Add support for increasing hardware frame pool sizes

2018-02-04 Thread Mark Thompson
AVCodecContext.extra_hw_frames is added to the size of hardware frame
pools created by libavcodec for APIs which require fixed-size pools.
This allows the user to keep references to a greater number of frames
after decode, which may be necessary for some use-cases.

It is also added to the initial_pool_size value returned by
avcodec_get_hw_frames_parameters() if a fixed-size pool is required.
---
 doc/APIchanges |  3 +++
 libavcodec/avcodec.h   | 14 ++
 libavcodec/decode.c|  9 +
 libavcodec/options_table.h |  1 +
 4 files changed, 27 insertions(+)

diff --git a/doc/APIchanges b/doc/APIchanges
index 0bde3a052..62c7a17e5 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,9 @@ libavutil: 2017-03-23
 
 API changes, most recent first:
 
+2018-xx-xx - xxx - lavc 58.x+1.0 - avcodec.h
+  Add AVCodecContext.extra_hw_frames.
+
 2017-xx-xx - xxx - lavc 58.8.0 - avcodec.h
   Add const to AVCodecContext.hwaccel.
 
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 7eaa0c927..03a3d5bd6 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2739,6 +2739,20 @@ typedef struct AVCodecContext {
  * AVCodecContext.get_format callback)
  */
 int hwaccel_flags;
+
+/**
+ * Video decoding only.  Sets the number of extra hardware frames which
+ * the decoder will allocate for use by the caller.  This must be set
+ * before avcodec_open2() is called.
+ *
+ * Some hardware decoders require all frames that they will use for
+ * output to be defined in advance before decoding starts.  For such
+ * decoders, the hardware frame pool must therefore be of a fixed size.
+ * The extra frames set here are on top of any number that the decoder
+ * needs internally in order to operate normally (for example, frames
+ * used as reference pictures).
+ */
+int extra_hw_frames;
 } AVCodecContext;
 
 /**
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index 12a95d422..e024a3232 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -791,6 +791,15 @@ int avcodec_get_hw_frames_parameters(AVCodecContext *avctx,
 
 ret = hwa->frame_params(avctx, frames_ref);
 if (ret >= 0) {
+AVHWFramesContext *frames_ctx = (AVHWFramesContext*)frames_ref->data;
+
+if (frames_ctx->initial_pool_size) {
+// If the user has requested that extra output surfaces be
+// available then add them here.
+if (avctx->extra_hw_frames > 0)
+frames_ctx->initial_pool_size += avctx->extra_hw_frames;
+}
+
 *out_frames_ref = frames_ref;
 } else {
 av_buffer_unref(_ref);
diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
index 925ef376f..4b0a8344d 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -419,6 +419,7 @@ static const AVOption avcodec_options[] = {
 {"side_data_only_packets", NULL, OFFSET(side_data_only_packets), 
AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, A|V|E },
 #endif
 {"apply_cropping", NULL, OFFSET(apply_cropping), AV_OPT_TYPE_INT, { .i64 = 1 
}, 0, 1, V | D },
+{"extra_hw_frames", "Number of extra hardware frames to allocate for the 
user", OFFSET(extra_hw_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, 
V|D },
 {NULL},
 };
 
-- 
2.11.0

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

[libav-devel] [PATCH 5/8] vf_scale_qsv: Support increasing hardware frame pool size

2018-02-04 Thread Mark Thompson
The deinterlacer does not change, because it does not allocate any new
frames (for output it uses the same pool as the input).
---
 libavfilter/vf_scale_qsv.c | 26 +++---
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c
index 8ef77835d..c568e9625 100644
--- a/libavfilter/vf_scale_qsv.c
+++ b/libavfilter/vf_scale_qsv.c
@@ -71,7 +71,6 @@ enum var_name {
 typedef struct QSVScaleContext {
 const AVClass *class;
 
-AVBufferRef *out_frames_ref;
 /* a clone of the main session, used internally for scaling */
 mfxSession   session;
 
@@ -134,7 +133,6 @@ static void qsvscale_uninit(AVFilterContext *ctx)
 MFXClose(s->session);
 s->session = NULL;
 }
-av_buffer_unref(>out_frames_ref);
 
 av_freep(>mem_ids_in);
 av_freep(>mem_ids_out);
@@ -163,6 +161,7 @@ static int init_out_pool(AVFilterContext *ctx,
  int out_width, int out_height)
 {
 QSVScaleContext *s = ctx->priv;
+AVFilterLink *outlink = ctx->outputs[0];
 
 AVHWFramesContext *in_frames_ctx;
 AVHWFramesContext *out_frames_ctx;
@@ -183,21 +182,25 @@ static int init_out_pool(AVFilterContext *ctx,
 in_format = in_frames_ctx->sw_format;
 out_format= (s->format == AV_PIX_FMT_NONE) ? in_format : s->format;
 
-s->out_frames_ref = av_hwframe_ctx_alloc(in_frames_ctx->device_ref);
-if (!s->out_frames_ref)
+outlink->hw_frames_ctx = av_hwframe_ctx_alloc(in_frames_ctx->device_ref);
+if (!outlink->hw_frames_ctx)
 return AVERROR(ENOMEM);
-out_frames_ctx   = (AVHWFramesContext*)s->out_frames_ref->data;
+out_frames_ctx   = (AVHWFramesContext*)outlink->hw_frames_ctx->data;
 out_frames_hwctx = out_frames_ctx->hwctx;
 
 out_frames_ctx->format= AV_PIX_FMT_QSV;
 out_frames_ctx->width = FFALIGN(out_width,  32);
 out_frames_ctx->height= FFALIGN(out_height, 32);
 out_frames_ctx->sw_format = out_format;
-out_frames_ctx->initial_pool_size = 32;
+out_frames_ctx->initial_pool_size = 4;
 
 out_frames_hwctx->frame_type = in_frames_hwctx->frame_type;
 
-ret = av_hwframe_ctx_init(s->out_frames_ref);
+ret = ff_filter_init_hw_frames(ctx, outlink, 32);
+if (ret < 0)
+return ret;
+
+ret = av_hwframe_ctx_init(outlink->hw_frames_ctx);
 if (ret < 0)
 return ret;
 
@@ -264,7 +267,7 @@ static int init_out_session(AVFilterContext *ctx)
 
 QSVScaleContext   *s = ctx->priv;
 AVHWFramesContext *in_frames_ctx = 
(AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data;
-AVHWFramesContext*out_frames_ctx = 
(AVHWFramesContext*)s->out_frames_ref->data;
+AVHWFramesContext*out_frames_ctx = 
(AVHWFramesContext*)ctx->outputs[0]->hw_frames_ctx->data;
 AVQSVFramesContext  *in_frames_hwctx = in_frames_ctx->hwctx;
 AVQSVFramesContext *out_frames_hwctx = out_frames_ctx->hwctx;
 AVQSVDeviceContext *device_hwctx = in_frames_ctx->device_ctx->hwctx;
@@ -405,8 +408,6 @@ static int init_out_session(AVFilterContext *ctx)
 static int init_scale_session(AVFilterContext *ctx, int in_width, int 
in_height,
   int out_width, int out_height)
 {
-QSVScaleContext *s = ctx->priv;
-
 int ret;
 
 qsvscale_uninit(ctx);
@@ -419,11 +420,6 @@ static int init_scale_session(AVFilterContext *ctx, int 
in_width, int in_height,
 if (ret < 0)
 return ret;
 
-av_buffer_unref(>outputs[0]->hw_frames_ctx);
-ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->out_frames_ref);
-if (!ctx->outputs[0]->hw_frames_ctx)
-return AVERROR(ENOMEM);
-
 return 0;
 }
 
-- 
2.11.0

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

Re: [libav-devel] [PATCH 08/12] vf_hwupload/hwmap: Support setting a fixed pool size

2018-02-04 Thread Mark Thompson
On 30/01/18 05:34, wm4 wrote:
> On Mon, 29 Jan 2018 23:01:25 +
> Mark Thompson <s...@jkqxz.net> wrote:
> 
>> These filters do not directly know whether the API they are using will
>> support dynamic frame pools, so this is somewhat tricky.  If the user
>> set extra_hw_frames, we assume that they are aware of the problem and
>> set a fixed size based on that.  If not, most cases use dynamic sizing
>> just like they did previously.  The hardware-reverse-mapping case for
>> hwmap previously had a large fixed size (64) here, primarily as a hack
>> for QSV use - this is removed and extra_hw_frames will need to be set
>> for QSV to work since it requires fixed-size pools (as the other cases
>> do, and which didn't work before).
>> ---
>>  libavfilter/vf_hwmap.c| 7 ++-
>>  libavfilter/vf_hwupload.c | 3 +++
>>  2 files changed, 9 insertions(+), 1 deletion(-)
>>
>> diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c
>> index b28cb2145..d5ad2768f 100644
>> --- a/libavfilter/vf_hwmap.c
>> +++ b/libavfilter/vf_hwmap.c
>> @@ -138,7 +138,9 @@ static int hwmap_config_output(AVFilterLink *outlink)
>>  frames->sw_format = hwfc->sw_format;
>>  frames->width = hwfc->width;
>>  frames->height= hwfc->height;
>> -frames->initial_pool_size = 64;
>> +
>> +if (avctx->extra_hw_frames >= 0)
>> +frames->initial_pool_size = 2 + avctx->extra_hw_frames;
>>  
>>  err = av_hwframe_ctx_init(ctx->hwframes_ref);
>>  if (err < 0) {
>> @@ -218,6 +220,9 @@ static int hwmap_config_output(AVFilterLink *outlink)
>>  hwfc->width = inlink->w;
>>  hwfc->height= inlink->h;
>>  
>> +if (avctx->extra_hw_frames >= 0)
>> +hwfc->initial_pool_size = 2 + avctx->extra_hw_frames;
>> +
>>  err = av_hwframe_ctx_init(ctx->hwframes_ref);
>>  if (err < 0) {
>>  av_log(avctx, AV_LOG_ERROR, "Failed to create frame "
>> diff --git a/libavfilter/vf_hwupload.c b/libavfilter/vf_hwupload.c
>> index 8cca9f42e..af4ff9b81 100644
>> --- a/libavfilter/vf_hwupload.c
>> +++ b/libavfilter/vf_hwupload.c
>> @@ -133,6 +133,9 @@ static int hwupload_config_output(AVFilterLink *outlink)
>>  ctx->hwframes->width = inlink->w;
>>  ctx->hwframes->height= inlink->h;
>>  
>> +if (avctx->extra_hw_frames >= 0)
>> +ctx->hwframes->initial_pool_size = 2 + avctx->extra_hw_frames;
>> +
>>  err = av_hwframe_ctx_init(ctx->hwframes_ref);
>>  if (err < 0)
>>  goto fail;
> 
> Should we have a hwcontext flag that informs the API user whether the
> frame pools require a fixed size?

That would work for users, but I think you still need something for the default 
value in this particular case.

Suppose the hwcontext definition also included a suggested default pool size - 
that would allow libmfx to have a suggested size of 9001 for hwupload to work 
with qsvenc while others can set more sensible values?

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

Re: [libav-devel] [PATCH V2] lavc/qsvdec: expose frame pic_type and key_frame

2018-01-31 Thread Mark Thompson
On 31/01/18 08:11, Li, Zhong wrote:
>>> @@ -416,6 +421,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
> 
>>>  outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF;
> 
>>>  frame->interlaced_frame =
> 
>>>  !(outsurf->Info.PicStruct &
> 
>> MFX_PICSTRUCT_PROGRESSIVE);
> 
>>> +frame->pict_type =
> 
>> ff_qsv_map_pictype(out_frame->dec_info.FrameType);
> 
>>> +frame->key_frame = !!(out_frame->dec_info.FrameType &
> 
>>> + MFX_FRAMETYPE_IDR);
> 
>>>
> 
>>>  /* update the surface properties */
> 
>>>  if (avctx->pix_fmt == AV_PIX_FMT_QSV)
> 
>>>
> 
>>
> 
>> Does this do the right thing for H.265?  (Can't test right now.)
> 
> 
> 
> Testing should use a HEVC clips
> 
> 
> 
>> I'm asking that because I know that frame types are still a problem for H.265
> 
>> encoding, because not all IRAPs are IDR - when CRA frames are generated
> 
>> they aren't marked as key.  The FrameType field (as used here) is not
> 
>> sufficient in that case, but I never sorted out exactly what does contain the
> 
>> necessary information.
> 
>>
> 
>> - Mark
> 
> 
> 
> Exactly, only IDR type is exposed from FrameType here, and it is set by 
> parsing slice_header 
> (https://github.com/Intel-Media-SDK/MediaSDK/blob/master/_studio/shared/umc/codec/h265_dec/src/umc_h265_bitstream_headers.cpp#L1428
>  )
> 
> But the problem is (I am not familiar with HEVC as well as H264, so please 
> correct me if I am wrong), should CRA frames be treated as key frames?

Yes, they have to be.  IDR, CRA and BLA frames are all IRAP pictures, so they 
are key frames because seeking can always move to that point in the stream.

> See the description as blew (source 
> http://ieeexplore.ieee.org/document/6324417/?part=undefined%7Cfig4#fig4 )
> 
> [cid:image003.jpg@01D39AAE.23C1D950]
> 
> 
> 
> Here some leading pictures such as B30 can’t be decoded when random access 
> from I28.
> 
> As my understanding, all frames behand (in display order) key frame should be 
> decodable.

Yes, all frames after the IRAP in display order should be decodable.  However, 
B30 is not after I28 in display order - it be marked as RASL to indicate that 
it should be skipped when it is found in decode order.

> IDR it can make sure this, but CRA can’t. So at least not all of the CRA 
> frames can be treated as key frames.
> 
> Looks some people agree with me (refer Jeanlf’s comment on 
> https://github.com/gpac/gpac/issues/144)
I'm not familiar with the precise meaning of "sync sample" in this case, so I'm 
not sure.  If it means the same thing as IRAP (a point at which decoding of a 
stream can always start correctly without any pictures which precede it in 
decode order), then the commenter is wrong.


On 31/01/18 08:16, Li, Zhong wrote:
> As your comment, maybe we need to find a HEVC clip with CRA frames to test.

Try the conformance sample RAP_A_docomo_4.bit (you can find it in 
fate/hevc-conformance).  That contains CRA and RASL frames (and no IDR frames 
at all).

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

Re: [libav-devel] [PATCH V2] lavc/qsvdec: expose frame pic_type and key_frame

2018-01-30 Thread Mark Thompson
On 30/01/18 09:52, Zhong Li wrote:
> Currently key_frame and pict_type are unset.
> Add an extra param to fetch the picture type from qsv decoder
> 
> Signed-off-by: ChaoX A Liu 
> Signed-off-by: Zhong Li 
> ---
>  libavcodec/qsv.c  | 24 
>  libavcodec/qsv_internal.h |  3 +++
>  libavcodec/qsvdec.c   |  7 +++
>  3 files changed, 34 insertions(+)
> 
> diff --git a/libavcodec/qsv.c b/libavcodec/qsv.c
> index e78633d..ffe7e6c 100644
> --- a/libavcodec/qsv.c
> +++ b/libavcodec/qsv.c
> @@ -195,6 +195,30 @@ int ff_qsv_find_surface_idx(QSVFramesContext *ctx, 
> QSVFrame *frame)
>  return AVERROR_BUG;
>  }
>  
> +enum AVPictureType ff_qsv_map_pictype(int mfx_pic_type)
> +{
> +enum AVPictureType type;
> +switch (mfx_pic_type & 0x7) {
> +case MFX_FRAMETYPE_I:
> +if (mfx_pic_type & MFX_FRAMETYPE_S)
> +type = AV_PICTURE_TYPE_SI;
> +else
> +type = AV_PICTURE_TYPE_I;
> +break;
> +case MFX_FRAMETYPE_B:
> +type = AV_PICTURE_TYPE_B;
> +break;
> +case MFX_FRAMETYPE_P:
> + if (mfx_pic_type & MFX_FRAMETYPE_S)
> +type = AV_PICTURE_TYPE_SP;
> +else
> +type = AV_PICTURE_TYPE_P;
> +break;
> +}
> +
> +return type;
> +}
> +
>  static int qsv_load_plugins(mfxSession session, const char *load_plugins,
>  void *logctx)
>  {
> diff --git a/libavcodec/qsv_internal.h b/libavcodec/qsv_internal.h
> index 975c8de..07ddc59 100644
> --- a/libavcodec/qsv_internal.h
> +++ b/libavcodec/qsv_internal.h
> @@ -48,6 +48,8 @@ typedef struct QSVMid {
>  typedef struct QSVFrame {
>  AVFrame *frame;
>  mfxFrameSurface1 surface;
> +mfxExtDecodedFrameInfo dec_info;
> +mfxExtBuffer *ext_param;
>  
>  int queued;
>  int used;
> @@ -83,6 +85,7 @@ int ff_qsv_codec_id_to_mfx(enum AVCodecID codec_id);
>  int ff_qsv_profile_to_mfx(enum AVCodecID codec_id, int profile);
>  
>  int ff_qsv_map_pixfmt(enum AVPixelFormat format, uint32_t *fourcc);
> +enum AVPictureType ff_qsv_map_pictype(int mfx_pic_type);
>  
>  int ff_qsv_init_internal_session(AVCodecContext *avctx, mfxSession *session,
>   const char *load_plugins);
> diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c
> index f31172d..9ee4177 100644
> --- a/libavcodec/qsvdec.c
> +++ b/libavcodec/qsvdec.c
> @@ -232,6 +232,11 @@ static int alloc_frame(AVCodecContext *avctx, QSVContext 
> *q, QSVFrame *frame)
>  
>  frame->surface.Data.MemId = >frames_ctx.mids[ret];
>  }
> +frame->surface.Data.ExtParam = >ext_param;
> +frame->surface.Data.NumExtParam = 1;
> +frame->ext_param = (mfxExtBuffer*)>dec_info;
> +frame->dec_info.Header.BufferId = MFX_EXTBUFF_DECODED_FRAME_INFO;
> +frame->dec_info.Header.BufferSz = sizeof(frame->dec_info);
>  
>  frame->used = 1;
>  
> @@ -416,6 +421,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
>  outsurf->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF;
>  frame->interlaced_frame =
>  !(outsurf->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE);
> +frame->pict_type = ff_qsv_map_pictype(out_frame->dec_info.FrameType);
> +frame->key_frame = !!(out_frame->dec_info.FrameType & 
> MFX_FRAMETYPE_IDR);
>  
>  /* update the surface properties */
>  if (avctx->pix_fmt == AV_PIX_FMT_QSV)
> 

Does this do the right thing for H.265?  (Can't test right now.)

I'm asking that because I know that frame types are still a problem for H.265 
encoding, because not all IRAPs are IDR - when CRA frames are generated they 
aren't marked as key.  The FrameType field (as used here) is not sufficient in 
that case, but I never sorted out exactly what does contain the necessary 
information.

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

Re: [libav-devel] [PATCH 04/12] lavc/dxva2: Don't add per-thread surfaces twice

2018-01-30 Thread Mark Thompson
On 30/01/18 05:30, wm4 wrote:
> On Mon, 29 Jan 2018 23:01:21 +
> Mark Thompson <s...@jkqxz.net> wrote:
> 
>> This is already accounted for in the generic code, so it shouldn't also
>> be added here.
>> ---
>>  libavcodec/dxva2.c | 4 
>>  1 file changed, 4 deletions(-)
>>
>> diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
>> index edc8ade96..f111d0b79 100644
>> --- a/libavcodec/dxva2.c
>> +++ b/libavcodec/dxva2.c
>> @@ -611,10 +611,6 @@ int ff_dxva2_common_frame_params(AVCodecContext *avctx,
>>  if (avctx->extra_hw_frames > 0)
>>  num_surfaces += avctx->extra_hw_frames;
>>  
>> -/* add extra surfaces for frame threading */
>> -if (avctx->active_thread_type & FF_THREAD_FRAME)
>> -num_surfaces += avctx->thread_count;
>> -
>>  frames_ctx->sw_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
>>  AV_PIX_FMT_P010 : AV_PIX_FMT_NV12;
>>  frames_ctx->width = FFALIGN(avctx->coded_width, surface_alignment);
> 
> OK, but after this change it's still not correct.
> 
> It looks like the adding of thread surfaces should be moved from the
> ff_decode_get_hw_frames_ctx() to avcodec_get_hw_frames_parameters().
> 
> The public API is supposed to always add them (because it's pretty much
> an implementation detail). If we don't want to have them in the hwaccel
> impls. (like dxva2 in this case), then the public API function must add
> them, or it'd break API users (and require them to know about the
> additional frame threading requirements).

Hmm, yeah.  That also means it's currently wrong for VAAPI in the 
get_hw_frames_parameters() case, since that never gets the per-thread frames 
added.

Will fix this up suitably.

Thanks,

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

Re: [libav-devel] [PATCH 01/12] lavc: Add support for increasing hardware frame pool sizes

2018-01-30 Thread Mark Thompson
On 30/01/18 05:40, wm4 wrote:
> On Mon, 29 Jan 2018 23:01:18 +
> Mark Thompson <s...@jkqxz.net> wrote:
> 
>> AVCodecContext.extra_hw_frames is added to the size of hardware frame
>> pools created by libavcodec for APIs which require fixed-size pools.
>> This allows the user to keep references to a greater number of frames
>> after decode, which may be necessary for some use-cases.
>>
>> It is also added to the initial_pool_size value returned by
>> avcodec_get_hw_frames_parameters() if a fixed-size pool is required.
>> ---
>> On 26/01/18 23:39, wm4 wrote:
>>> On Fri, 26 Jan 2018 23:30:48 +
>>> Mark Thompson <s...@jkqxz.net> wrote:
>>>   
>>>> On 26/01/18 23:13, Mark Thompson wrote:  
>>>>> AVFilterContext.extra_hw_frames functions identically to the field of
>>>>> the same name in AVCodecContext.
>>>>
>>>> Of course, that field doesn't actually exist before this patch now.  
>>>> Updated to reflect that.
>>>>
>>>> Still, should the field be in AVCodecContext as well?  (The 
>>>> hw_frames_parameters API can do this for library users, but it isn't 
>>>> usable in avconv.)  
>>>
>>> Probably makes sense. How else would avconv control this? (Although in
>>> theory avconv could use the avcodec_get_hw_frames_parameters() API.)
>>>
>>> I assume actually this field would just be added to the frames context
>>> returned by avcodec_get_hw_frames_parameters(), since that is used
>>> internally by most hwaccels to allocate a frames context if
>>> hw_device_ctx is used.  
>>
>> Yep, that sounds like a good way to do it.
>>
>> Here is new series with that change and some other minor fixups.  (Not 
>> tested on Windows yet.)
>>
>> Thanks,
>>
>> - Mark
>>
>>
>>  doc/APIchanges |  3 +++
>>  libavcodec/avcodec.h   | 14 ++
>>  libavcodec/options_table.h |  1 +
>>  3 files changed, 18 insertions(+)
>>
>> diff --git a/doc/APIchanges b/doc/APIchanges
>> index 0bde3a052..62c7a17e5 100644
>> --- a/doc/APIchanges
>> +++ b/doc/APIchanges
>> @@ -13,6 +13,9 @@ libavutil: 2017-03-23
>>  
>>  API changes, most recent first:
>>  
>> +2018-xx-xx - xxx - lavc 58.x+1.0 - avcodec.h
>> +  Add AVCodecContext.extra_hw_frames.
>> +
>>  2017-xx-xx - xxx - lavc 58.8.0 - avcodec.h
>>Add const to AVCodecContext.hwaccel.
>>  
>> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
>> index 7eaa0c927..03a3d5bd6 100644
>> --- a/libavcodec/avcodec.h
>> +++ b/libavcodec/avcodec.h
>> @@ -2739,6 +2739,20 @@ typedef struct AVCodecContext {
>>   * AVCodecContext.get_format callback)
>>   */
>>  int hwaccel_flags;
>> +
>> +/**
>> + * Video decoding only.  Sets the number of extra hardware frames which
>> + * the decoder will allocate for use by the caller.  This must be set
>> + * before avcodec_open2() is called.
>> + *
>> + * Some hardware decoders require all frames that they will use for
>> + * output to be defined in advance before decoding starts.  For such
>> + * decoders, the hardware frame pool must therefore be of a fixed size.
>> + * The extra frames set here are on top of any number that the decoder
>> + * needs internally in order to operate normally (for example, frames
>> + * used as reference pictures).
>> + */
>> +int extra_hw_frames;
>>  } AVCodecContext;
>>  
>>  /**
>> diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
>> index 925ef376f..4b0a8344d 100644
>> --- a/libavcodec/options_table.h
>> +++ b/libavcodec/options_table.h
>> @@ -419,6 +419,7 @@ static const AVOption avcodec_options[] = {
>>  {"side_data_only_packets", NULL, OFFSET(side_data_only_packets), 
>> AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, A|V|E },
>>  #endif
>>  {"apply_cropping", NULL, OFFSET(apply_cropping), AV_OPT_TYPE_INT, { .i64 = 
>> 1 }, 0, 1, V | D },
>> +{"extra_hw_frames", "Number of extra hardware frames to allocate for the 
>> user", OFFSET(extra_hw_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, 
>> V|D },
>>  {NULL},
>>  };
>>  
> 
> Why not do this in generic code instead of every hwaccel backend?

Duh, yeah.  Didn't think about that properly, will change :)

> Why not set this to the default of 4 ff_decode_get_hw_frames_ctx()
> implies?

I think we want to know whether the value is set or not.  That's more visible 
in lavfi where existing filters (especially libmfx) have a default value much 
higher than they actually need, and I think it may want to apply to lavc as 
well (if libmfx gets hw_device_ctx support and avconv_qsv goes away, say).

> Otherwise generally LGTM.

Thanks,

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

Re: [libav-devel] [PATCH] hwcontext_qsv: Fix qsv hwupload failure issue

2018-01-30 Thread Mark Thompson
On 30/01/18 03:35, Song, Ruiling wrote:
>> -Original Message-
>> From: libav-devel [mailto:libav-devel-boun...@libav.org] On Behalf Of wm4
>> Sent: Friday, January 26, 2018 5:15 PM
>> To: libav-devel@libav.org
>> Subject: Re: [libav-devel] [PATCH] hwcontext_qsv: Fix qsv hwupload failure 
>> issue
>>
>> On Fri, 26 Jan 2018 05:56:46 +
>> "Li, Zhong"  wrote:
>>
 From: libav-devel [mailto:libav-devel-boun...@libav.org] On Behalf Of
 Ruiling Song
 Sent: Friday, January 26, 2018 9:17 AM
 To: libav-devel@libav.org
 Subject: [libav-devel] [PATCH] hwcontext_qsv: Fix qsv hwupload failure 
 issue

 From: "Ruiling, Song" 

 1.) the initial_pool_size need to be set instead of zero.
 2.) the PicStruct is required by MediaSDK, so give a default value.

 A simple command to reproduce the issue:
 avconv -i INPUT -init_hw_device qsv=foo -filter_hw_device foo -vf
 format=nv12,hwupload -c:v h264_qsv ... OUTPUT

 Signed-off-by: Ruiling Song 
 ---
  libavutil/hwcontext_qsv.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

 diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index
 9270b22..14f26c6 100644
 --- a/libavutil/hwcontext_qsv.c
 +++ b/libavutil/hwcontext_qsv.c
 @@ -313,6 +313,7 @@ static int qsv_init_surface(AVHWFramesContext *ctx,
 mfxFrameSurface1 *surf)
  surf->Info.CropH  = ctx->height;
  surf->Info.FrameRateExtN  = 25;
  surf->Info.FrameRateExtD  = 1;
 +surf->Info.PicStruct  = MFX_PICSTRUCT_PROGRESSIVE;

  return 0;
  }
 @@ -325,8 +326,7 @@ static int qsv_init_pool(AVHWFramesContext *ctx,
 uint32_t fourcc)
  int i, ret = 0;

  if (ctx->initial_pool_size <= 0) {
 -av_log(ctx, AV_LOG_ERROR, "QSV requires a fixed frame pool
 size\n");
>>>
>>> Should keep this log message as a warning be better?
>>>
 -return AVERROR(EINVAL);
 +ctx->initial_pool_size = 64;
>>
>> That doesn't really feel appropriate. If a fixed size pool is required,
>> the user should simply be forced to specify a size. Making it use a
>> random value doesn't make too much sense to me, and the required size
>> is going to depend on the caller's use cases. In addition 64 by default
>> sounds like a huge waste of memory.
> 
> Thanks for your comment!
> But I think it is better if we don't force the user to explicitly setup a 
> value to get it work.
> Less parameters means less burden for end-users. If this rule is not 
> applicable here, please correct me.
> I am not sure why a default workable value is not as good here. Could you 
> share me more thought?
> And there are more places that set default values to initial_pool_size:
> Inside libavfilter/qsvvpp.c it also sets initial_pool_size to 64.
> Inside avtools/avcov_qsv.c, it sets initial_pool_size to 32.
> I am not sure do you have any comment on this? Will be 32 looks a little 
> better?

IMO any fixed number is a problem.  The user can always break it by holding on 
to more frames - the lookahead option in the libmfx encoder is the easiest way 
to eat lots of frames, but there is nothing stopping the user just not giving 
the frames back for a long time.  The advantage of the extra_hw_frames option 
is that it actually codifies how many frames the user is allowed to hold, so 
that if they do hold more it is clear where the error is rather than the answer 
being "um, that doesn't work, sorry".

It is unclear what the default should be before that number is applied, but 
probably not something particularly large because it is very memory-wasteful if 
you have 64 surfaces and only ever use 2 (currently a common problem when 
chaining filters together - it's only the encoder which wants many).  Obviously 
that can all solved by some sort of magic autonegotiation, but noone has yet 
offered a plan of how that could work.

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

[libav-devel] [PATCH 06/12] vf_*_vaapi: Support increasing hardware frame pool size

2018-01-29 Thread Mark Thompson
Defaults to 10 frames to preserve compatibility, but can allocate
fewer if extra_hw_frames is set explicitly.
---
 libavfilter/vf_deinterlace_vaapi.c | 39 +++
 libavfilter/vf_scale_vaapi.c   | 42 +++---
 2 files changed, 33 insertions(+), 48 deletions(-)

diff --git a/libavfilter/vf_deinterlace_vaapi.c 
b/libavfilter/vf_deinterlace_vaapi.c
index 95a0f4041..082df8914 100644
--- a/libavfilter/vf_deinterlace_vaapi.c
+++ b/libavfilter/vf_deinterlace_vaapi.c
@@ -53,8 +53,6 @@ typedef struct DeintVAAPIContext {
 AVBufferRef   *input_frames_ref;
 AVHWFramesContext *input_frames;
 
-AVBufferRef   *output_frames_ref;
-AVHWFramesContext *output_frames;
 intoutput_height;
 intoutput_width;
 
@@ -236,6 +234,7 @@ static int deint_vaapi_config_output(AVFilterLink *outlink)
 DeintVAAPIContext*ctx = avctx->priv;
 AVVAAPIHWConfig *hwconfig = NULL;
 AVHWFramesConstraints *constraints = NULL;
+AVHWFramesContext *output_frames;
 AVVAAPIFramesContext *va_frames;
 VAStatus vas;
 int err;
@@ -287,34 +286,35 @@ static int deint_vaapi_config_output(AVFilterLink 
*outlink)
 goto fail;
 }
 
-ctx->output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref);
-if (!ctx->output_frames_ref) {
+outlink->hw_frames_ctx = av_hwframe_ctx_alloc(ctx->device_ref);
+if (!outlink->hw_frames_ctx) {
 av_log(avctx, AV_LOG_ERROR, "Failed to create HW frame context "
"for output.\n");
 err = AVERROR(ENOMEM);
 goto fail;
 }
 
-ctx->output_frames = (AVHWFramesContext*)ctx->output_frames_ref->data;
+output_frames = (AVHWFramesContext*)outlink->hw_frames_ctx->data;
 
-ctx->output_frames->format= AV_PIX_FMT_VAAPI;
-ctx->output_frames->sw_format = ctx->input_frames->sw_format;
-ctx->output_frames->width = ctx->output_width;
-ctx->output_frames->height= ctx->output_height;
+output_frames->format= AV_PIX_FMT_VAAPI;
+output_frames->sw_format = ctx->input_frames->sw_format;
+output_frames->width = ctx->output_width;
+output_frames->height= ctx->output_height;
 
-// The number of output frames we need is determined by what follows
-// the filter.  If it's an encoder with complex frame reference
-// structures then this could be very high.
-ctx->output_frames->initial_pool_size = 10;
+output_frames->initial_pool_size = 4;
+
+err = ff_filter_init_hw_frames(avctx, outlink, 10);
+if (err < 0)
+goto fail;
 
-err = av_hwframe_ctx_init(ctx->output_frames_ref);
+err = av_hwframe_ctx_init(outlink->hw_frames_ctx);
 if (err < 0) {
 av_log(avctx, AV_LOG_ERROR, "Failed to initialise VAAPI frame "
"context for output: %d\n", err);
 goto fail;
 }
 
-va_frames = ctx->output_frames->hwctx;
+va_frames = output_frames->hwctx;
 
 av_assert0(ctx->va_context == VA_INVALID_ID);
 vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
@@ -340,18 +340,12 @@ static int deint_vaapi_config_output(AVFilterLink 
*outlink)
 outlink->frame_rate = av_mul_q(inlink->frame_rate,
(AVRational) { ctx->field_rate, 1 });
 
-outlink->hw_frames_ctx = av_buffer_ref(ctx->output_frames_ref);
-if (!outlink->hw_frames_ctx) {
-err = AVERROR(ENOMEM);
-goto fail;
-}
-
 av_freep();
 av_hwframe_constraints_free();
 return 0;
 
 fail:
-av_buffer_unref(>output_frames_ref);
+av_buffer_unref(>hw_frames_ctx);
 av_freep();
 av_hwframe_constraints_free();
 return err;
@@ -601,7 +595,6 @@ static av_cold void deint_vaapi_uninit(AVFilterContext 
*avctx)
 deint_vaapi_pipeline_uninit(avctx);
 
 av_buffer_unref(>input_frames_ref);
-av_buffer_unref(>output_frames_ref);
 av_buffer_unref(>device_ref);
 }
 
diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c
index 4c8f2cf4e..0ab5518b5 100644
--- a/libavfilter/vf_scale_vaapi.c
+++ b/libavfilter/vf_scale_vaapi.c
@@ -22,6 +22,7 @@
 #include 
 
 #include "libavutil/avassert.h"
+#include "libavutil/common.h"
 #include "libavutil/hwcontext.h"
 #include "libavutil/hwcontext_vaapi.h"
 #include "libavutil/mem.h"
@@ -46,9 +47,6 @@ typedef struct ScaleVAAPIContext {
 AVBufferRef   *input_frames_ref;
 AVHWFramesContext *input_frames;
 
-AVBufferRef   *output_frames_ref;
-AVHWFramesContext *output_frames;
-
 char *output_format_string;
 enum AVPixelFormat output_format;
 int output_width;
@@ -83,7 +81,6 @@ static int scale_vaapi_pipeline_uninit(ScaleVAAPIContext *ctx)
 ctx->va_config = VA_INVALID_ID;
 }
 
-av_buffer_unref(>output_frames_ref);
 av_buffer_unref(>device_ref);
 ctx->hwctx = 0;
 
@@ -115,6 +112,7 @@ static int scale_vaapi_config_output(AVFilterLink *outlink)
 ScaleVAAPIContext *ctx = 

[libav-devel] [PATCH 04/12] lavc/dxva2: Don't add per-thread surfaces twice

2018-01-29 Thread Mark Thompson
This is already accounted for in the generic code, so it shouldn't also
be added here.
---
 libavcodec/dxva2.c | 4 
 1 file changed, 4 deletions(-)

diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
index edc8ade96..f111d0b79 100644
--- a/libavcodec/dxva2.c
+++ b/libavcodec/dxva2.c
@@ -611,10 +611,6 @@ int ff_dxva2_common_frame_params(AVCodecContext *avctx,
 if (avctx->extra_hw_frames > 0)
 num_surfaces += avctx->extra_hw_frames;
 
-/* add extra surfaces for frame threading */
-if (avctx->active_thread_type & FF_THREAD_FRAME)
-num_surfaces += avctx->thread_count;
-
 frames_ctx->sw_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
 AV_PIX_FMT_P010 : AV_PIX_FMT_NV12;
 frames_ctx->width = FFALIGN(avctx->coded_width, surface_alignment);
-- 
2.11.0

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

[libav-devel] [PATCH 02/12] lavc/vaapi: Support increasing hardware frame pool size

2018-01-29 Thread Mark Thompson
---
 libavcodec/vaapi_decode.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c
index cc79875ef..7ff42317e 100644
--- a/libavcodec/vaapi_decode.c
+++ b/libavcodec/vaapi_decode.c
@@ -452,6 +452,9 @@ static int vaapi_decode_make_config(AVCodecContext *avctx,
 default:
 frames->initial_pool_size += 2;
 }
+
+if (avctx->extra_hw_frames > 0)
+frames->initial_pool_size += avctx->extra_hw_frames;
 }
 
 av_hwframe_constraints_free();
-- 
2.11.0

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

[libav-devel] [PATCH 09/12] hwcontext: Fix documentation for av_hwdevice_ctx_alloc()

2018-01-29 Thread Mark Thompson
From: Jun Zhao <jun.z...@intel.com>

From ffmpeg commit 9365dfcbf665b83b2e60c5ec5e2abf1f0a49e2c3.

Signed-off-by: Jun Zhao <jun.z...@intel.com>
Signed-off-by: Mark Thompson <s...@jkqxz.net>
---
 libavutil/hwcontext.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index 203ea510e..ba293d72e 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -252,8 +252,9 @@ const char *av_hwdevice_get_type_name(enum AVHWDeviceType 
type);
 enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev);
 
 /**
- * Allocate an AVHWDeviceContext for a given pixel format.
+ * Allocate an AVHWDeviceContext for a given hardware type.
  *
+ * @param type the type of the hardware device to allocate.
  * @return a reference to the newly created AVHWDeviceContext on success or 
NULL
  * on failure.
  */
-- 
2.11.0

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

[libav-devel] [PATCH 01/12] lavc: Add support for increasing hardware frame pool sizes

2018-01-29 Thread Mark Thompson
AVCodecContext.extra_hw_frames is added to the size of hardware frame
pools created by libavcodec for APIs which require fixed-size pools.
This allows the user to keep references to a greater number of frames
after decode, which may be necessary for some use-cases.

It is also added to the initial_pool_size value returned by
avcodec_get_hw_frames_parameters() if a fixed-size pool is required.
---
On 26/01/18 23:39, wm4 wrote:
> On Fri, 26 Jan 2018 23:30:48 +
> Mark Thompson <s...@jkqxz.net> wrote:
> 
>> On 26/01/18 23:13, Mark Thompson wrote:
>>> AVFilterContext.extra_hw_frames functions identically to the field of
>>> the same name in AVCodecContext.  
>>
>> Of course, that field doesn't actually exist before this patch now.  Updated 
>> to reflect that.
>>
>> Still, should the field be in AVCodecContext as well?  (The 
>> hw_frames_parameters API can do this for library users, but it isn't usable 
>> in avconv.)
> 
> Probably makes sense. How else would avconv control this? (Although in
> theory avconv could use the avcodec_get_hw_frames_parameters() API.)
> 
> I assume actually this field would just be added to the frames context
> returned by avcodec_get_hw_frames_parameters(), since that is used
> internally by most hwaccels to allocate a frames context if
> hw_device_ctx is used.

Yep, that sounds like a good way to do it.

Here is new series with that change and some other minor fixups.  (Not tested 
on Windows yet.)

Thanks,

- Mark


 doc/APIchanges |  3 +++
 libavcodec/avcodec.h   | 14 ++
 libavcodec/options_table.h |  1 +
 3 files changed, 18 insertions(+)

diff --git a/doc/APIchanges b/doc/APIchanges
index 0bde3a052..62c7a17e5 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,9 @@ libavutil: 2017-03-23
 
 API changes, most recent first:
 
+2018-xx-xx - xxx - lavc 58.x+1.0 - avcodec.h
+  Add AVCodecContext.extra_hw_frames.
+
 2017-xx-xx - xxx - lavc 58.8.0 - avcodec.h
   Add const to AVCodecContext.hwaccel.
 
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 7eaa0c927..03a3d5bd6 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2739,6 +2739,20 @@ typedef struct AVCodecContext {
  * AVCodecContext.get_format callback)
  */
 int hwaccel_flags;
+
+/**
+ * Video decoding only.  Sets the number of extra hardware frames which
+ * the decoder will allocate for use by the caller.  This must be set
+ * before avcodec_open2() is called.
+ *
+ * Some hardware decoders require all frames that they will use for
+ * output to be defined in advance before decoding starts.  For such
+ * decoders, the hardware frame pool must therefore be of a fixed size.
+ * The extra frames set here are on top of any number that the decoder
+ * needs internally in order to operate normally (for example, frames
+ * used as reference pictures).
+ */
+int extra_hw_frames;
 } AVCodecContext;
 
 /**
diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
index 925ef376f..4b0a8344d 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -419,6 +419,7 @@ static const AVOption avcodec_options[] = {
 {"side_data_only_packets", NULL, OFFSET(side_data_only_packets), 
AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, A|V|E },
 #endif
 {"apply_cropping", NULL, OFFSET(apply_cropping), AV_OPT_TYPE_INT, { .i64 = 1 
}, 0, 1, V | D },
+{"extra_hw_frames", "Number of extra hardware frames to allocate for the 
user", OFFSET(extra_hw_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, 
V|D },
 {NULL},
 };
 
-- 
2.11.0

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

[libav-devel] [PATCH 03/12] lavc/dxva2: Support increasing hardware frame pool size

2018-01-29 Thread Mark Thompson
---
 libavcodec/dxva2.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
index e34409d44..edc8ade96 100644
--- a/libavcodec/dxva2.c
+++ b/libavcodec/dxva2.c
@@ -608,6 +608,9 @@ int ff_dxva2_common_frame_params(AVCodecContext *avctx,
 else
 num_surfaces += 2;
 
+if (avctx->extra_hw_frames > 0)
+num_surfaces += avctx->extra_hw_frames;
+
 /* add extra surfaces for frame threading */
 if (avctx->active_thread_type & FF_THREAD_FRAME)
 num_surfaces += avctx->thread_count;
-- 
2.11.0

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

[libav-devel] [PATCH 08/12] vf_hwupload/hwmap: Support setting a fixed pool size

2018-01-29 Thread Mark Thompson
These filters do not directly know whether the API they are using will
support dynamic frame pools, so this is somewhat tricky.  If the user
set extra_hw_frames, we assume that they are aware of the problem and
set a fixed size based on that.  If not, most cases use dynamic sizing
just like they did previously.  The hardware-reverse-mapping case for
hwmap previously had a large fixed size (64) here, primarily as a hack
for QSV use - this is removed and extra_hw_frames will need to be set
for QSV to work since it requires fixed-size pools (as the other cases
do, and which didn't work before).
---
 libavfilter/vf_hwmap.c| 7 ++-
 libavfilter/vf_hwupload.c | 3 +++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c
index b28cb2145..d5ad2768f 100644
--- a/libavfilter/vf_hwmap.c
+++ b/libavfilter/vf_hwmap.c
@@ -138,7 +138,9 @@ static int hwmap_config_output(AVFilterLink *outlink)
 frames->sw_format = hwfc->sw_format;
 frames->width = hwfc->width;
 frames->height= hwfc->height;
-frames->initial_pool_size = 64;
+
+if (avctx->extra_hw_frames >= 0)
+frames->initial_pool_size = 2 + avctx->extra_hw_frames;
 
 err = av_hwframe_ctx_init(ctx->hwframes_ref);
 if (err < 0) {
@@ -218,6 +220,9 @@ static int hwmap_config_output(AVFilterLink *outlink)
 hwfc->width = inlink->w;
 hwfc->height= inlink->h;
 
+if (avctx->extra_hw_frames >= 0)
+hwfc->initial_pool_size = 2 + avctx->extra_hw_frames;
+
 err = av_hwframe_ctx_init(ctx->hwframes_ref);
 if (err < 0) {
 av_log(avctx, AV_LOG_ERROR, "Failed to create frame "
diff --git a/libavfilter/vf_hwupload.c b/libavfilter/vf_hwupload.c
index 8cca9f42e..af4ff9b81 100644
--- a/libavfilter/vf_hwupload.c
+++ b/libavfilter/vf_hwupload.c
@@ -133,6 +133,9 @@ static int hwupload_config_output(AVFilterLink *outlink)
 ctx->hwframes->width = inlink->w;
 ctx->hwframes->height= inlink->h;
 
+if (avctx->extra_hw_frames >= 0)
+ctx->hwframes->initial_pool_size = 2 + avctx->extra_hw_frames;
+
 err = av_hwframe_ctx_init(ctx->hwframes_ref);
 if (err < 0)
 goto fail;
-- 
2.11.0

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

[libav-devel] [PATCH 07/12] vf_scale_qsv: Support increasing hardware frame pool size

2018-01-29 Thread Mark Thompson
The deinterlacer does not change, because it does not allocate any new
frames (for output it uses the same pool as the input).
---
 libavfilter/vf_scale_qsv.c | 26 +++---
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c
index 8ef77835d..c568e9625 100644
--- a/libavfilter/vf_scale_qsv.c
+++ b/libavfilter/vf_scale_qsv.c
@@ -71,7 +71,6 @@ enum var_name {
 typedef struct QSVScaleContext {
 const AVClass *class;
 
-AVBufferRef *out_frames_ref;
 /* a clone of the main session, used internally for scaling */
 mfxSession   session;
 
@@ -134,7 +133,6 @@ static void qsvscale_uninit(AVFilterContext *ctx)
 MFXClose(s->session);
 s->session = NULL;
 }
-av_buffer_unref(>out_frames_ref);
 
 av_freep(>mem_ids_in);
 av_freep(>mem_ids_out);
@@ -163,6 +161,7 @@ static int init_out_pool(AVFilterContext *ctx,
  int out_width, int out_height)
 {
 QSVScaleContext *s = ctx->priv;
+AVFilterLink *outlink = ctx->outputs[0];
 
 AVHWFramesContext *in_frames_ctx;
 AVHWFramesContext *out_frames_ctx;
@@ -183,21 +182,25 @@ static int init_out_pool(AVFilterContext *ctx,
 in_format = in_frames_ctx->sw_format;
 out_format= (s->format == AV_PIX_FMT_NONE) ? in_format : s->format;
 
-s->out_frames_ref = av_hwframe_ctx_alloc(in_frames_ctx->device_ref);
-if (!s->out_frames_ref)
+outlink->hw_frames_ctx = av_hwframe_ctx_alloc(in_frames_ctx->device_ref);
+if (!outlink->hw_frames_ctx)
 return AVERROR(ENOMEM);
-out_frames_ctx   = (AVHWFramesContext*)s->out_frames_ref->data;
+out_frames_ctx   = (AVHWFramesContext*)outlink->hw_frames_ctx->data;
 out_frames_hwctx = out_frames_ctx->hwctx;
 
 out_frames_ctx->format= AV_PIX_FMT_QSV;
 out_frames_ctx->width = FFALIGN(out_width,  32);
 out_frames_ctx->height= FFALIGN(out_height, 32);
 out_frames_ctx->sw_format = out_format;
-out_frames_ctx->initial_pool_size = 32;
+out_frames_ctx->initial_pool_size = 4;
 
 out_frames_hwctx->frame_type = in_frames_hwctx->frame_type;
 
-ret = av_hwframe_ctx_init(s->out_frames_ref);
+ret = ff_filter_init_hw_frames(ctx, outlink, 32);
+if (ret < 0)
+return ret;
+
+ret = av_hwframe_ctx_init(outlink->hw_frames_ctx);
 if (ret < 0)
 return ret;
 
@@ -264,7 +267,7 @@ static int init_out_session(AVFilterContext *ctx)
 
 QSVScaleContext   *s = ctx->priv;
 AVHWFramesContext *in_frames_ctx = 
(AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data;
-AVHWFramesContext*out_frames_ctx = 
(AVHWFramesContext*)s->out_frames_ref->data;
+AVHWFramesContext*out_frames_ctx = 
(AVHWFramesContext*)ctx->outputs[0]->hw_frames_ctx->data;
 AVQSVFramesContext  *in_frames_hwctx = in_frames_ctx->hwctx;
 AVQSVFramesContext *out_frames_hwctx = out_frames_ctx->hwctx;
 AVQSVDeviceContext *device_hwctx = in_frames_ctx->device_ctx->hwctx;
@@ -405,8 +408,6 @@ static int init_out_session(AVFilterContext *ctx)
 static int init_scale_session(AVFilterContext *ctx, int in_width, int 
in_height,
   int out_width, int out_height)
 {
-QSVScaleContext *s = ctx->priv;
-
 int ret;
 
 qsvscale_uninit(ctx);
@@ -419,11 +420,6 @@ static int init_scale_session(AVFilterContext *ctx, int 
in_width, int in_height,
 if (ret < 0)
 return ret;
 
-av_buffer_unref(>outputs[0]->hw_frames_ctx);
-ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->out_frames_ref);
-if (!ctx->outputs[0]->hw_frames_ctx)
-return AVERROR(ENOMEM);
-
 return 0;
 }
 
-- 
2.11.0

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

[libav-devel] [PATCH 11/12] hwcontext: Perform usual uninitialisation on derived frames contexts

2018-01-29 Thread Mark Thompson
---
 libavutil/hwcontext.c | 17 +++--
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index 157b73872..3ac17572b 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -205,19 +205,16 @@ static void hwframe_ctx_free(void *opaque, uint8_t *data)
 {
 AVHWFramesContext *ctx = (AVHWFramesContext*)data;
 
-if (ctx->internal->source_frames) {
-av_buffer_unref(>internal->source_frames);
+if (ctx->internal->pool_internal)
+av_buffer_pool_uninit(>internal->pool_internal);
 
-} else {
-if (ctx->internal->pool_internal)
-av_buffer_pool_uninit(>internal->pool_internal);
+if (ctx->internal->hw_type->frames_uninit)
+ctx->internal->hw_type->frames_uninit(ctx);
 
-if (ctx->internal->hw_type->frames_uninit)
-ctx->internal->hw_type->frames_uninit(ctx);
+if (ctx->free)
+ctx->free(ctx);
 
-if (ctx->free)
-ctx->free(ctx);
-}
+av_buffer_unref(>internal->source_frames);
 
 av_buffer_unref(>device_ref);
 
-- 
2.11.0

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

[libav-devel] [PATCH 12/12] hwcontext: Fix memory leak on derived frame allocation failure

2018-01-29 Thread Mark Thompson
---
 libavutil/hwcontext.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index 3ac17572b..34fb720a7 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -467,8 +467,10 @@ int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, 
AVFrame *frame, int flags)
 
 ret = av_hwframe_get_buffer(ctx->internal->source_frames,
 src_frame, 0);
-if (ret < 0)
+if (ret < 0) {
+av_frame_free(_frame);
 return ret;
+}
 
 ret = av_hwframe_map(frame, src_frame,
  ctx->internal->source_allocation_map_flags);
-- 
2.11.0

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

[libav-devel] [PATCH 10/12] hwcontext: Perform usual initialisation on derived device contexts

2018-01-29 Thread Mark Thompson
The initialisation should be common.  For libmfx, it was previously
happening in the derivation function and this moves it out.
---
 libavutil/hwcontext.c |  4 
 libavutil/hwcontext_qsv.c | 11 ---
 2 files changed, 4 insertions(+), 11 deletions(-)

diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index 6dc95bba1..157b73872 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -643,6 +643,10 @@ int av_hwdevice_ctx_create_derived(AVBufferRef 
**dst_ref_ptr,
 goto fail;
 
 done:
+ret = av_hwdevice_ctx_init(dst_ref);
+if (ret < 0)
+goto fail;
+
 *dst_ref_ptr = dst_ref;
 return 0;
 
diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index 9270b2258..9fa603c35 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -989,7 +989,6 @@ static int qsv_device_derive_from_child(AVHWDeviceContext 
*ctx,
 int flags)
 {
 AVQSVDeviceContext *hwctx = ctx->hwctx;
-QSVDeviceContext   *s = ctx->internal->priv;
 
 mfxVersionver = { { 3, 1 } };
 mfxHDLhandle;
@@ -1058,16 +1057,6 @@ static int 
qsv_device_derive_from_child(AVHWDeviceContext *ctx,
 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:
-- 
2.11.0

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

[libav-devel] [PATCH 05/12] lavfi: Add support for increasing hardware frame pool sizes

2018-01-29 Thread Mark Thompson
AVFilterContext.extra_hw_frames functions identically to the field of
the same name in AVCodecContext.
---
 doc/APIchanges |  3 +++
 libavfilter/avfilter.c | 23 +++
 libavfilter/avfilter.h | 16 
 libavfilter/internal.h | 16 
 4 files changed, 58 insertions(+)

diff --git a/doc/APIchanges b/doc/APIchanges
index 62c7a17e5..824333b9a 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,9 @@ libavutil: 2017-03-23
 
 API changes, most recent first:
 
+2018-xx-xx - xxx - lavfi 7.x+1.0 - avfilter.h
+  Add AVFilterContext.extra_hw_frames.
+
 2018-xx-xx - xxx - lavc 58.x+1.0 - avcodec.h
   Add AVCodecContext.extra_hw_frames.
 
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 83c1a7c20..2c4a385ea 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -368,6 +368,8 @@ static const AVOption avfilter_options[] = {
 { "thread_type", "Allowed thread types", OFFSET(thread_type), 
AV_OPT_TYPE_FLAGS,
 { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, FLAGS, "thread_type" },
 { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE 
}, .unit = "thread_type" },
+{ "extra_hw_frames", "Number of extra hardware frames to allocate for the 
user",
+OFFSET(extra_hw_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, 
FLAGS },
 { NULL },
 };
 
@@ -707,3 +709,24 @@ const AVClass *avfilter_get_class(void)
 {
 return _class;
 }
+
+int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link,
+ int default_pool_size)
+{
+AVHWFramesContext *frames;
+
+// Must already be set by caller.
+av_assert0(link->hw_frames_ctx);
+
+frames = (AVHWFramesContext*)link->hw_frames_ctx->data;
+
+if (frames->initial_pool_size == 0) {
+// Dynamic allocation is necessarily supported.
+} else if (avctx->extra_hw_frames >= 0) {
+frames->initial_pool_size += avctx->extra_hw_frames;
+} else {
+frames->initial_pool_size = default_pool_size;
+}
+
+return 0;
+}
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 6df69dbbb..66cc23ce8 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -311,6 +311,22 @@ struct AVFilterContext {
  * hardware context information.
  */
 AVBufferRef *hw_device_ctx;
+
+/**
+ * Sets the number of extra hardware frames which the filter will
+ * allocate on its output links for use in following filters or by
+ * the caller.
+ *
+ * Some hardware filters require all frames that they will use for
+ * output to be defined in advance before filtering starts.  For such
+ * filters, any hardware frame pools used for output must therefore be
+ * of fixed size.  The extra frames set here are on top of any number
+ * that the filter needs internally in order to operate normally.
+ *
+ * This field must be set before the graph containing this filer is
+ * configured.
+ */
+int extra_hw_frames;
 };
 
 /**
diff --git a/libavfilter/internal.h b/libavfilter/internal.h
index a377f9b2b..d17f917c6 100644
--- a/libavfilter/internal.h
+++ b/libavfilter/internal.h
@@ -226,4 +226,20 @@ void ff_filter_graph_remove_filter(AVFilterGraph *graph, 
AVFilterContext *filter
  */
 #define FF_FILTER_FLAG_HWFRAME_AWARE (1 << 0)
 
+/**
+ * Perform any additional setup required for hardware frames.
+ *
+ * link->hw_frames_ctx must be set before calling this function.
+ * Inside link->hw_frames_ctx, the fields format, sw_format, width and
+ * height must be set.  If dynamically allocated pools are not supported,
+ * then initial_pool_size must also be set, to the minimum hardware frame
+ * pool size necessary for decode (taking into account reference frames
+ * and delay as appropriate).  If default_pool_size is nonzero, then it
+ * will be used as the pool size if no other modification takes place
+ * (this can be used to preserve compatibility).
+ */
+int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link,
+ int default_pool_size);
+
+
 #endif /* AVFILTER_INTERNAL_H */
-- 
2.11.0

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

Re: [libav-devel] [PATCH 1/8] lavfi: Add support for modifying hardware frame pool sizes

2018-01-26 Thread Mark Thompson
On 26/01/18 23:13, Mark Thompson wrote:
> AVFilterContext.extra_hw_frames functions identically to the field of
> the same name in AVCodecContext.

Of course, that field doesn't actually exist before this patch now.  Updated to 
reflect that.

Still, should the field be in AVCodecContext as well?  (The 
hw_frames_parameters API can do this for library users, but it isn't usable in 
avconv.)

- Mark


> ---
>  doc/APIchanges |  3 +++
>  libavfilter/avfilter.c | 23 +++
>  libavfilter/avfilter.h | 13 +
>  libavfilter/internal.h | 16 
>  4 files changed, 55 insertions(+)
> 
> diff --git a/doc/APIchanges b/doc/APIchanges
> index 0bde3a052..645ac231a 100644
> --- a/doc/APIchanges
> +++ b/doc/APIchanges
> @@ -13,6 +13,9 @@ libavutil: 2017-03-23
>  
>  API changes, most recent first:
>  
> +2018-xx-xx - xxx - lavfi 7.x+1.0 - avfilter.h
> +  Add AVFilterContext.extra_hw_frames.
> +
>  2017-xx-xx - xxx - lavc 58.8.0 - avcodec.h
>Add const to AVCodecContext.hwaccel.
>  
> diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
> index 83c1a7c20..2c4a385ea 100644
> --- a/libavfilter/avfilter.c
> +++ b/libavfilter/avfilter.c
> @@ -368,6 +368,8 @@ static const AVOption avfilter_options[] = {
>  { "thread_type", "Allowed thread types", OFFSET(thread_type), 
> AV_OPT_TYPE_FLAGS,
>  { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, FLAGS, "thread_type" },
>  { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 
> AVFILTER_THREAD_SLICE }, .unit = "thread_type" },
> +{ "extra_hw_frames", "Number of extra hardware frames to allocate for 
> the user",
> +OFFSET(extra_hw_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 
> INT_MAX, FLAGS },
>  { NULL },
>  };
>  
> @@ -707,3 +709,24 @@ const AVClass *avfilter_get_class(void)
>  {
>  return _class;
>  }
> +
> +int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link,
> + int default_pool_size)
> +{
> +AVHWFramesContext *frames;
> +
> +// Must already be set by caller.
> +av_assert0(link->hw_frames_ctx);
> +
> +frames = (AVHWFramesContext*)link->hw_frames_ctx->data;
> +
> +if (frames->initial_pool_size == 0) {
> +// Dynamic allocation is necessarily supported.
> +} else if (avctx->extra_hw_frames >= 0) {
> +frames->initial_pool_size += avctx->extra_hw_frames;
> +} else {
> +frames->initial_pool_size = default_pool_size;
> +}
> +
> +return 0;
> +}
> diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
> index 6df69dbbb..c8f861076 100644
> --- a/libavfilter/avfilter.h
> +++ b/libavfilter/avfilter.h
> @@ -311,6 +311,19 @@ struct AVFilterContext {
>   * hardware context information.
>   */
>  AVBufferRef *hw_device_ctx;
> +
> +/**
> + * Sets the number of extra hardware frames which the filter will
> + * allocate on its output links for use in following filters or by
> + * the caller.
> + *
> + * Some hardware filters require all frames that they will use for
> + * output to be defined in advance before filtering starts.  For such
> + * filters, any hardware frame pools used for output must therefore be
> + * of fixed size.  The extra frames set here are on top of any number
> + * that the filter needs internally in order to operate normally.
> + */
> +int extra_hw_frames;
>  };
>  
>  /**
> diff --git a/libavfilter/internal.h b/libavfilter/internal.h
> index a377f9b2b..d17f917c6 100644
> --- a/libavfilter/internal.h
> +++ b/libavfilter/internal.h
> @@ -226,4 +226,20 @@ void ff_filter_graph_remove_filter(AVFilterGraph *graph, 
> AVFilterContext *filter
>   */
>  #define FF_FILTER_FLAG_HWFRAME_AWARE (1 << 0)
>  
> +/**
> + * Perform any additional setup required for hardware frames.
> + *
> + * link->hw_frames_ctx must be set before calling this function.
> + * Inside link->hw_frames_ctx, the fields format, sw_format, width and
> + * height must be set.  If dynamically allocated pools are not supported,
> + * then initial_pool_size must also be set, to the minimum hardware frame
> + * pool size necessary for decode (taking into account reference frames
> + * and delay as appropriate).  If default_pool_size is nonzero, then it
> + * will be used as the pool size if no other modification takes place
> + * (this can be used to preserve compatibility).
> + */
> +int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link,
> + int default_pool_size);
> +
> +
>  #endif /* AVFILTER_INTERNAL_H */
> 
___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

[libav-devel] [PATCH 7/8] hwcontext: Perform usual uninitialisation on derived frames contexts

2018-01-26 Thread Mark Thompson
---
 libavutil/hwcontext.c | 17 +++--
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index 157b73872..3ac17572b 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -205,19 +205,16 @@ static void hwframe_ctx_free(void *opaque, uint8_t *data)
 {
 AVHWFramesContext *ctx = (AVHWFramesContext*)data;
 
-if (ctx->internal->source_frames) {
-av_buffer_unref(>internal->source_frames);
+if (ctx->internal->pool_internal)
+av_buffer_pool_uninit(>internal->pool_internal);
 
-} else {
-if (ctx->internal->pool_internal)
-av_buffer_pool_uninit(>internal->pool_internal);
+if (ctx->internal->hw_type->frames_uninit)
+ctx->internal->hw_type->frames_uninit(ctx);
 
-if (ctx->internal->hw_type->frames_uninit)
-ctx->internal->hw_type->frames_uninit(ctx);
+if (ctx->free)
+ctx->free(ctx);
 
-if (ctx->free)
-ctx->free(ctx);
-}
+av_buffer_unref(>internal->source_frames);
 
 av_buffer_unref(>device_ref);
 
-- 
2.11.0

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

[libav-devel] [PATCH 4/8] vf_hwupload/hwmap: Support setting a fixed pool size

2018-01-26 Thread Mark Thompson
These filters do not directly know whether the API they are using will
support dynamic frame pools, so this is somewhat tricky.  If the user
set extra_hw_frames, we assume that they are aware of the problem and
set a fixed size based on that.  If not, most cases use dynamic sizing
just like they did previously.  The hardware-reverse-mapping case for
hwmap previously had a large fixed size (64) here, primarily as a hack
for QSV use - this is removed and extra_hw_frames will need to be set
for QSV to work since it requires fixed-size pools (as the other cases
do, and which didn't work before).
---
 libavfilter/vf_hwmap.c| 7 ++-
 libavfilter/vf_hwupload.c | 3 +++
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/libavfilter/vf_hwmap.c b/libavfilter/vf_hwmap.c
index b28cb2145..d5ad2768f 100644
--- a/libavfilter/vf_hwmap.c
+++ b/libavfilter/vf_hwmap.c
@@ -138,7 +138,9 @@ static int hwmap_config_output(AVFilterLink *outlink)
 frames->sw_format = hwfc->sw_format;
 frames->width = hwfc->width;
 frames->height= hwfc->height;
-frames->initial_pool_size = 64;
+
+if (avctx->extra_hw_frames >= 0)
+frames->initial_pool_size = 2 + avctx->extra_hw_frames;
 
 err = av_hwframe_ctx_init(ctx->hwframes_ref);
 if (err < 0) {
@@ -218,6 +220,9 @@ static int hwmap_config_output(AVFilterLink *outlink)
 hwfc->width = inlink->w;
 hwfc->height= inlink->h;
 
+if (avctx->extra_hw_frames >= 0)
+hwfc->initial_pool_size = 2 + avctx->extra_hw_frames;
+
 err = av_hwframe_ctx_init(ctx->hwframes_ref);
 if (err < 0) {
 av_log(avctx, AV_LOG_ERROR, "Failed to create frame "
diff --git a/libavfilter/vf_hwupload.c b/libavfilter/vf_hwupload.c
index 8cca9f42e..af4ff9b81 100644
--- a/libavfilter/vf_hwupload.c
+++ b/libavfilter/vf_hwupload.c
@@ -133,6 +133,9 @@ static int hwupload_config_output(AVFilterLink *outlink)
 ctx->hwframes->width = inlink->w;
 ctx->hwframes->height= inlink->h;
 
+if (avctx->extra_hw_frames >= 0)
+ctx->hwframes->initial_pool_size = 2 + avctx->extra_hw_frames;
+
 err = av_hwframe_ctx_init(ctx->hwframes_ref);
 if (err < 0)
 goto fail;
-- 
2.11.0

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

[libav-devel] [PATCH 5/8] hwcontext: Fix documentation for av_hwdevice_ctx_alloc()

2018-01-26 Thread Mark Thompson
From: Jun Zhao <jun.z...@intel.com>

From ffmpeg commit 9365dfcbf665b83b2e60c5ec5e2abf1f0a49e2c3.

Signed-off-by: Jun Zhao <jun.z...@intel.com>
Signed-off-by: Mark Thompson <s...@jkqxz.net>
---
 libavutil/hwcontext.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libavutil/hwcontext.h b/libavutil/hwcontext.h
index 203ea510e..ba293d72e 100644
--- a/libavutil/hwcontext.h
+++ b/libavutil/hwcontext.h
@@ -252,8 +252,9 @@ const char *av_hwdevice_get_type_name(enum AVHWDeviceType 
type);
 enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev);
 
 /**
- * Allocate an AVHWDeviceContext for a given pixel format.
+ * Allocate an AVHWDeviceContext for a given hardware type.
  *
+ * @param type the type of the hardware device to allocate.
  * @return a reference to the newly created AVHWDeviceContext on success or 
NULL
  * on failure.
  */
-- 
2.11.0

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

[libav-devel] [PATCH 3/8] vf_scale_qsv: Support modifying hardware frame pool sizes

2018-01-26 Thread Mark Thompson
The deinterlacer does not change, because it does not allocate any new
frames (for output it uses the same pool as the input).
---
 libavfilter/vf_scale_qsv.c | 26 +++---
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/libavfilter/vf_scale_qsv.c b/libavfilter/vf_scale_qsv.c
index 8ef77835d..c568e9625 100644
--- a/libavfilter/vf_scale_qsv.c
+++ b/libavfilter/vf_scale_qsv.c
@@ -71,7 +71,6 @@ enum var_name {
 typedef struct QSVScaleContext {
 const AVClass *class;
 
-AVBufferRef *out_frames_ref;
 /* a clone of the main session, used internally for scaling */
 mfxSession   session;
 
@@ -134,7 +133,6 @@ static void qsvscale_uninit(AVFilterContext *ctx)
 MFXClose(s->session);
 s->session = NULL;
 }
-av_buffer_unref(>out_frames_ref);
 
 av_freep(>mem_ids_in);
 av_freep(>mem_ids_out);
@@ -163,6 +161,7 @@ static int init_out_pool(AVFilterContext *ctx,
  int out_width, int out_height)
 {
 QSVScaleContext *s = ctx->priv;
+AVFilterLink *outlink = ctx->outputs[0];
 
 AVHWFramesContext *in_frames_ctx;
 AVHWFramesContext *out_frames_ctx;
@@ -183,21 +182,25 @@ static int init_out_pool(AVFilterContext *ctx,
 in_format = in_frames_ctx->sw_format;
 out_format= (s->format == AV_PIX_FMT_NONE) ? in_format : s->format;
 
-s->out_frames_ref = av_hwframe_ctx_alloc(in_frames_ctx->device_ref);
-if (!s->out_frames_ref)
+outlink->hw_frames_ctx = av_hwframe_ctx_alloc(in_frames_ctx->device_ref);
+if (!outlink->hw_frames_ctx)
 return AVERROR(ENOMEM);
-out_frames_ctx   = (AVHWFramesContext*)s->out_frames_ref->data;
+out_frames_ctx   = (AVHWFramesContext*)outlink->hw_frames_ctx->data;
 out_frames_hwctx = out_frames_ctx->hwctx;
 
 out_frames_ctx->format= AV_PIX_FMT_QSV;
 out_frames_ctx->width = FFALIGN(out_width,  32);
 out_frames_ctx->height= FFALIGN(out_height, 32);
 out_frames_ctx->sw_format = out_format;
-out_frames_ctx->initial_pool_size = 32;
+out_frames_ctx->initial_pool_size = 4;
 
 out_frames_hwctx->frame_type = in_frames_hwctx->frame_type;
 
-ret = av_hwframe_ctx_init(s->out_frames_ref);
+ret = ff_filter_init_hw_frames(ctx, outlink, 32);
+if (ret < 0)
+return ret;
+
+ret = av_hwframe_ctx_init(outlink->hw_frames_ctx);
 if (ret < 0)
 return ret;
 
@@ -264,7 +267,7 @@ static int init_out_session(AVFilterContext *ctx)
 
 QSVScaleContext   *s = ctx->priv;
 AVHWFramesContext *in_frames_ctx = 
(AVHWFramesContext*)ctx->inputs[0]->hw_frames_ctx->data;
-AVHWFramesContext*out_frames_ctx = 
(AVHWFramesContext*)s->out_frames_ref->data;
+AVHWFramesContext*out_frames_ctx = 
(AVHWFramesContext*)ctx->outputs[0]->hw_frames_ctx->data;
 AVQSVFramesContext  *in_frames_hwctx = in_frames_ctx->hwctx;
 AVQSVFramesContext *out_frames_hwctx = out_frames_ctx->hwctx;
 AVQSVDeviceContext *device_hwctx = in_frames_ctx->device_ctx->hwctx;
@@ -405,8 +408,6 @@ static int init_out_session(AVFilterContext *ctx)
 static int init_scale_session(AVFilterContext *ctx, int in_width, int 
in_height,
   int out_width, int out_height)
 {
-QSVScaleContext *s = ctx->priv;
-
 int ret;
 
 qsvscale_uninit(ctx);
@@ -419,11 +420,6 @@ static int init_scale_session(AVFilterContext *ctx, int 
in_width, int in_height,
 if (ret < 0)
 return ret;
 
-av_buffer_unref(>outputs[0]->hw_frames_ctx);
-ctx->outputs[0]->hw_frames_ctx = av_buffer_ref(s->out_frames_ref);
-if (!ctx->outputs[0]->hw_frames_ctx)
-return AVERROR(ENOMEM);
-
 return 0;
 }
 
-- 
2.11.0

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

[libav-devel] [PATCH 8/8] hwcontext: Fix memory leak on derived frame allocation failure

2018-01-26 Thread Mark Thompson
---
 libavutil/hwcontext.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index 3ac17572b..34fb720a7 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -467,8 +467,10 @@ int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, 
AVFrame *frame, int flags)
 
 ret = av_hwframe_get_buffer(ctx->internal->source_frames,
 src_frame, 0);
-if (ret < 0)
+if (ret < 0) {
+av_frame_free(_frame);
 return ret;
+}
 
 ret = av_hwframe_map(frame, src_frame,
  ctx->internal->source_allocation_map_flags);
-- 
2.11.0

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

[libav-devel] [PATCH 1/8] lavfi: Add support for modifying hardware frame pool sizes

2018-01-26 Thread Mark Thompson
AVFilterContext.extra_hw_frames functions identically to the field of
the same name in AVCodecContext.
---
 doc/APIchanges |  3 +++
 libavfilter/avfilter.c | 23 +++
 libavfilter/avfilter.h | 13 +
 libavfilter/internal.h | 16 
 4 files changed, 55 insertions(+)

diff --git a/doc/APIchanges b/doc/APIchanges
index 0bde3a052..645ac231a 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,9 @@ libavutil: 2017-03-23
 
 API changes, most recent first:
 
+2018-xx-xx - xxx - lavfi 7.x+1.0 - avfilter.h
+  Add AVFilterContext.extra_hw_frames.
+
 2017-xx-xx - xxx - lavc 58.8.0 - avcodec.h
   Add const to AVCodecContext.hwaccel.
 
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 83c1a7c20..2c4a385ea 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -368,6 +368,8 @@ static const AVOption avfilter_options[] = {
 { "thread_type", "Allowed thread types", OFFSET(thread_type), 
AV_OPT_TYPE_FLAGS,
 { .i64 = AVFILTER_THREAD_SLICE }, 0, INT_MAX, FLAGS, "thread_type" },
 { "slice", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AVFILTER_THREAD_SLICE 
}, .unit = "thread_type" },
+{ "extra_hw_frames", "Number of extra hardware frames to allocate for the 
user",
+OFFSET(extra_hw_frames), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, 
FLAGS },
 { NULL },
 };
 
@@ -707,3 +709,24 @@ const AVClass *avfilter_get_class(void)
 {
 return _class;
 }
+
+int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link,
+ int default_pool_size)
+{
+AVHWFramesContext *frames;
+
+// Must already be set by caller.
+av_assert0(link->hw_frames_ctx);
+
+frames = (AVHWFramesContext*)link->hw_frames_ctx->data;
+
+if (frames->initial_pool_size == 0) {
+// Dynamic allocation is necessarily supported.
+} else if (avctx->extra_hw_frames >= 0) {
+frames->initial_pool_size += avctx->extra_hw_frames;
+} else {
+frames->initial_pool_size = default_pool_size;
+}
+
+return 0;
+}
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 6df69dbbb..c8f861076 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -311,6 +311,19 @@ struct AVFilterContext {
  * hardware context information.
  */
 AVBufferRef *hw_device_ctx;
+
+/**
+ * Sets the number of extra hardware frames which the filter will
+ * allocate on its output links for use in following filters or by
+ * the caller.
+ *
+ * Some hardware filters require all frames that they will use for
+ * output to be defined in advance before filtering starts.  For such
+ * filters, any hardware frame pools used for output must therefore be
+ * of fixed size.  The extra frames set here are on top of any number
+ * that the filter needs internally in order to operate normally.
+ */
+int extra_hw_frames;
 };
 
 /**
diff --git a/libavfilter/internal.h b/libavfilter/internal.h
index a377f9b2b..d17f917c6 100644
--- a/libavfilter/internal.h
+++ b/libavfilter/internal.h
@@ -226,4 +226,20 @@ void ff_filter_graph_remove_filter(AVFilterGraph *graph, 
AVFilterContext *filter
  */
 #define FF_FILTER_FLAG_HWFRAME_AWARE (1 << 0)
 
+/**
+ * Perform any additional setup required for hardware frames.
+ *
+ * link->hw_frames_ctx must be set before calling this function.
+ * Inside link->hw_frames_ctx, the fields format, sw_format, width and
+ * height must be set.  If dynamically allocated pools are not supported,
+ * then initial_pool_size must also be set, to the minimum hardware frame
+ * pool size necessary for decode (taking into account reference frames
+ * and delay as appropriate).  If default_pool_size is nonzero, then it
+ * will be used as the pool size if no other modification takes place
+ * (this can be used to preserve compatibility).
+ */
+int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link,
+ int default_pool_size);
+
+
 #endif /* AVFILTER_INTERNAL_H */
-- 
2.11.0

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

[libav-devel] [PATCH 6/8] hwcontext: Perform usual initialisation on derived device contexts

2018-01-26 Thread Mark Thompson
The initialisation should be common.  For libmfx, it was previously
happening in the derivation function and this moves it out.
---
 libavutil/hwcontext.c |  4 
 libavutil/hwcontext_qsv.c | 10 --
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/libavutil/hwcontext.c b/libavutil/hwcontext.c
index 6dc95bba1..157b73872 100644
--- a/libavutil/hwcontext.c
+++ b/libavutil/hwcontext.c
@@ -643,6 +643,10 @@ int av_hwdevice_ctx_create_derived(AVBufferRef 
**dst_ref_ptr,
 goto fail;
 
 done:
+ret = av_hwdevice_ctx_init(dst_ref);
+if (ret < 0)
+goto fail;
+
 *dst_ref_ptr = dst_ref;
 return 0;
 
diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c
index 9270b2258..a47170b66 100644
--- a/libavutil/hwcontext_qsv.c
+++ b/libavutil/hwcontext_qsv.c
@@ -1058,16 +1058,6 @@ static int 
qsv_device_derive_from_child(AVHWDeviceContext *ctx,
 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:
-- 
2.11.0

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

[libav-devel] [PATCH 2/8] vf_*_vaapi: Support modifying hardware frame pool sizes

2018-01-26 Thread Mark Thompson
Defaults to 10 frames to preserve compatibility, but can allocate
fewer if extra_hw_frames is set explicitly.
---
 libavfilter/vf_deinterlace_vaapi.c | 39 +++
 libavfilter/vf_scale_vaapi.c   | 42 +++---
 2 files changed, 33 insertions(+), 48 deletions(-)

diff --git a/libavfilter/vf_deinterlace_vaapi.c 
b/libavfilter/vf_deinterlace_vaapi.c
index 95a0f4041..082df8914 100644
--- a/libavfilter/vf_deinterlace_vaapi.c
+++ b/libavfilter/vf_deinterlace_vaapi.c
@@ -53,8 +53,6 @@ typedef struct DeintVAAPIContext {
 AVBufferRef   *input_frames_ref;
 AVHWFramesContext *input_frames;
 
-AVBufferRef   *output_frames_ref;
-AVHWFramesContext *output_frames;
 intoutput_height;
 intoutput_width;
 
@@ -236,6 +234,7 @@ static int deint_vaapi_config_output(AVFilterLink *outlink)
 DeintVAAPIContext*ctx = avctx->priv;
 AVVAAPIHWConfig *hwconfig = NULL;
 AVHWFramesConstraints *constraints = NULL;
+AVHWFramesContext *output_frames;
 AVVAAPIFramesContext *va_frames;
 VAStatus vas;
 int err;
@@ -287,34 +286,35 @@ static int deint_vaapi_config_output(AVFilterLink 
*outlink)
 goto fail;
 }
 
-ctx->output_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref);
-if (!ctx->output_frames_ref) {
+outlink->hw_frames_ctx = av_hwframe_ctx_alloc(ctx->device_ref);
+if (!outlink->hw_frames_ctx) {
 av_log(avctx, AV_LOG_ERROR, "Failed to create HW frame context "
"for output.\n");
 err = AVERROR(ENOMEM);
 goto fail;
 }
 
-ctx->output_frames = (AVHWFramesContext*)ctx->output_frames_ref->data;
+output_frames = (AVHWFramesContext*)outlink->hw_frames_ctx->data;
 
-ctx->output_frames->format= AV_PIX_FMT_VAAPI;
-ctx->output_frames->sw_format = ctx->input_frames->sw_format;
-ctx->output_frames->width = ctx->output_width;
-ctx->output_frames->height= ctx->output_height;
+output_frames->format= AV_PIX_FMT_VAAPI;
+output_frames->sw_format = ctx->input_frames->sw_format;
+output_frames->width = ctx->output_width;
+output_frames->height= ctx->output_height;
 
-// The number of output frames we need is determined by what follows
-// the filter.  If it's an encoder with complex frame reference
-// structures then this could be very high.
-ctx->output_frames->initial_pool_size = 10;
+output_frames->initial_pool_size = 4;
+
+err = ff_filter_init_hw_frames(avctx, outlink, 10);
+if (err < 0)
+goto fail;
 
-err = av_hwframe_ctx_init(ctx->output_frames_ref);
+err = av_hwframe_ctx_init(outlink->hw_frames_ctx);
 if (err < 0) {
 av_log(avctx, AV_LOG_ERROR, "Failed to initialise VAAPI frame "
"context for output: %d\n", err);
 goto fail;
 }
 
-va_frames = ctx->output_frames->hwctx;
+va_frames = output_frames->hwctx;
 
 av_assert0(ctx->va_context == VA_INVALID_ID);
 vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
@@ -340,18 +340,12 @@ static int deint_vaapi_config_output(AVFilterLink 
*outlink)
 outlink->frame_rate = av_mul_q(inlink->frame_rate,
(AVRational) { ctx->field_rate, 1 });
 
-outlink->hw_frames_ctx = av_buffer_ref(ctx->output_frames_ref);
-if (!outlink->hw_frames_ctx) {
-err = AVERROR(ENOMEM);
-goto fail;
-}
-
 av_freep();
 av_hwframe_constraints_free();
 return 0;
 
 fail:
-av_buffer_unref(>output_frames_ref);
+av_buffer_unref(>hw_frames_ctx);
 av_freep();
 av_hwframe_constraints_free();
 return err;
@@ -601,7 +595,6 @@ static av_cold void deint_vaapi_uninit(AVFilterContext 
*avctx)
 deint_vaapi_pipeline_uninit(avctx);
 
 av_buffer_unref(>input_frames_ref);
-av_buffer_unref(>output_frames_ref);
 av_buffer_unref(>device_ref);
 }
 
diff --git a/libavfilter/vf_scale_vaapi.c b/libavfilter/vf_scale_vaapi.c
index 4c8f2cf4e..0ab5518b5 100644
--- a/libavfilter/vf_scale_vaapi.c
+++ b/libavfilter/vf_scale_vaapi.c
@@ -22,6 +22,7 @@
 #include 
 
 #include "libavutil/avassert.h"
+#include "libavutil/common.h"
 #include "libavutil/hwcontext.h"
 #include "libavutil/hwcontext_vaapi.h"
 #include "libavutil/mem.h"
@@ -46,9 +47,6 @@ typedef struct ScaleVAAPIContext {
 AVBufferRef   *input_frames_ref;
 AVHWFramesContext *input_frames;
 
-AVBufferRef   *output_frames_ref;
-AVHWFramesContext *output_frames;
-
 char *output_format_string;
 enum AVPixelFormat output_format;
 int output_width;
@@ -83,7 +81,6 @@ static int scale_vaapi_pipeline_uninit(ScaleVAAPIContext *ctx)
 ctx->va_config = VA_INVALID_ID;
 }
 
-av_buffer_unref(>output_frames_ref);
 av_buffer_unref(>device_ref);
 ctx->hwctx = 0;
 
@@ -115,6 +112,7 @@ static int scale_vaapi_config_output(AVFilterLink *outlink)
 ScaleVAAPIContext *ctx = 

Re: [libav-devel] [PATCH] hwcontext_qsv: Fix qsv hwupload failure issue

2018-01-26 Thread Mark Thompson
On 26/01/18 09:15, wm4 wrote:
> On Fri, 26 Jan 2018 05:56:46 +
> "Li, Zhong"  wrote:
> 
>>> From: libav-devel [mailto:libav-devel-boun...@libav.org] On Behalf Of
>>> Ruiling Song
>>> Sent: Friday, January 26, 2018 9:17 AM
>>> To: libav-devel@libav.org
>>> Subject: [libav-devel] [PATCH] hwcontext_qsv: Fix qsv hwupload failure issue
>>>
>>> From: "Ruiling, Song" 
>>>
>>> 1.) the initial_pool_size need to be set instead of zero.
>>> 2.) the PicStruct is required by MediaSDK, so give a default value.
>>>
>>> A simple command to reproduce the issue:
>>> avconv -i INPUT -init_hw_device qsv=foo -filter_hw_device foo -vf
>>> format=nv12,hwupload -c:v h264_qsv ... OUTPUT
>>>
>>> Signed-off-by: Ruiling Song 
>>> ---
>>>  libavutil/hwcontext_qsv.c | 4 ++--
>>>  1 file changed, 2 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index
>>> 9270b22..14f26c6 100644
>>> --- a/libavutil/hwcontext_qsv.c
>>> +++ b/libavutil/hwcontext_qsv.c
>>> @@ -313,6 +313,7 @@ static int qsv_init_surface(AVHWFramesContext *ctx,
>>> mfxFrameSurface1 *surf)
>>>  surf->Info.CropH  = ctx->height;
>>>  surf->Info.FrameRateExtN  = 25;
>>>  surf->Info.FrameRateExtD  = 1;
>>> +surf->Info.PicStruct  = MFX_PICSTRUCT_PROGRESSIVE;
>>>
>>>  return 0;
>>>  }
>>> @@ -325,8 +326,7 @@ static int qsv_init_pool(AVHWFramesContext *ctx,
>>> uint32_t fourcc)
>>>  int i, ret = 0;
>>>
>>>  if (ctx->initial_pool_size <= 0) {
>>> -av_log(ctx, AV_LOG_ERROR, "QSV requires a fixed frame pool
>>> size\n");  
>>
>> Should keep this log message as a warning be better? 
>>
>>> -return AVERROR(EINVAL);
>>> +ctx->initial_pool_size = 64;
> 
> That doesn't really feel appropriate. If a fixed size pool is required,
> the user should simply be forced to specify a size. Making it use a
> random value doesn't make too much sense to me, and the required size
> is going to depend on the caller's use cases. In addition 64 by default
> sounds like a huge waste of memory.

Agree.

Maybe it would be a good idea to resurrect the set at 
, in 
particular there is 
 for 
exactly this case.  I don't know if we want to modify how this works to be more 
like what was used in libavcodec, though.

Thoughts?  I can send the set again if that would be helpful.

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

Re: [libav-devel] qsv: How about replace software parsers with MFXVideoDECODE_DecodeHeader

2018-01-23 Thread Mark Thompson
On 23/01/18 05:05, Li, Zhong wrote:
>> From: libav-devel [mailto:libav-devel-boun...@libav.org] On Behalf Of Mark
>> Thompson
>> Sent: Monday, January 22, 2018 9:19 PM
>> To: libav-devel@libav.org
>> Subject: Re: [libav-devel] qsv: How about replace software parsers with
>> MFXVideoDECODE_DecodeHeader
>>
>> ...
>>
>> PS:  Feel free to ignore anything I say about qsvdec - I regard qsvdec as
>> deprecated, because nowadays I find that using the platform API hwaccels
>> (DXVA2/VAAPI) and mapping back if necessary is just more flexible and better
>> supported.  (Though it would be nice if libmfx encode supported D3D11
>> array textures too...)
> 
> Thanks very much for your detail reply and I'm appreciated for your comments. 
> IIUC, surface sharing between libmfx and vaapi hasn't be supported, and I'm 
> not sure it can be done since the release version of MSDK is using a private 
> libva (instead of upstream libva.)

This interop already works and has done so for a while with the proprietary 
drivers.

I'm not next to a suitable machine so this command may be subtly wrong, but on 
Linux with proprietary Media SDK you can do things like:

avconv -hwaccel vaapi -hwaccel_output_format vaapi -i input.mp4 -vf 
'scale_vaapi=1280:720,hwmap=derive_device=qsv,format=qsv' -c:v h264_qsv -b:v 5M 
output.mp4

On Windows, there is similarly:

avconv -hwaccel dxva2 -hwaccel_output_format dxva2_vld -i input.mp4 -vf 
'hwmap=derive_device=qsv,format=qsv' -c:v h264_qsv -b:v 5M output.mp4

(There aren't any generic filters for D3D9, though.)

OpenCL interop also works on both platforms for intermediate processing.

> The good news is opensource MSDK on github has been updated with upstream 
> libva (and iHD driver has removed the dependency for linux kernel patches), 
> but still needs time to make sure it is stable. 

Yeah, I've looked at it and done some investigation (and sent some patches), 
but indeed it does need a bit more time to clean up all of the setup to work as 
well as the i965 driver.  The fact that it doesn't work on any 
current-generation machines (Kaby Lake / Coffee Lake) is also something of a 
pain.

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

Re: [libav-devel] qsv: How about replace software parsers with MFXVideoDECODE_DecodeHeader

2018-01-22 Thread Mark Thompson
On 22/01/18 11:20, Li, Zhong wrote:
>   MSDK provides an API (MFXVideoDECODE_DecodeHeader) to parse video 
> parameters. Currently it hasn't been used.
> Instead, software parsers are used. It works well for h264 decoder, and 
> basically works well for hevc decoder (some issues found by Mayxm due to 
> width/height are unaligned, I also found some hevc clips without setting 
> profile can be decoded by software but qsv failed) .
> More issues found on other decoders such as VP8. The decoding conformance 
> pass rate is low and looks like it is due to some missing/incompatible header 
> information is passed to qsv decoder (though Mark provides a patch 182cf17 
> but still something is missing).
>   Similar issues happens on MJPEG decoding which I am going to add.

Have you looked into what is missing for VP8?  There shouldn't be much magic 
there, so I doubt that particular case is difficult to fix.

I imagine MJPEG will be nastier, though, because there is a lot more variation 
in layout.

>   Maybe we can continue to work on software parsers for qsv, but I believe 
> replace software parser with MFXVideoDECODE_DecodeHeader is a better choice:
> 
> 1.  It can remove the dependence on various software parsers, and just 
> need a unified interface for all codes.
> 
> 2.  It will be very easy to add new decoder such as MJPEG decoding 
> support without any software parser patches.
> 
> 3.  MFXVideoDECODE_DecodeHeader is used by MSDK sample decoder (i.e: 
> sample_decode), so it is reliable for MSDK decoder. (As my test, it can 
> effectively improve decoding conformance pass rate, especially for vp8 
> decoding.)
> 
> 4.  CUVID decoder is using CUVID parser instead of software parser, maybe 
> qsv can align with it.

The CUVID decoder only exists in ffmpeg and is considered deprecated in favour 
of the hwaccel (which is the only thing in libav).

>Negative effect:
> 
> 1.  May cause some regression since it will take effect to all codecs.
> 
> 2.  Others?

I believe a problem with this method is that you don't have any libmfx session 
at the point where you do the initial parsing (since you only get it after the 
get_format() callback, which needs information from that parsing).  How would 
you intend to get the session to use for this purpose?

- Mark


PS:  Feel free to ignore anything I say about qsvdec - I regard qsvdec as 
deprecated, because nowadays I find that using the platform API hwaccels 
(DXVA2/VAAPI) and mapping back if necessary is just more flexible and better 
supported.  (Though it would be nice if libmfx encode supported D3D11 array 
textures too...)
___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Re: [libav-devel] [PATCH 2/2] vaapi_h265: Mark unused entries in RefPicList[01] as explicitly invalid

2017-12-20 Thread Mark Thompson
On 18/12/17 01:59, Jun Zhao wrote:
> On 2017/12/18 4:05, Mark Thompson wrote:
>> The iHD driver looks at entries beyond num_ref_idx_l[01]_active_minus1
>> for unknown reasons.
>> ---
>> This still isn't enough to actually work for encoding H.265 with the iHD 
>> driver on Skylake.  It can generate output with this rather than crashing, 
>> but the output is still wrong (though it does resemble the input somewhat).
>>
>> It also seems to like inserting emulation prevention bytes everywhere in 
>> slice headers after the first, so it breaks totally if AUDs are present.
> I think the root cause for HECV enc can't work in SKL is iHD have a
> limitation for
> max_transform_hierarchy_depth_inter/max_transform_hierarchy_depth_intra,
> you can apply the patch in
> https://github.com/mypopydev/FFmpeg/commit/fb35b6167d16d1acb81d0c82e19293c7cf97a574,
> then re-try h265 ENC with iHD in SKL. Tks.

I'm not sure that can be a hardware limitation, since it does work with the 
i965 driver on the same hardware.

If it really is different then I think something will need to be added to VAAPI 
itself to query these parameters (certainly all the transform size stuff, 
possibly more).  Currently we use values suitable for i965 because it was the 
only working driver when the code was written, but once there is a second 
driver we need some way to choose between them.

- Mark

>>
>>  libavcodec/vaapi_encode_h265.c | 21 +++--
>>  1 file changed, 19 insertions(+), 2 deletions(-)
>>
>> diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
>> index a9853a3aa..813d4f944 100644
>> --- a/libavcodec/vaapi_encode_h265.c
>> +++ b/libavcodec/vaapi_encode_h265.c
>> @@ -767,8 +767,6 @@ static int 
>> vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
>>  
>>  .num_ref_idx_l0_active_minus1 = sh->num_ref_idx_l0_active_minus1,
>>  .num_ref_idx_l1_active_minus1 = sh->num_ref_idx_l1_active_minus1,
>> -.ref_pic_list0[0] = vpic->reference_frames[0],
>> -.ref_pic_list1[0] = vpic->reference_frames[1],
>>  
>>  .luma_log2_weight_denom = sh->luma_log2_weight_denom,
>>  .delta_chroma_log2_weight_denom = 
>> sh->delta_chroma_log2_weight_denom,
>> @@ -802,6 +800,25 @@ static int 
>> vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
>>  },
>>  };
>>  
>> +for (i = 0; i < FF_ARRAY_ELEMS(vslice->ref_pic_list0); i++) {
>> +vslice->ref_pic_list0[i].picture_id = VA_INVALID_ID;
>> +vslice->ref_pic_list0[i].flags  = VA_PICTURE_HEVC_INVALID;
>> +vslice->ref_pic_list1[i].picture_id = VA_INVALID_ID;
>> +vslice->ref_pic_list1[i].flags  = VA_PICTURE_HEVC_INVALID;
>> +}
>> +
>> +av_assert0(pic->nb_refs <= 2);
>> +if (pic->nb_refs >= 1) {
>> +// Backward reference for P- or B-frame.
>> +av_assert0(pic->type == PICTURE_TYPE_P ||
>> +   pic->type == PICTURE_TYPE_B);
>> +vslice->ref_pic_list0[0] = vpic->reference_frames[0];
>> +}
>> +if (pic->nb_refs >= 2) {
>> +// Forward reference for B-frame.
>> +av_assert0(pic->type == PICTURE_TYPE_B);
>> +vslice->ref_pic_list1[0] = vpic->reference_frames[1];
>> +}
>>  
>>  return 0;
>>  }
> 

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

[libav-devel] [PATCH 2/2] vaapi_h265: Mark unused entries in RefPicList[01] as explicitly invalid

2017-12-17 Thread Mark Thompson
The iHD driver looks at entries beyond num_ref_idx_l[01]_active_minus1
for unknown reasons.
---
This still isn't enough to actually work for encoding H.265 with the iHD driver 
on Skylake.  It can generate output with this rather than crashing, but the 
output is still wrong (though it does resemble the input somewhat).

It also seems to like inserting emulation prevention bytes everywhere in slice 
headers after the first, so it breaks totally if AUDs are present.


 libavcodec/vaapi_encode_h265.c | 21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
index a9853a3aa..813d4f944 100644
--- a/libavcodec/vaapi_encode_h265.c
+++ b/libavcodec/vaapi_encode_h265.c
@@ -767,8 +767,6 @@ static int 
vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
 
 .num_ref_idx_l0_active_minus1 = sh->num_ref_idx_l0_active_minus1,
 .num_ref_idx_l1_active_minus1 = sh->num_ref_idx_l1_active_minus1,
-.ref_pic_list0[0] = vpic->reference_frames[0],
-.ref_pic_list1[0] = vpic->reference_frames[1],
 
 .luma_log2_weight_denom = sh->luma_log2_weight_denom,
 .delta_chroma_log2_weight_denom = sh->delta_chroma_log2_weight_denom,
@@ -802,6 +800,25 @@ static int 
vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
 },
 };
 
+for (i = 0; i < FF_ARRAY_ELEMS(vslice->ref_pic_list0); i++) {
+vslice->ref_pic_list0[i].picture_id = VA_INVALID_ID;
+vslice->ref_pic_list0[i].flags  = VA_PICTURE_HEVC_INVALID;
+vslice->ref_pic_list1[i].picture_id = VA_INVALID_ID;
+vslice->ref_pic_list1[i].flags  = VA_PICTURE_HEVC_INVALID;
+}
+
+av_assert0(pic->nb_refs <= 2);
+if (pic->nb_refs >= 1) {
+// Backward reference for P- or B-frame.
+av_assert0(pic->type == PICTURE_TYPE_P ||
+   pic->type == PICTURE_TYPE_B);
+vslice->ref_pic_list0[0] = vpic->reference_frames[0];
+}
+if (pic->nb_refs >= 2) {
+// Forward reference for B-frame.
+av_assert0(pic->type == PICTURE_TYPE_B);
+vslice->ref_pic_list1[0] = vpic->reference_frames[1];
+}
 
 return 0;
 }
-- 
2.11.0
___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

[libav-devel] [PATCH 1/2] vaapi_encode: Destroy output buffer pool before VA context

2017-12-17 Thread Mark Thompson
The buffers are created associated with the context, so they should be
destroyed before the context is.  This is enforced by the iHD driver.
---
(Causes a crash on close.)


 libavcodec/vaapi_encode.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
index 47795ba73..fdc3d2a95 100644
--- a/libavcodec/vaapi_encode.c
+++ b/libavcodec/vaapi_encode.c
@@ -1536,6 +1536,8 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx)
 vaapi_encode_free(avctx, pic);
 }
 
+av_buffer_pool_uninit(>output_buffer_pool);
+
 if (ctx->va_context != VA_INVALID_ID) {
 vaDestroyContext(ctx->hwctx->display, ctx->va_context);
 ctx->va_context = VA_INVALID_ID;
@@ -1546,8 +1548,6 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx)
 ctx->va_config = VA_INVALID_ID;
 }
 
-av_buffer_pool_uninit(>output_buffer_pool);
-
 av_freep(>codec_sequence_params);
 av_freep(>codec_picture_params);
 
-- 
2.11.0
___
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

[libav-devel] [PATCH 3/6] cbs: Demote the "decomposition unimplemented" warning

2017-12-10 Thread Mark Thompson
This is harmless and should not be a warning - unknown units are passed
through to the write functions unchanged, and no other code will interact
with them.
---
 libavcodec/cbs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c
index 3baa31a4d..283e2cc59 100644
--- a/libavcodec/cbs.c
+++ b/libavcodec/cbs.c
@@ -121,7 +121,7 @@ static int cbs_read_fragment_content(CodedBitstreamContext 
*ctx,
 
 err = ctx->codec->read_unit(ctx, >units[i]);
 if (err == AVERROR(ENOSYS)) {
-av_log(ctx->log_ctx, AV_LOG_WARNING,
+av_log(ctx->log_ctx, AV_LOG_VERBOSE,
"Decomposition unimplemented for unit %d "
"(type %d).\n", i, frag->units[i].type);
 } else if (err < 0) {
-- 
2.11.0

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

[libav-devel] [PATCH 2/6] hevc: Remove unused hevc_ps_enc.c

2017-12-10 Thread Mark Thompson
Replaced with more complete implementation via coded bitstream infrastructure.
---
 libavcodec/hevc_ps.h |   3 --
 libavcodec/hevc_ps_enc.c | 118 ---
 2 files changed, 121 deletions(-)
 delete mode 100644 libavcodec/hevc_ps_enc.c

diff --git a/libavcodec/hevc_ps.h b/libavcodec/hevc_ps.h
index 6e2b52777..7f88b42e1 100644
--- a/libavcodec/hevc_ps.h
+++ b/libavcodec/hevc_ps.h
@@ -312,7 +312,4 @@ int ff_hevc_decode_nal_pps(GetBitContext *gb, 
AVCodecContext *avctx,
 int ff_hevc_decode_short_term_rps(GetBitContext *gb, AVCodecContext *avctx,
   ShortTermRPS *rps, const HEVCSPS *sps, int 
is_slice_header);
 
-int ff_hevc_encode_nal_vps(HEVCVPS *vps, unsigned int id,
-   uint8_t *buf, int buf_size);
-
 #endif /* AVCODEC_HEVC_PS_H */
diff --git a/libavcodec/hevc_ps_enc.c b/libavcodec/hevc_ps_enc.c
deleted file mode 100644
index 1fb93b302..0
--- a/libavcodec/hevc_ps_enc.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * HEVC Parameter Set encoding
- *
- * This file is part of Libav.
- *
- * Libav is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * Libav is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "golomb_legacy.h"
-#include "hevc_ps.h"
-#include "put_bits.h"
-
-static void write_ptl_layer(PutBitContext *pb, PTLCommon *ptl)
-{
-int i;
-
-put_bits(pb, 2, ptl->profile_space);
-put_bits(pb, 1, ptl->tier_flag);
-put_bits(pb, 5, ptl->profile_idc);
-for (i = 0; i < 32; i++)
-put_bits(pb, 1, ptl->profile_compatibility_flag[i]);
-put_bits(pb, 1, ptl->progressive_source_flag);
-put_bits(pb, 1, ptl->interlaced_source_flag);
-put_bits(pb, 1, ptl->non_packed_constraint_flag);
-put_bits(pb, 1, ptl->frame_only_constraint_flag);
-put_bits32(pb, 0);   // reserved
-put_bits(pb, 12, 0); // reserved
-}
-
-static void write_ptl(PutBitContext *pb, PTL *ptl, int max_num_sub_layers)
-{
-int i;
-
-write_ptl_layer(pb, >general_ptl);
-put_bits(pb, 8, ptl->general_ptl.level_idc);
-
-for (i = 0; i < max_num_sub_layers - 1; i++) {
-put_bits(pb, 1, ptl->sub_layer_profile_present_flag[i]);
-put_bits(pb, 1, ptl->sub_layer_level_present_flag[i]);
-}
-
-if (max_num_sub_layers > 1)
-for (i = max_num_sub_layers - 1; i < 8; i++)
-put_bits(pb, 2, 0); // reserved
-
-for (i = 0; i < max_num_sub_layers - 1; i++) {
-if (ptl->sub_layer_profile_present_flag[i])
-write_ptl_layer(pb, >sub_layer_ptl[i]);
-if (ptl->sub_layer_level_present_flag[i])
-put_bits(pb, 8, ptl->sub_layer_ptl[i].level_idc);
-}
-}
-
-int ff_hevc_encode_nal_vps(HEVCVPS *vps, unsigned int id,
-   uint8_t *buf, int buf_size)
-{
-PutBitContext pb;
-int i;
-
-init_put_bits(, buf, buf_size);
-put_bits(,  4, id);
-put_bits(,  2, 3);   // reserved
-put_bits(,  6, vps->vps_max_layers - 1);
-put_bits(,  3, vps->vps_max_sub_layers - 1);
-put_bits(,  1, vps->vps_temporal_id_nesting_flag);
-put_bits(, 16, 0x);  // reserved
-
-write_ptl(, >ptl, vps->vps_max_sub_layers);
-
-put_bits(, 1, vps->vps_sub_layer_ordering_info_present_flag);
-for (i = vps->vps_sub_layer_ordering_info_present_flag ? 0 : 
vps->vps_max_layers - 1;
- i < vps->vps_max_sub_layers; i++) {
-set_ue_golomb(, vps->vps_max_dec_pic_buffering[i] - 1);
-set_ue_golomb(, vps->vps_num_reorder_pics[i]);
-set_ue_golomb(, vps->vps_max_latency_increase[i] + 1);
-}
-
-put_bits(, 6, vps->vps_max_layer_id);
-set_ue_golomb(, vps->vps_num_layer_sets - 1);
-
-if (vps->vps_num_layer_sets > 1) {
-avpriv_report_missing_feature(NULL, "Writing layer_id_included_flag");
-return AVERROR_PATCHWELCOME;
-}
-
-put_bits(, 1, vps->vps_timing_info_present_flag);
-if (vps->vps_timing_info_present_flag) {
-put_bits32(, vps->vps_num_units_in_tick);
-put_bits32(, vps->vps_time_scale);
-put_bits(, 1, vps->vps_poc_proportional_to_timing_flag);
-if (vps->vps_poc_proportional_to_timing_flag)
-set_ue_golomb(, vps->vps_num_ticks_poc_diff_one - 1);
-
-if (vps->vps_num_hrd_parameters) {
-avpriv_report_missing_feature(NULL, "Writing HRD 

[libav-devel] [PATCH 1/6] qsvenc_hevc: Replace ad-hoc VPS writing with CBS implementation

2017-12-10 Thread Mark Thompson
This copies more information which should be present from the SPS.
It also fixes the value of vps_temporal_id_nesting_flag, which was
previously incorrect for a single-layer stream (the standard states
that it must be 1, and the reference decoder barfs if it isn't).
---
 configure|   2 +-
 libavcodec/Makefile  |   3 +-
 libavcodec/qsvenc_hevc.c | 190 +++
 3 files changed, 111 insertions(+), 84 deletions(-)

diff --git a/configure b/configure
index 7f320fee1..3aa61abb8 100755
--- a/configure
+++ b/configure
@@ -2267,7 +2267,7 @@ h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264"
 h264_vaapi_encoder_select="cbs_h264 vaapi_encode"
 hevc_nvenc_encoder_deps="nvenc"
 hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser hevc_qsv_hwaccel 
qsvdec"
-hevc_qsv_encoder_select="hevcparse qsvenc"
+hevc_qsv_encoder_select="cbs_h265 qsvenc"
 hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC"
 hevc_vaapi_encoder_select="cbs_h265 vaapi_encode"
 mjpeg_qsv_encoder_deps="libmfx"
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index d04902be0..9a1a6fec6 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -284,8 +284,7 @@ OBJS-$(CONFIG_HEVC_DECODER)+= hevcdec.o 
hevc_mvs.o hevc_sei.o \
   hevcdsp.o hevc_filter.o hevc_data.o
 OBJS-$(CONFIG_HEVC_NVENC_ENCODER)  += nvenc_hevc.o
 OBJS-$(CONFIG_HEVC_QSV_DECODER)+= qsvdec_h2645.o
-OBJS-$(CONFIG_HEVC_QSV_ENCODER)+= qsvenc_hevc.o hevc_ps_enc.o   \
-  hevc_data.o
+OBJS-$(CONFIG_HEVC_QSV_ENCODER)+= qsvenc_hevc.o
 OBJS-$(CONFIG_HEVC_VAAPI_ENCODER)  += vaapi_encode_h265.o
 OBJS-$(CONFIG_HNM4_VIDEO_DECODER)  += hnm4video.o
 OBJS-$(CONFIG_HQ_HQA_DECODER)  += hq_hqa.o hq_hqadata.o hq_hqadsp.o \
diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c
index dbb55e2f1..92066dcb7 100644
--- a/libavcodec/qsvenc_hevc.c
+++ b/libavcodec/qsvenc_hevc.c
@@ -28,11 +28,11 @@
 #include "libavutil/opt.h"
 
 #include "avcodec.h"
-#include "bytestream.h"
+#include "cbs.h"
+#include "cbs_h265.h"
 #include "get_bits.h"
 #include "hevc.h"
 #include "hevcdec.h"
-#include "h2645_parse.h"
 #include "internal.h"
 #include "qsv.h"
 #include "qsv_internal.h"
@@ -52,107 +52,135 @@ typedef struct QSVHEVCEncContext {
 
 static int generate_fake_vps(QSVEncContext *q, AVCodecContext *avctx)
 {
-GetByteContext gbc;
-PutByteContext pbc;
-
-GetBitContext gb;
-H2645NAL sps_nal = { NULL };
-HEVCSPS sps = { 0 };
-HEVCVPS vps = { 0 };
-uint8_t vps_buf[128], vps_rbsp_buf[128];
-uint8_t *new_extradata;
-unsigned int sps_id;
-int ret, i, type, vps_size;
+CodedBitstreamContext cbc;
+CodedBitstreamFragment ps;
+const H265RawSPS *sps;
+H265RawVPS vps;
+uint8_t *data = NULL;
+size_t data_size;
+int err, sps_pos, i;
 
 if (!avctx->extradata_size) {
-av_log(avctx, AV_LOG_ERROR, "No extradata returned from libmfx\n");
+av_log(avctx, AV_LOG_ERROR,
+   "No parameter sets returned by libmfx.\n");
 return AVERROR_UNKNOWN;
 }
 
-/* parse the SPS */
-ret = ff_h2645_extract_rbsp(avctx->extradata + 4, avctx->extradata_size - 
4, _nal);
-if (ret < 0) {
-av_log(avctx, AV_LOG_ERROR, "Error unescaping the SPS buffer\n");
-return ret;
-}
+err = ff_cbs_init(, AV_CODEC_ID_HEVC, avctx);
+if (err < 0)
+return err;
 
-ret = init_get_bits8(, sps_nal.data, sps_nal.size);
-if (ret < 0) {
-av_freep(_nal.rbsp_buffer);
-return ret;
+err = ff_cbs_read(, , avctx->extradata, avctx->extradata_size);
+if (err < 0) {
+av_log(avctx, AV_LOG_ERROR,
+   "Error reading parameter sets returned by libmfx.\n");
+ff_cbs_close();
+return err;
 }
 
-get_bits(, 1);
-type = get_bits(, 6);
-if (type != HEVC_NAL_SPS) {
-av_log(avctx, AV_LOG_ERROR, "Unexpected NAL type in the extradata: 
%d\n",
-   type);
-av_freep(_nal.rbsp_buffer);
-return AVERROR_INVALIDDATA;
+sps = NULL;
+for (sps_pos = 0; sps_pos < ps.nb_units; sps_pos++) {
+if (ps.units[sps_pos].type == HEVC_NAL_SPS) {
+sps = ps.units[sps_pos].content;
+break;
+}
 }
-get_bits(, 9);
-
-ret = ff_hevc_parse_sps(, , _id, 0, NULL, avctx);
-av_freep(_nal.rbsp_buffer);
-if (ret < 0) {
-av_log(avctx, AV_LOG_ERROR, "Error parsing the SPS\n");
-return ret;
+if (!sps) {
+av_log(avctx, AV_LOG_ERROR, "No SPS returned by libmfx.\n");
+goto fail;
 }
 
-/* generate the VPS */
-vps.vps_max_layers = 1;
-vps.vps_max_sub_layers = sps.max_sub_layers;
-memcpy(, , sizeof(vps.ptl));
-vps.vps_sub_layer_ordering_info_present_flag = 1;
+vps = (H265RawVPS) {
+.nal_unit_header = {
+

[libav-devel] [PATCH 5/6] cbs_h264: Add hack for pic_timing with no active SPS

2017-12-10 Thread Mark Thompson
If there is exactly one possible SPS but it is not yet active then just
assume that it should be the active one.
---
 libavcodec/cbs_h264_syntax_template.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/libavcodec/cbs_h264_syntax_template.c 
b/libavcodec/cbs_h264_syntax_template.c
index 0fe18441c..c2fd54682 100644
--- a/libavcodec/cbs_h264_syntax_template.c
+++ b/libavcodec/cbs_h264_syntax_template.c
@@ -561,6 +561,22 @@ static int FUNC(sei_pic_timing)(CodedBitstreamContext 
*ctx, RWContext *rw,
 
 sps = h264->active_sps;
 if (!sps) {
+// If there is exactly one possible SPS but it is not yet active
+// then just assume that it should be the active one.
+int i, k = -1;
+for (i = 0; i < H264_MAX_SPS_COUNT; i++) {
+if (h264->sps[i]) {
+if (k >= 0) {
+k = -1;
+break;
+}
+k = i;
+}
+}
+if (k >= 0)
+sps = h264->sps[k];
+}
+if (!sps) {
 av_log(ctx->log_ctx, AV_LOG_ERROR,
"No active SPS for pic_timing.\n");
 return AVERROR_INVALIDDATA;
-- 
2.11.0

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

[libav-devel] [PATCH 4/6] cbs_h2645: Remove active ps references when it is replaced

2017-12-10 Thread Mark Thompson
---
 libavcodec/cbs_h2645.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libavcodec/cbs_h2645.c b/libavcodec/cbs_h2645.c
index 00eed0f28..1e7854584 100644
--- a/libavcodec/cbs_h2645.c
+++ b/libavcodec/cbs_h2645.c
@@ -674,6 +674,8 @@ static int cbs_h26 ## h26n ## _replace_ ## 
ps_var(CodedBitstreamContext *ctx, \
" id : %d.\n", id); \
 return AVERROR_INVALIDDATA; \
 } \
+if (priv->ps_var[id] == priv->active_ ## ps_var) \
+priv->active_ ## ps_var = NULL ; \
 av_freep(>ps_var[id]); \
 priv->ps_var[id] = av_malloc(sizeof(*ps_var)); \
 if (!priv->ps_var[id]) \
-- 
2.11.0

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

[libav-devel] [PATCH 6/6] h264_metadata: Add ability to delete filler data

2017-12-10 Thread Mark Thompson
Deletes both filler NAL units and filler SEI messages.
---
 libavcodec/h264_metadata_bsf.c | 44 ++
 1 file changed, 44 insertions(+)

diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c
index ac0b9823b..58d598e6d 100644
--- a/libavcodec/h264_metadata_bsf.c
+++ b/libavcodec/h264_metadata_bsf.c
@@ -62,6 +62,8 @@ typedef struct H264MetadataContext {
 int crop_bottom;
 
 const char *sei_user_data;
+
+int delete_filler;
 } H264MetadataContext;
 
 
@@ -278,6 +280,45 @@ static int h264_metadata_filter(AVBSFContext *bsf, 
AVPacket *out)
 }
 }
 
+if (ctx->delete_filler) {
+for (i = 0; i < au->nb_units; i++) {
+int delete_unit = 0;
+if (au->units[i].type == H264_NAL_FILLER_DATA) {
+// Filler NAL units.
+delete_unit = 1;
+}
+if (au->units[i].type == H264_NAL_SEI) {
+// Filler SEI messages.
+H264RawSEI *sei = au->units[i].content;
+
+for (j = 0; j < sei->payload_count; j++) {
+if (sei->payload[j].payload_type ==
+H264_SEI_TYPE_FILLER_PAYLOAD) {
+if (j + 1 < sei->payload_count) {
+memmove(>payload[j],
+>payload[j + 1],
+(sei->payload_count - (j + 1)) *
+sizeof(*sei->payload));
+}
+--j;
+--sei->payload_count;
+}
+}
+if (sei->payload_count == 0)
+delete_unit = 1;
+}
+if (delete_unit) {
+err = ff_cbs_delete_unit(>cbc, au, i);
+if (err < 0) {
+av_log(bsf, AV_LOG_ERROR, "Failed to delete "
+   "filler NAL.\n");
+goto fail;
+}
+--i;
+}
+}
+}
+
 has_sps = 0;
 for (i = 0; i < au->nb_units; i++) {
 if (au->units[i].type == H264_NAL_SPS) {
@@ -495,6 +536,9 @@ static const AVOption h264_metadata_options[] = {
 { "sei_user_data", "Insert SEI user data (UUID+string)",
 OFFSET(sei_user_data), AV_OPT_TYPE_STRING, { .str = NULL } },
 
+{ "delete_filler", "Delete all filler (both NAL and SEI)",
+OFFSET(delete_filler), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1 },
+
 { NULL }
 };
 
-- 
2.11.0

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

[libav-devel] [PATCH 6/9] lavc: Remove register mechanism for hwaccels

2017-12-10 Thread Mark Thompson
There is no longer any need for a list of them at runtime, because
decoders now carry the pointers to their associated hwaccels internally.
The file containing external declarations is now used to make the list
of hwaccels for configure.
---
 configure  |  2 +-
 libavcodec/allcodecs.c | 51 --
 2 files changed, 1 insertion(+), 52 deletions(-)

diff --git a/configure b/configure
index 7f320fee1..d0e1980dc 100755
--- a/configure
+++ b/configure
@@ -2704,7 +2704,6 @@ find_things(){
 
 ENCODER_LIST=$(find_things  encoder  ENC  libavcodec/allcodecs.c)
 DECODER_LIST=$(find_things  decoder  DEC  libavcodec/allcodecs.c)
-HWACCEL_LIST=$(find_things  hwaccel  HWACCEL  libavcodec/allcodecs.c)
 PARSER_LIST=$(find_things   parser   PARSER   libavcodec/allcodecs.c)
 MUXER_LIST=$(find_thingsmuxer_MUX libavformat/allformats.c)
 DEMUXER_LIST=$(find_things  demuxer  DEMUXlibavformat/allformats.c)
@@ -2719,6 +2718,7 @@ find_things_extern(){
 }
 
 BSF_LIST=$(find_things_extern bsf AVBitStreamFilter 
libavcodec/bitstream_filters.c)
+HWACCEL_LIST=$(find_things_extern hwaccel AVHWAccel libavcodec/hwaccels.h)
 PROTOCOL_LIST=$(find_things_extern protocol URLProtocol 
libavformat/protocols.c)
 
 AVCODEC_COMPONENTS_LIST="
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 4ece4307a..50a87493e 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -28,13 +28,6 @@
 #include "avcodec.h"
 #include "version.h"
 
-#define REGISTER_HWACCEL(X, x)  \
-{   \
-extern AVHWAccel ff_##x##_hwaccel;  \
-if (CONFIG_##X##_HWACCEL)   \
-av_register_hwaccel(_##x##_hwaccel); \
-}
-
 #define REGISTER_ENCODER(X, x)  \
 {   \
 extern AVCodec ff_##x##_encoder;\
@@ -66,50 +59,6 @@ void avcodec_register_all(void)
 return;
 initialized = 1;
 
-/* hardware accelerators */
-REGISTER_HWACCEL(H263_VAAPI,h263_vaapi);
-REGISTER_HWACCEL(H264_CUVID,h264_cuvid);
-REGISTER_HWACCEL(H264_D3D11VA,  h264_d3d11va);
-REGISTER_HWACCEL(H264_D3D11VA2, h264_d3d11va2);
-REGISTER_HWACCEL(H264_DXVA2,h264_dxva2);
-REGISTER_HWACCEL(H264_MMAL, h264_mmal);
-REGISTER_HWACCEL(H264_QSV,  h264_qsv);
-REGISTER_HWACCEL(H264_VAAPI,h264_vaapi);
-REGISTER_HWACCEL(H264_VDA,  h264_vda);
-REGISTER_HWACCEL(H264_VDA_OLD,  h264_vda_old);
-REGISTER_HWACCEL(H264_VDPAU,h264_vdpau);
-REGISTER_HWACCEL(HEVC_CUVID,hevc_cuvid);
-REGISTER_HWACCEL(HEVC_D3D11VA,  hevc_d3d11va);
-REGISTER_HWACCEL(HEVC_D3D11VA2, hevc_d3d11va2);
-REGISTER_HWACCEL(HEVC_DXVA2,hevc_dxva2);
-REGISTER_HWACCEL(HEVC_QSV,  hevc_qsv);
-REGISTER_HWACCEL(HEVC_VAAPI,hevc_vaapi);
-REGISTER_HWACCEL(HEVC_VDPAU,hevc_vdpau);
-REGISTER_HWACCEL(MPEG1_VDPAU,   mpeg1_vdpau);
-REGISTER_HWACCEL(MPEG2_D3D11VA, mpeg2_d3d11va);
-REGISTER_HWACCEL(MPEG2_D3D11VA2,mpeg2_d3d11va2);
-REGISTER_HWACCEL(MPEG2_DXVA2,   mpeg2_dxva2);
-REGISTER_HWACCEL(MPEG2_MMAL,mpeg2_mmal);
-REGISTER_HWACCEL(MPEG2_QSV, mpeg2_qsv);
-REGISTER_HWACCEL(MPEG2_VAAPI,   mpeg2_vaapi);
-REGISTER_HWACCEL(MPEG2_VDPAU,   mpeg2_vdpau);
-REGISTER_HWACCEL(MPEG4_VAAPI,   mpeg4_vaapi);
-REGISTER_HWACCEL(MPEG4_VDPAU,   mpeg4_vdpau);
-REGISTER_HWACCEL(VC1_D3D11VA,   vc1_d3d11va);
-REGISTER_HWACCEL(VC1_D3D11VA2,  vc1_d3d11va2);
-REGISTER_HWACCEL(VC1_DXVA2, vc1_dxva2);
-REGISTER_HWACCEL(VC1_QSV,   vc1_qsv);
-REGISTER_HWACCEL(VC1_VAAPI, vc1_vaapi);
-REGISTER_HWACCEL(VC1_VDPAU, vc1_vdpau);
-REGISTER_HWACCEL(VC1_MMAL,  vc1_mmal);
-REGISTER_HWACCEL(VP8_QSV,   vp8_qsv);
-REGISTER_HWACCEL(VP8_VAAPI, vp8_vaapi);
-REGISTER_HWACCEL(WMV3_D3D11VA,  wmv3_d3d11va);
-REGISTER_HWACCEL(WMV3_D3D11VA2, wmv3_d3d11va2);
-REGISTER_HWACCEL(WMV3_DXVA2,wmv3_dxva2);
-REGISTER_HWACCEL(WMV3_VAAPI,wmv3_vaapi);
-REGISTER_HWACCEL(WMV3_VDPAU,wmv3_vdpau);
-
 /* video codecs */
 REGISTER_ENCODER(A64MULTI,  a64multi);
 REGISTER_ENCODER(A64MULTI5, a64multi5);
-- 
2.11.0

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

[libav-devel] [PATCH 7/9] lavc: Delete all fake hwaccels

2017-12-10 Thread Mark Thompson
They are now unused.
---
 configure | 18 +-
 libavcodec/mmaldec.c  | 21 -
 libavcodec/qsvdec_h2645.c | 18 --
 libavcodec/qsvdec_other.c | 27 ---
 4 files changed, 5 insertions(+), 79 deletions(-)

diff --git a/configure b/configure
index d0e1980dc..d31cb5658 100755
--- a/configure
+++ b/configure
@@ -2183,8 +2183,6 @@ h264_d3d11va2_hwaccel_deps="d3d11va"
 h264_d3d11va2_hwaccel_select="h264_decoder"
 h264_dxva2_hwaccel_deps="dxva2"
 h264_dxva2_hwaccel_select="h264_decoder"
-h264_mmal_hwaccel_deps="mmal"
-h264_qsv_hwaccel_deps="libmfx"
 h264_vaapi_hwaccel_deps="vaapi"
 h264_vaapi_hwaccel_select="h264_decoder"
 h264_vda_hwaccel_deps="vda"
@@ -2201,7 +2199,6 @@ hevc_d3d11va2_hwaccel_deps="d3d11va DXVA_PicParams_HEVC"
 hevc_d3d11va2_hwaccel_select="hevc_decoder"
 hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC"
 hevc_dxva2_hwaccel_select="hevc_decoder"
-hevc_qsv_hwaccel_deps="libmfx"
 hevc_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferHEVC"
 hevc_vaapi_hwaccel_select="hevc_decoder"
 hevc_vdpau_hwaccel_deps="vdpau VdpPictureInfoHEVC"
@@ -2214,8 +2211,6 @@ mpeg2_d3d11va2_hwaccel_deps="d3d11va"
 mpeg2_d3d11va2_hwaccel_select="mpeg2video_decoder"
 mpeg2_dxva2_hwaccel_deps="dxva2"
 mpeg2_dxva2_hwaccel_select="mpeg2video_decoder"
-mpeg2_mmal_hwaccel_deps="mmal"
-mpeg2_qsv_hwaccel_deps="libmfx"
 mpeg2_vaapi_hwaccel_deps="vaapi"
 mpeg2_vaapi_hwaccel_select="mpeg2video_decoder"
 mpeg2_vdpau_hwaccel_deps="vdpau"
@@ -2230,13 +2225,10 @@ vc1_d3d11va2_hwaccel_deps="d3d11va"
 vc1_d3d11va2_hwaccel_select="vc1_decoder"
 vc1_dxva2_hwaccel_deps="dxva2"
 vc1_dxva2_hwaccel_select="vc1_decoder"
-vc1_mmal_hwaccel_deps="mmal"
-vc1_qsv_hwaccel_deps="libmfx"
 vc1_vaapi_hwaccel_deps="vaapi"
 vc1_vaapi_hwaccel_select="vc1_decoder"
 vc1_vdpau_hwaccel_deps="vdpau"
 vc1_vdpau_hwaccel_select="vc1_decoder"
-vp8_qsv_hwaccel_deps="libmfx"
 vp8_vaapi_hwaccel_deps="vaapi VAPictureParameterBufferVP8"
 vp8_vaapi_hwaccel_select="vp8_decoder"
 wmv3_d3d11va_hwaccel_select="vc1_d3d11va_hwaccel"
@@ -2261,12 +2253,12 @@ scale_npp_filter_deps="cuda libnpp"
 h264_mmal_decoder_deps="mmal"
 h264_nvenc_encoder_deps="nvenc"
 h264_omx_encoder_deps="omx"
-h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec 
h264_qsv_hwaccel"
+h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec"
 h264_qsv_encoder_select="qsvenc"
 h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264"
 h264_vaapi_encoder_select="cbs_h264 vaapi_encode"
 hevc_nvenc_encoder_deps="nvenc"
-hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser hevc_qsv_hwaccel 
qsvdec"
+hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser qsvdec"
 hevc_qsv_encoder_select="hevcparse qsvenc"
 hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC"
 hevc_vaapi_encoder_select="cbs_h265 vaapi_encode"
@@ -2275,14 +2267,14 @@ mjpeg_qsv_encoder_select="qsvenc"
 mjpeg_vaapi_encoder_deps="VAEncPictureParameterBufferJPEG"
 mjpeg_vaapi_encoder_select="vaapi_encode jpegtables"
 mpeg2_mmal_decoder_deps="mmal"
-mpeg2_qsv_decoder_select="qsvdec mpeg2_qsv_hwaccel mpegvideo_parser"
+mpeg2_qsv_decoder_select="qsvdec mpegvideo_parser"
 mpeg2_qsv_encoder_select="qsvenc"
 mpeg2_vaapi_encoder_deps="VAEncPictureParameterBufferMPEG2"
 mpeg2_vaapi_encoder_select="cbs_mpeg2 vaapi_encode"
 mpeg4_omx_encoder_deps="omx"
 vc1_mmal_decoder_deps="mmal"
-vc1_qsv_decoder_select="qsvdec vc1_qsv_hwaccel vc1_parser"
-vp8_qsv_decoder_select="qsvdec vp8_qsv_hwaccel vp8_parser"
+vc1_qsv_decoder_select="qsvdec vc1_parser"
+vp8_qsv_decoder_select="qsvdec vp8_parser"
 vp8_vaapi_encoder_deps="VAEncPictureParameterBufferVP8"
 vp8_vaapi_encoder_select="vaapi_encode"
 vp9_vaapi_encoder_deps="VAEncPictureParameterBufferVP9"
diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c
index 9d92ee715..b158e24cb 100644
--- a/libavcodec/mmaldec.c
+++ b/libavcodec/mmaldec.c
@@ -788,27 +788,6 @@ static int ffmmal_decode(AVCodecContext *avctx, void 
*data, int *got_frame,
 return ret;
 }
 
-AVHWAccel ff_h264_mmal_hwaccel = {
-.name   = "h264_mmal",
-.type   = AVMEDIA_TYPE_VIDEO,
-.id = AV_CODEC_ID_H264,
-.pix_fmt= AV_PIX_FMT_MMAL,
-};
-
-AVHWAccel ff_mpeg2_mmal_hwaccel = {
-.name   = "mpeg2_mmal",
-.type   = AVMEDIA_TYPE_VIDEO,
-.id = AV_CODEC_ID_MPEG2VIDEO,
-.pix_fmt= AV_PIX_FMT_MMAL,
-};
-
-AVHWAccel ff_vc1_mmal_hwaccel = {
-.name   = "vc1_mmal",
-.type   = AVMEDIA_TYPE_VIDEO,
-.id = AV_CODEC_ID_VC1,
-.pix_fmt= AV_PIX_FMT_MMAL,
-};
-
 static const AVCodecHWConfigInternal *mmal_hw_configs = {
 HW_CONFIG_INTERNAL(MMAL),
 NULL
diff --git a/libavcodec/qsvdec_h2645.c b/libavcodec/qsvdec_h2645.c
index 2fabe38c5..a87e81679 100644
--- a/libavcodec/qsvdec_h2645.c
+++ b/libavcodec/qsvdec_h2645.c
@@ -180,15 +180,6 @@ static void qsv_decode_flush(AVCodecContext *avctx)
 #define OFFSET(x) offsetof(QSVH2645Context, x)
 #define VD 

[libav-devel] [PATCH 9/9] avconv: Use codec hardware config to configure hwaccels

2017-12-10 Thread Mark Thompson
Removes specific support for all hwaccels supported by the generic code
(CUVID, DXVA2, D3D11VA, VAAPI and VDPAU).
---
 avtools/avconv.c |  76 +++-
 avtools/avconv.h |   9 +-
 avtools/avconv_hw.c  | 249 ++-
 avtools/avconv_opt.c |  47 +-
 4 files changed, 246 insertions(+), 135 deletions(-)

diff --git a/avtools/avconv.c b/avtools/avconv.c
index cee7a7b45..ac15464a8 100644
--- a/avtools/avconv.c
+++ b/avtools/avconv.c
@@ -1631,44 +1631,77 @@ static void print_sdp(void)
 av_freep();
 }
 
-static const HWAccel *get_hwaccel(enum AVPixelFormat pix_fmt)
-{
-int i;
-for (i = 0; hwaccels[i].name; i++)
-if (hwaccels[i].pix_fmt == pix_fmt)
-return [i];
-return NULL;
-}
-
 static enum AVPixelFormat get_format(AVCodecContext *s, const enum 
AVPixelFormat *pix_fmts)
 {
 InputStream *ist = s->opaque;
 const enum AVPixelFormat *p;
 int ret;
 
-for (p = pix_fmts; *p != -1; p++) {
+for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) {
 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p);
-const HWAccel *hwaccel;
+const AVCodecHWConfig  *config = NULL;
+int i;
 
 if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
 break;
 
-hwaccel = get_hwaccel(*p);
-if (!hwaccel ||
-(ist->active_hwaccel_id && ist->active_hwaccel_id != hwaccel->id) 
||
-(ist->hwaccel_id != HWACCEL_AUTO && ist->hwaccel_id != 
hwaccel->id))
-continue;
+if (ist->hwaccel_id == HWACCEL_GENERIC ||
+ist->hwaccel_id == HWACCEL_AUTO) {
+for (i = 0;; i++) {
+config = avcodec_get_hw_config(s->codec, i);
+if (!config)
+break;
+if (!(config->methods &
+  AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX))
+continue;
+if (config->pix_fmt == *p)
+break;
+}
+}
+if (config) {
+if (config->device_type != ist->hwaccel_device_type) {
+// Different hwaccel offered, ignore.
+continue;
+}
 
-ret = hwaccel->init(s);
-if (ret < 0) {
-if (ist->hwaccel_id == hwaccel->id) {
+ret = hwaccel_decode_init(s);
+if (ret < 0) {
+if (ist->hwaccel_id == HWACCEL_GENERIC) {
+av_log(NULL, AV_LOG_FATAL,
+   "%s hwaccel requested for input stream #%d:%d, "
+   "but cannot be initialized.\n",
+   av_hwdevice_get_type_name(config->device_type),
+   ist->file_index, ist->st->index);
+return AV_PIX_FMT_NONE;
+}
+continue;
+}
+} else {
+const HWAccel *hwaccel = NULL;
+int i;
+for (i = 0; hwaccels[i].name; i++) {
+if (hwaccels[i].pix_fmt == *p) {
+hwaccel = [i];
+break;
+}
+}
+if (!hwaccel) {
+// No hwaccel supporting this pixfmt.
+continue;
+}
+if (hwaccel->id != ist->hwaccel_id) {
+// Does not match requested hwaccel.
+continue;
+}
+
+ret = hwaccel->init(s);
+if (ret < 0) {
 av_log(NULL, AV_LOG_FATAL,
"%s hwaccel requested for input stream #%d:%d, "
"but cannot be initialized.\n", hwaccel->name,
ist->file_index, ist->st->index);
 return AV_PIX_FMT_NONE;
 }
-continue;
 }
 
 if (ist->hw_frames_ctx) {
@@ -1677,8 +1710,7 @@ static enum AVPixelFormat get_format(AVCodecContext *s, 
const enum AVPixelFormat
 return AV_PIX_FMT_NONE;
 }
 
-ist->active_hwaccel_id = hwaccel->id;
-ist->hwaccel_pix_fmt   = *p;
+ist->hwaccel_pix_fmt = *p;
 break;
 }
 
diff --git a/avtools/avconv.h b/avtools/avconv.h
index b5843fbc0..0d24c71a7 100644
--- a/avtools/avconv.h
+++ b/avtools/avconv.h
@@ -52,13 +52,9 @@
 enum HWAccelID {
 HWACCEL_NONE = 0,
 HWACCEL_AUTO,
-HWACCEL_VDPAU,
-HWACCEL_DXVA2,
+HWACCEL_GENERIC,
 HWACCEL_VDA,
 HWACCEL_QSV,
-HWACCEL_VAAPI,
-HWACCEL_D3D11VA,
-HWACCEL_CUVID,
 };
 
 typedef struct HWAccel {
@@ -66,7 +62,6 @@ typedef struct HWAccel {
 int (*init)(AVCodecContext *s);
 enum HWAccelID id;
 enum AVPixelFormat pix_fmt;
-enum AVHWDeviceType device_type;
 } HWAccel;
 
 typedef struct HWDevice {
@@ -301,11 +296,11 @@ typedef struct InputStream {
 
 /* hwaccel options */
 enum HWAccelID hwaccel_id;
+enum AVHWDeviceType hwaccel_device_type;
 char  *hwaccel_device;

[libav-devel] [PATCH 8/9] lavc: Mark all AVHWAccel structures as const

2017-12-10 Thread Mark Thompson
---
 libavcodec/avcodec.h  |  2 +-
 libavcodec/cuvid_h264.c   |  2 +-
 libavcodec/cuvid_hevc.c   |  2 +-
 libavcodec/decode.c   |  2 +-
 libavcodec/dxva2_h264.c   |  6 ++---
 libavcodec/dxva2_hevc.c   |  6 ++---
 libavcodec/dxva2_mpeg2.c  |  6 ++---
 libavcodec/dxva2_vc1.c| 12 -
 libavcodec/hwaccels.h | 68 +++
 libavcodec/vaapi_h264.c   |  2 +-
 libavcodec/vaapi_hevc.c   |  2 +-
 libavcodec/vaapi_mpeg2.c  |  2 +-
 libavcodec/vaapi_mpeg4.c  |  4 +--
 libavcodec/vaapi_vc1.c|  4 +--
 libavcodec/vaapi_vp8.c|  2 +-
 libavcodec/vda_h264.c |  4 +--
 libavcodec/vdpau_h264.c   |  2 +-
 libavcodec/vdpau_hevc.c   |  2 +-
 libavcodec/vdpau_mpeg12.c |  4 +--
 libavcodec/vdpau_mpeg4.c  |  2 +-
 libavcodec/vdpau_vc1.c|  4 +--
 21 files changed, 70 insertions(+), 70 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index f81a48e47..531ffad6a 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2294,7 +2294,7 @@ typedef struct AVCodecContext {
  * - encoding: unused.
  * - decoding: Set by libavcodec
  */
-struct AVHWAccel *hwaccel;
+const struct AVHWAccel *hwaccel;
 
 /**
  * Hardware accelerator context.
diff --git a/libavcodec/cuvid_h264.c b/libavcodec/cuvid_h264.c
index a83e4ffba..4f36e922b 100644
--- a/libavcodec/cuvid_h264.c
+++ b/libavcodec/cuvid_h264.c
@@ -163,7 +163,7 @@ static int cuvid_h264_decode_init(AVCodecContext *avctx)
 return ff_cuvid_decode_init(avctx, sps->ref_frame_count + 
sps->num_reorder_frames);
 }
 
-AVHWAccel ff_h264_cuvid_hwaccel = {
+const AVHWAccel ff_h264_cuvid_hwaccel = {
 .name = "h264_cuvid",
 .type = AVMEDIA_TYPE_VIDEO,
 .id   = AV_CODEC_ID_H264,
diff --git a/libavcodec/cuvid_hevc.c b/libavcodec/cuvid_hevc.c
index 5de9bca48..fcf20bbcf 100644
--- a/libavcodec/cuvid_hevc.c
+++ b/libavcodec/cuvid_hevc.c
@@ -266,7 +266,7 @@ static int cuvid_hevc_decode_init(AVCodecContext *avctx)
 return ff_cuvid_decode_init(avctx, sps->temporal_layer[sps->max_sub_layers 
- 1].max_dec_pic_buffering + 1);
 }
 
-AVHWAccel ff_hevc_cuvid_hwaccel = {
+const AVHWAccel ff_hevc_cuvid_hwaccel = {
 .name = "hevc_cuvid",
 .type = AVMEDIA_TYPE_VIDEO,
 .id   = AV_CODEC_ID_HEVC,
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index bc2208a3f..12a95d422 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -812,7 +812,7 @@ static int hwaccel_init(AVCodecContext *avctx,
 return AVERROR(ENOMEM);
 }
 
-avctx->hwaccel = (AVHWAccel*)hwaccel;
+avctx->hwaccel = hwaccel;
 err = hwaccel->init(avctx);
 if (err < 0) {
 av_log(avctx, AV_LOG_ERROR, "Failed setup for format %s: "
diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c
index 8ce8c358c..50e7863bf 100644
--- a/libavcodec/dxva2_h264.c
+++ b/libavcodec/dxva2_h264.c
@@ -513,7 +513,7 @@ static int dxva2_h264_end_frame(AVCodecContext *avctx)
 }
 
 #if CONFIG_H264_DXVA2_HWACCEL
-AVHWAccel ff_h264_dxva2_hwaccel = {
+const AVHWAccel ff_h264_dxva2_hwaccel = {
 .name   = "h264_dxva2",
 .type   = AVMEDIA_TYPE_VIDEO,
 .id = AV_CODEC_ID_H264,
@@ -530,7 +530,7 @@ AVHWAccel ff_h264_dxva2_hwaccel = {
 #endif
 
 #if CONFIG_H264_D3D11VA_HWACCEL
-AVHWAccel ff_h264_d3d11va_hwaccel = {
+const AVHWAccel ff_h264_d3d11va_hwaccel = {
 .name   = "h264_d3d11va",
 .type   = AVMEDIA_TYPE_VIDEO,
 .id = AV_CODEC_ID_H264,
@@ -547,7 +547,7 @@ AVHWAccel ff_h264_d3d11va_hwaccel = {
 #endif
 
 #if CONFIG_H264_D3D11VA2_HWACCEL
-AVHWAccel ff_h264_d3d11va2_hwaccel = {
+const AVHWAccel ff_h264_d3d11va2_hwaccel = {
 .name   = "h264_d3d11va2",
 .type   = AVMEDIA_TYPE_VIDEO,
 .id = AV_CODEC_ID_H264,
diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c
index 1d665f07d..02d3b9b15 100644
--- a/libavcodec/dxva2_hevc.c
+++ b/libavcodec/dxva2_hevc.c
@@ -422,7 +422,7 @@ static int dxva2_hevc_end_frame(AVCodecContext *avctx)
 }
 
 #if CONFIG_HEVC_DXVA2_HWACCEL
-AVHWAccel ff_hevc_dxva2_hwaccel = {
+const AVHWAccel ff_hevc_dxva2_hwaccel = {
 .name   = "hevc_dxva2",
 .type   = AVMEDIA_TYPE_VIDEO,
 .id = AV_CODEC_ID_HEVC,
@@ -439,7 +439,7 @@ AVHWAccel ff_hevc_dxva2_hwaccel = {
 #endif
 
 #if CONFIG_HEVC_D3D11VA_HWACCEL
-AVHWAccel ff_hevc_d3d11va_hwaccel = {
+const AVHWAccel ff_hevc_d3d11va_hwaccel = {
 .name   = "hevc_d3d11va",
 .type   = AVMEDIA_TYPE_VIDEO,
 .id = AV_CODEC_ID_HEVC,
@@ -456,7 +456,7 @@ AVHWAccel ff_hevc_d3d11va_hwaccel = {
 #endif
 
 #if CONFIG_HEVC_D3D11VA2_HWACCEL
-AVHWAccel ff_hevc_d3d11va2_hwaccel = {
+const AVHWAccel ff_hevc_d3d11va2_hwaccel = {
 .name   = "hevc_d3d11va2",
 .type   = AVMEDIA_TYPE_VIDEO,
 .id = AV_CODEC_ID_HEVC,

[libav-devel] [PATCH 5/9] lavc: Deprecate av_hwaccel_next() and av_register_hwaccel()

2017-12-10 Thread Mark Thompson
---
 doc/APIchanges   |  4 
 libavcodec/avcodec.h | 13 +
 libavcodec/utils.c   | 15 +--
 libavcodec/version.h |  3 +++
 4 files changed, 25 insertions(+), 10 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index 9d8c7725e..a1abcffaa 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -14,6 +14,10 @@ libavutil: 2017-03-23
 API changes, most recent first:
 
 2017-xx-xx - xxx - lavc 58.x+1.0 - avcodec.h
+  Deprecate user visibility of the AVHWAccel structure and the functions
+  av_register_hwaccel() and av_hwaccel_next().
+
+2017-xx-xx - xxx - lavc 58.x+1.0 - avcodec.h
   Add AVCodecHWConfig and avcodec_get_hw_config().
 
 2017-xx-xx - xxx - lavu 56.7.0 - stereo3d.h
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 5d7b3459c..f81a48e47 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2937,6 +2937,10 @@ const AVCodecHWConfig *avcodec_get_hw_config(const 
AVCodec *codec, int index);
 
 /**
  * @defgroup lavc_hwaccel AVHWAccel
+ *
+ * @note  Nothing in this structure should be accessed by the user.  At some
+ *point in future it will not be externally visible at all.
+ *
  * @{
  */
 typedef struct AVHWAccel {
@@ -5015,17 +5019,26 @@ void av_fast_padded_malloc(void *ptr, unsigned int 
*size, size_t min_size);
  */
 unsigned int av_xiphlacing(unsigned char *s, unsigned int v);
 
+#if FF_API_USER_VISIBLE_AVHWACCEL
 /**
  * Register the hardware accelerator hwaccel.
+ *
+ * @deprecated  This function doesn't do anything.
  */
+attribute_deprecated
 void av_register_hwaccel(AVHWAccel *hwaccel);
 
 /**
  * If hwaccel is NULL, returns the first registered hardware accelerator,
  * if hwaccel is non-NULL, returns the next registered hardware accelerator
  * after hwaccel, or NULL if hwaccel is the last one.
+ *
+ * @deprecated  AVHWaccel structures contain no user-serviceable parts, so
+ *  this function should not be used.
  */
+attribute_deprecated
 AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel);
+#endif
 
 
 /**
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 3d6b35fa4..ba3457664 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -1347,21 +1347,16 @@ const AVCodecHWConfig *avcodec_get_hw_config(const 
AVCodec *codec, int index)
 return >hw_configs[index]->public;
 }
 
-static AVHWAccel *first_hwaccel = NULL;
-
-void av_register_hwaccel(AVHWAccel *hwaccel)
+#if FF_API_USER_VISIBLE_AVHWACCEL
+AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel)
 {
-AVHWAccel **p = _hwaccel;
-while (*p)
-p = &(*p)->next;
-*p = hwaccel;
-hwaccel->next = NULL;
+return NULL;
 }
 
-AVHWAccel *av_hwaccel_next(const AVHWAccel *hwaccel)
+void av_register_hwaccel(AVHWAccel *hwaccel)
 {
-return hwaccel ? hwaccel->next : first_hwaccel;
 }
+#endif
 
 int av_lockmgr_register(int (*cb)(void **mutex, enum AVLockOp op))
 {
diff --git a/libavcodec/version.h b/libavcodec/version.h
index aa6cdcd6b..09e03328d 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -95,5 +95,8 @@
 #ifndef FF_API_VAAPI_CONTEXT
 #define FF_API_VAAPI_CONTEXT(LIBAVCODEC_VERSION_MAJOR < 59)
 #endif
+#ifndef FF_API_USER_VISIBLE_AVHWACCEL
+#define FF_API_USER_VISIBLE_AVHWACCEL (LIBAVCODEC_VERSION_MAJOR < 60)
+#endif
 
 #endif /* AVCODEC_VERSION_H */
-- 
2.11.0

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

[libav-devel] [PATCH 1/9] lavc: Add codec metadata to indicate hardware support

2017-12-10 Thread Mark Thompson
---
 doc/APIchanges   |  3 +++
 libavcodec/avcodec.h | 74 
 libavcodec/hwaccel.h | 18 +
 libavcodec/utils.c   | 12 +
 4 files changed, 107 insertions(+)

diff --git a/doc/APIchanges b/doc/APIchanges
index a7ecbcdaa..9d8c7725e 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,9 @@ libavutil: 2017-03-23
 
 API changes, most recent first:
 
+2017-xx-xx - xxx - lavc 58.x+1.0 - avcodec.h
+  Add AVCodecHWConfig and avcodec_get_hw_config().
+
 2017-xx-xx - xxx - lavu 56.7.0 - stereo3d.h
   Add view field to AVStereo3D structure and AVStereo3DView enum.
 
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 562483502..5d7b3459c 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"
@@ -2735,6 +2736,61 @@ typedef struct AVProfile {
 const char *name; ///< short name for the profile
 } AVProfile;
 
+enum {
+/**
+ * The codec supports this format via the hw_device_ctx interface.
+ *
+ * When selecting this format, AVCodecContext.hw_device_ctx should
+ * have been set to a device of the specified type before calling
+ * avcodec_open2().
+ */
+AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX = 0x01,
+/**
+ * The codec supports this format via the hw_frames_ctx interface.
+ *
+ * When selecting this format for a decoder,
+ * AVCodecContext.hw_frames_ctx should be set to a suitable frames
+ * context inside the get_format() callback.  The frames context
+ * must have been created on a device of the specified type.
+ */
+AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX = 0x02,
+/**
+ * The codec supports this format by some internal method.
+ *
+ * This format can be selected without any additional configuration -
+ * no device or frames context is required.
+ */
+AV_CODEC_HW_CONFIG_METHOD_INTERNAL  = 0x04,
+/**
+ * The codec supports this format by some ad-hoc method.
+ *
+ * Additional settings and/or function calls are required.  See the
+ * codec-specific documentation for details.  (Methods requiring
+ * this sort of configuration are deprecated and others should be
+ * used in preference.)
+ */
+AV_CODEC_HW_CONFIG_METHOD_AD_HOC= 0x08,
+};
+
+typedef struct AVCodecHWConfig {
+/**
+ * A hardware pixel format which the codec can use.
+ */
+enum AVPixelFormat pix_fmt;
+/**
+ * Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible
+ * setup methods which can be used with this configuration.
+ */
+int methods;
+/**
+ * The device type associated with the configuration.
+ *
+ * Must be set for AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX and
+ * AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX, otherwise unused.
+ */
+enum AVHWDeviceType device_type;
+} AVCodecHWConfig;
+
 typedef struct AVCodecDefault AVCodecDefault;
 
 struct AVSubtitle;
@@ -2859,9 +2915,27 @@ typedef struct AVCodec {
  * packets before decoding.
  */
 const char *bsfs;
+
+/**
+ * Array of pointers to hardware configurations supported by the codec,
+ * or NULL if no hardware supported.  The array is terminated by a NULL
+ * pointer.
+ *
+ * The user can only access this field via avcodec_get_hw_config().
+ */
+const struct AVCodecHWConfigInternal **hw_configs;
 } AVCodec;
 
 /**
+ * Retrieve supported hardware configurations for a codec.
+ *
+ * Values of index from zero to some maximum return the indexed configuration
+ * descriptor; all other values return NULL.  If the codec does not support
+ * any hardware configurations then it will always return NULL.
+ */
+const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index);
+
+/**
  * @defgroup lavc_hwaccel AVHWAccel
  * @{
  */
diff --git a/libavcodec/hwaccel.h b/libavcodec/hwaccel.h
index 60dbe81c8..b6d566248 100644
--- a/libavcodec/hwaccel.h
+++ b/libavcodec/hwaccel.h
@@ -19,6 +19,24 @@
 #ifndef AVCODEC_HWACCEL_H
 #define AVCODEC_HWACCEL_H
 
+#include "avcodec.h"
+
+
 #define HWACCEL_CAP_ASYNC_SAFE  (1 << 0)
 
+
+typedef struct AVCodecHWConfigInternal {
+/**
+ * This is the structure which will be returned to the user by
+ * avcodec_get_hw_config().
+ */
+AVCodecHWConfig public;
+/**
+ * If this configuration uses a hwaccel, a pointer to it.
+ * If not, NULL.
+ */
+const AVHWAccel *hwaccel;
+} AVCodecHWConfigInternal;
+
+
 #endif /* AVCODEC_HWACCEL_H */
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index bc421f67f..3d6b35fa4 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -41,6 +41,7 @@
 #include "libavutil/dict.h"
 #include "avcodec.h"
 

[libav-devel] [PATCH 2/9] lavc: Add hardware config metadata for decoders supporting hardware output

2017-12-10 Thread Mark Thompson
This includes a pointer to the associated hwaccel for decoders using
hwaccels - these will be used later to implement the hwaccel setup
without needing a global list.

Also added is a new file listing all hwaccels as external declarations -
this will be used later to generate the hwaccel list at configure time.
---
 libavcodec/h263dec.c   | 10 
 libavcodec/h264dec.c   | 28 ++
 libavcodec/hevcdec.c   | 22 +
 libavcodec/hwaccel.h   | 38 +
 libavcodec/hwaccels.h  | 59 ++
 libavcodec/mmaldec.c   |  7 ++
 libavcodec/mpeg12dec.c | 27 -
 libavcodec/mpeg4videodec.c | 10 
 libavcodec/qsvdec.c| 13 ++
 libavcodec/qsvdec.h|  3 +++
 libavcodec/qsvdec_h2645.c  |  2 ++
 libavcodec/qsvdec_other.c  |  3 +++
 libavcodec/vc1dec.c| 37 +
 libavcodec/vp8.c   |  7 ++
 14 files changed, 265 insertions(+), 1 deletion(-)
 create mode 100644 libavcodec/hwaccels.h

diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c
index 921ff5fb9..b883c 100644
--- a/libavcodec/h263dec.c
+++ b/libavcodec/h263dec.c
@@ -31,6 +31,7 @@
 #include "flv.h"
 #include "h263.h"
 #include "h263_parser.h"
+#include "hwaccel.h"
 #include "internal.h"
 #include "mpeg_er.h"
 #include "mpeg4video.h"
@@ -677,4 +678,13 @@ AVCodec ff_h263_decoder = {
   AV_CODEC_CAP_TRUNCATED | AV_CODEC_CAP_DELAY,
 .flush  = ff_mpeg_flush,
 .pix_fmts   = ff_h263_hwaccel_pixfmt_list_420,
+.hw_configs = (const AVCodecHWConfigInternal*[]) {
+#if CONFIG_H263_VAAPI_HWACCEL
+HWACCEL_VAAPI(h263),
+#endif
+#if CONFIG_MPEG4_VDPAU_HWACCEL
+HWACCEL_VDPAU(mpeg4),
+#endif
+NULL
+},
 };
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
index 7a8293efa..4bfd78962 100644
--- a/libavcodec/h264dec.c
+++ b/libavcodec/h264dec.c
@@ -44,6 +44,7 @@
 #include "h264chroma.h"
 #include "h264_mvpred.h"
 #include "h264_ps.h"
+#include "hwaccel.h"
 #include "mathops.h"
 #include "me_cmp.h"
 #include "mpegutils.h"
@@ -786,6 +787,33 @@ AVCodec ff_h264_decoder = {
 .capabilities  = /*AV_CODEC_CAP_DRAW_HORIZ_BAND |*/ 
AV_CODEC_CAP_DR1 |
  AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS |
  AV_CODEC_CAP_FRAME_THREADS,
+.hw_configs= (const AVCodecHWConfigInternal*[]) {
+#if CONFIG_H264_CUVID_HWACCEL
+   HWACCEL_CUVID(h264),
+#endif
+#if CONFIG_H264_DXVA2_HWACCEL
+   HWACCEL_DXVA2(h264),
+#endif
+#if CONFIG_H264_D3D11VA_HWACCEL
+   HWACCEL_D3D11VA(h264),
+#endif
+#if CONFIG_H264_D3D11VA2_HWACCEL
+   HWACCEL_D3D11VA2(h264),
+#endif
+#if CONFIG_H264_VAAPI_HWACCEL
+   HWACCEL_VAAPI(h264),
+#endif
+#if CONFIG_H264_VDPAU_HWACCEL
+   HWACCEL_VDPAU(h264),
+#endif
+#if CONFIG_H264_VDA_HWACCEL
+   HW_CONFIG_HWACCEL(0, 0, 1, VDA, NONE, 
ff_h264_vda_hwaccel),
+#endif
+#if CONFIG_H264_VDA_OLD_HWACCEL
+   HW_CONFIG_HWACCEL(0, 0, 1, VDA_VLD, NONE, 
ff_h264_vda_old_hwaccel),
+#endif
+   NULL
+   },
 .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | 
FF_CODEC_CAP_EXPORTS_CROPPING,
 .flush = flush_dpb,
 .init_thread_copy  = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy),
diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c
index f1d1c7749..130b99f77 100644
--- a/libavcodec/hevcdec.c
+++ b/libavcodec/hevcdec.c
@@ -39,6 +39,7 @@
 #include "hevc.h"
 #include "hevc_data.h"
 #include "hevcdec.h"
+#include "hwaccel.h"
 #include "profiles.h"
 
 const uint8_t ff_hevc_qpel_extra_before[4] = { 0, 3, 3, 3 };
@@ -3120,4 +3121,25 @@ AVCodec ff_hevc_decoder = {
  AV_CODEC_CAP_FRAME_THREADS,
 .profiles  = NULL_IF_CONFIG_SMALL(ff_hevc_profiles),
 .caps_internal = FF_CODEC_CAP_EXPORTS_CROPPING | 
FF_CODEC_CAP_INIT_THREADSAFE,
+.hw_configs= (const AVCodecHWConfigInternal*[]) {
+#if CONFIG_HEVC_CUVID_HWACCEL
+   HWACCEL_CUVID(hevc),
+#endif
+#if CONFIG_HEVC_DXVA2_HWACCEL
+   HWACCEL_DXVA2(hevc),
+#endif
+#if CONFIG_HEVC_D3D11VA_HWACCEL
+   HWACCEL_D3D11VA(hevc),
+#endif
+#if CONFIG_HEVC_D3D11VA2_HWACCEL
+   HWACCEL_D3D11VA2(hevc),
+#endif
+#if CONFIG_HEVC_VAAPI_HWACCEL
+   HWACCEL_VAAPI(hevc),
+#endif
+#if CONFIG_HEVC_VDPAU_HWACCEL
+   HWACCEL_VDPAU(hevc),
+#endif
+   NULL
+  

  1   2   3   4   5   6   7   8   9   10   >