Hi,

2014-09-05 18:13 GMT+02:00 wm4 <[email protected]>:
> On Thu,  4 Sep 2014 16:11:15 +0300
> Rémi Denis-Courmont <[email protected]> wrote:
>
>> From: Rémi Denis-Courmont <[email protected]>
>>
>> Using the not so new init and uninit callbacks, avcodec can now take
>> care of creating and destroying the VDPAU decoder instance.
>>
>> The application is still responsible for creating the VDPAU device
>> and allocating video surfaces. But it wull no longer needs to care
>> about any codec-specific aspects.
>>
>> This deprecates av_vdpau_alloc_context() and introduces a new
>> av_vdpau_create_context() accepting the VDPAU device (VdpDevice) and
>> VDPAU driver (VdpGetProcAddress) as explicit parameter.
>>
>> Note that av_vdpau_get_profile() is also deprecated since it becomes
>> totally useless for external use.
>>
>> [Discuss: It could be:
>>     int av_vdpau_init_context(AVCodecContext *, VdpDevice,
>>                               VdpGetProcAddress *);
>> instead (that would enable capability checks). In that case, there
>> should probably be a deinitializer for the sake of symmetry:
>>     void av_vdpau_deinit_context(AVCodecContext *);
>> instead of the current reliance on av_freep().]
>> ---
>>  libavcodec/vdpau.c          | 84 
>> ++++++++++++++++++++++++++++++++++++++++++++-
>>  libavcodec/vdpau.h          | 27 +++++++++++++--
>>  libavcodec/vdpau_internal.h | 16 +++++++++
>>  libavcodec/version.h        |  3 ++
>>  4 files changed, 127 insertions(+), 3 deletions(-)
>>
>> diff --git a/libavcodec/vdpau.c b/libavcodec/vdpau.c
>> index 5406874..c285897 100644
>> --- a/libavcodec/vdpau.c
>> +++ b/libavcodec/vdpau.c
>> @@ -22,7 +22,9 @@
>>   */
>>
>>  #include <limits.h>
>> +#include "libavutil/avassert.h"
>>  #include "avcodec.h"
>> +#include "internal.h"
>>  #include "h264.h"
>>  #include "vc1.h"
>>
>> @@ -38,6 +40,67 @@
>>   * @{
>>   */
>>
>> +static VdpStatus vdp_enosys(/* Unspecified, not void - leave empty */)
>> +{
>> +    return VDP_STATUS_NO_IMPLEMENTATION;
>> +}
>> +
>> +static void *ff_vdpau_get_proc_address(AVCodecContext *avctx, VdpFuncId id)
>> +{
>> +    AVVDPAUContext *hwctx = avctx->hwaccel_context;
>> +    void *ret;
>> +
>> +    av_assert0(hwctx->device != VDP_INVALID_HANDLE);
>> +
>> +    if (hwctx->get_proc_address(hwctx->device, id, &ret) != VDP_STATUS_OK)
>> +        ret = vdp_enosys;
>
> Isn't this very questionable? IMO initialization should just fail if a
> required function is missing. But if a C language lawyer can confirm
> that this use of vdp_enosys is indeed legal, why not (although I
> have my doubt).

This is indeed questionable. A pointer to function is not always a
pointer to the function start address, but it could rather be a
pointer to a function descriptor, which comprises of the function
start address and additional information. e.g. some TOC pointer on
ppc64. It's better to use the correct type: pointer-to-function. This
is assuming that get_proc_address() really returns a pointer to
function to begin with.

I don't immediately remember the chapter and verse, but probably
somewhere in section 6.2.x or 6.3.x.
i.e. casts from pointer-to-function to pointer are not guaranteed.

>> +    return ret;
>> +}
>> +
>> +int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile,
>> +                         uint32_t level, uint32_t surfaces)
>> +{
>> +    AVVDPAUContext *hwctx = avctx->hwaccel_context;
>> +    struct vdpau_context *vdctx = avctx->internal->hwaccel_priv_data;
>> +    VdpDecoderCreate *create;
>> +    VdpStatus status;
>> +
>> +#if FF_API_DECODER_VDPAU
>> +    if (hwctx->device == VDP_INVALID_HANDLE) {
>> +        vdctx->decoder = hwctx->decoder;
>> +        vdctx->render = hwctx->render;
>> +        return 0; /* Decoder created by user */
>> +    }
>> +#endif
>> +
>> +    create = ff_vdpau_get_proc_address(avctx, VDP_FUNC_ID_DECODER_CREATE);
>> +
>> +    status = create(hwctx->device, profile, avctx->width, avctx->height,
>> +                    surfaces, &vdctx->decoder);
>> +    if (status != VDP_STATUS_OK)
>> +        return AVERROR(ENODEV); /* TODO: VDPAU to AV error codes */
>> +
>> +    vdctx->render = ff_vdpau_get_proc_address(avctx,
>> +                                              VDP_FUNC_ID_DECODER_RENDER);
>> +    return 0;
>> +}
>> +
>> +int ff_vdpau_common_uninit(AVCodecContext *avctx)
>> +{
>> +    struct vdpau_context *vdctx = avctx->internal->hwaccel_priv_data;
>> +    VdpDecoderDestroy *destroy;
>> +#if FF_API_DECODER_VDPAU
>> +    AVVDPAUContext *hwctx = avctx->hwaccel_context;
>> +
>> +    if (hwctx->device == VDP_INVALID_HANDLE)
>> +        return 0; /* Decoder to be destroyed by user */
>> +#endif
>> +
>> +    destroy = ff_vdpau_get_proc_address(avctx, VDP_FUNC_ID_DECODER_DESTROY);
>> +    destroy(vdctx->decoder);
>> +    return 0;
>> +}
>> +
>>  int ff_vdpau_common_start_frame(struct vdpau_picture_context *pic_ctx,
>>                                  av_unused const uint8_t *buffer,
>>                                  av_unused uint32_t size)
>> @@ -88,6 +151,7 @@ int ff_vdpau_add_buffer(struct vdpau_picture_context 
>> *pic_ctx,
>>      return 0;
>>  }
>>
>> +#if FF_API_DECODER_VDPAU
>>  int av_vdpau_get_profile(AVCodecContext *avctx, VdpDecoderProfile *profile)
>>  {
>>  #define PROFILE(prof)       \
>> @@ -133,7 +197,25 @@ do {                        \
>>
>>  AVVDPAUContext *av_vdpau_alloc_context(void)
>>  {
>> -    return av_mallocz(sizeof(AVVDPAUContext));
>> +    AVVDPAUContext *hwctx = av_mallocz(sizeof(AVVDPAUContext));
>> +    if (!hwctx)
>> +        return NULL;
>> +
>> +    hwctx->device = VDP_INVALID_HANDLE;
>> +    return hwctx;
>> +}
>> +#endif
>> +
>> +AVVDPAUContext *av_vdpau_create_context(VdpDevice device,
>> +                                        VdpGetProcAddress *get_proc_address)
>> +{
>> +    AVVDPAUContext *hwctx = av_mallocz(sizeof(AVVDPAUContext));
>> +    if (!hwctx)
>> +        return NULL;
>> +
>> +    hwctx->device = device;
>> +    hwctx->get_proc_address = get_proc_address;
>> +    return hwctx;
>>  }
>>
>>  /* @}*/
>> diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
>> index 75cb1bf..4a99834 100644
>> --- a/libavcodec/vdpau.h
>> +++ b/libavcodec/vdpau.h
>> @@ -80,11 +80,13 @@ union AVVDPAUPictureInfo {
>>   * AVVDPAUContext.
>>   */
>>  typedef struct AVVDPAUContext {
>> +#if FF_API_DECODER_VDPAU
>>      /**
>>       * VDPAU decoder handle
>>       *
>>       * Set by user.
>>       */
>> +    attribute_deprecated
>>      VdpDecoder decoder;
>>
>>      /**
>> @@ -92,8 +94,9 @@ typedef struct AVVDPAUContext {
>>       *
>>       * Set by the user.
>>       */
>> +    attribute_deprecated
>>      VdpDecoderRender *render;
>> -
>> +#endif
>>  #if FF_API_BUFS_VDPAU
>>      /**
>>       * VDPAU picture information
>> @@ -128,14 +131,32 @@ typedef struct AVVDPAUContext {
>>      attribute_deprecated
>>      VdpBitstreamBuffer *bitstream_buffers;
>>  #endif
>> +    /*****************************************************************
>> +     * No fields below this line are part of the public API. They
>> +     * may not be used outside of libavcodec and can be changed and
>> +     * removed at will.
>> +     * No new public fields will be added to this structure.
>> +     *****************************************************************
>> +     */
>> +    VdpDevice device;
>> +    VdpGetProcAddress *get_proc_address;
>>  } AVVDPAUContext;
>>
>>  /**
>> + * Create an AVVDPAUContext.
>> + *
>> + * @return Newly-allocated AVVDPAUContext or NULL on failure.
>> + */
>> +AVVDPAUContext *av_vdpau_create_context(VdpDevice device,
>> +                                        VdpGetProcAddress 
>> *get_proc_address);
>> +
>> +#if FF_API_DECODER_VDPAU
>> +/**
>>   * Allocate an AVVDPAUContext.
>>   *
>>   * @return Newly-allocated AVVDPAUContext or NULL on failure.
>>   */
>> -AVVDPAUContext *av_vdpau_alloc_context(void);
>> +attribute_deprecated AVVDPAUContext *av_vdpau_alloc_context(void);
>>
>>  /**
>>   * Get a decoder profile that should be used for initializing a VDPAU 
>> decoder.
>> @@ -148,7 +169,9 @@ AVVDPAUContext *av_vdpau_alloc_context(void);
>>   *
>>   * @return 0 on success (non-negative), a negative AVERROR on failure.
>>   */
>> +attribute_deprecated
>>  int av_vdpau_get_profile(AVCodecContext *avctx, VdpDecoderProfile *profile);
>> +#endif
>>
>>  #if FF_API_CAP_VDPAU
>>  /** @brief The videoSurface is used for rendering. */
>> diff --git a/libavcodec/vdpau_internal.h b/libavcodec/vdpau_internal.h
>> index 2443e0a..379407e 100644
>> --- a/libavcodec/vdpau_internal.h
>> +++ b/libavcodec/vdpau_internal.h
>> @@ -48,6 +48,18 @@ union AVVDPAUPictureInfo {
>>  #include "vdpau.h"
>>  #endif
>>
>> +struct vdpau_context {
>> +    /**
>> +     * VDPAU decoder handle
>> +     */
>> +    VdpDecoder decoder;
>> +
>> +    /**
>> +     * VDPAU decoder render callback
>> +     */
>> +    VdpDecoderRender *render;
>> +};
>> +
>>  struct vdpau_picture_context {
>>      /**
>>       * VDPAU picture information.
>> @@ -70,6 +82,10 @@ struct vdpau_picture_context {
>>      VdpBitstreamBuffer *bitstream_buffers;
>>  };
>>
>> +int ff_vdpau_common_init(AVCodecContext *avctx, VdpDecoderProfile profile,
>> +                         uint32_t level, uint32_t surfaces);
>> +int ff_vdpau_common_uninit(AVCodecContext *avctx);
>> +
>>  int ff_vdpau_common_start_frame(struct vdpau_picture_context *pic,
>>                                  const uint8_t *buffer, uint32_t size);
>>  int ff_vdpau_mpeg_end_frame(AVCodecContext *avctx);
>> diff --git a/libavcodec/version.h b/libavcodec/version.h
>> index 8cc2fb0..41c7fcb 100644
>> --- a/libavcodec/version.h
>> +++ b/libavcodec/version.h
>> @@ -153,5 +153,8 @@
>>  #ifndef FF_API_AFD
>>  #define FF_API_AFD               (LIBAVCODEC_VERSION_MAJOR < 57)
>>  #endif
>> +#ifndef FF_API_DECODER_VDPAU
>> +#define FF_API_DECODER_VDPAU     (LIBAVCODEC_VERSION_MAJOR < 57)
>> +#endif
>>
>>  #endif /* AVCODEC_VERSION_H */
>
>
> The idea seems generally ok (and making libavcodec handle more aspects
> of hw decoding is welcome). But I have some doubts whether it will
> still be possible for me to handle preemption as well as I could, and I
> wouldn't appreciate if a small incremental improvement breaks all of my
> code.
>
> Also, think of the API users: do they have to update their vdpau code
> every month now? WTF?
>
> A solution to this might be not deprecating the "old" API. Then
> downstreams can wait it out until the API finally becomes sane after a
> bunch of more incremental improvements. This is true for the other
> hwaccels as well (since I always hear of hwaccel 1.x...).
>
> _______________________________________________
> libav-devel mailing list
> [email protected]
> https://lists.libav.org/mailman/listinfo/libav-devel

Regards,
-- 
Gwenole Beauchesne
Intel Corporation SAS / 2 rue de Paris, 92196 Meudon Cedex, France
Registration Number (RCS): Nanterre B 302 456 199
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to