[FFmpeg-devel] [PATCH]: Video Decoder Acceleration (VDA) HWAccel module for Mac OS X

Michael Niedermayer michaelni at gmx.at
Tue Nov 1 20:15:03 CET 2011


On Tue, Nov 01, 2011 at 05:39:30PM +0100, Sebastien Zwickert wrote:
> 
> On Nov 1, 2011, at 4:43 PM, Carl Eugen Hoyos wrote:
> 
> > Sebastien Zwickert <dilaroga <at> gmail.com> writes:
> > 
> >> Change done in the upated patch in attachment.
> > 
> > Please bump libavutil and libavcodec version number and please add a line to the
> > Changelog.
> 
> Done. patch updated.
> 
> Best regards,
> 
> Sebastien.
> 

[...]

> +/* Mutex manager callback. */
> +static int ff_vda_lock_operation(void **mtx, enum AVLockOp op)

the ff prefix is normally used for non static private functions
within one library in ffmpeg.


> +{
> +    switch(op) {
> +        case AV_LOCK_CREATE:
> +            *mtx = av_malloc(sizeof(pthread_mutex_t));
> +            if(!*mtx)
> +                return 1;
> +            return !!pthread_mutex_init(*mtx, NULL);
> +        case AV_LOCK_OBTAIN:
> +            return !!pthread_mutex_lock(*mtx);
> +        case AV_LOCK_RELEASE:
> +            return !!pthread_mutex_unlock(*mtx);
> +        case AV_LOCK_DESTROY:
> +            pthread_mutex_destroy(*mtx);

> +            av_free(*mtx);

av_freep() is a bit safer as it zeros mtx


[...]
> +/* Removes and releases all frames from the queue. */
> +static void ff_vda_clear_queue(struct vda_context *vda_ctx)
> +{
> +    vda_frame *top_frame;
> +    top_frame = NULL;
> +
> +    ff_vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_OBTAIN);
> +
> +    while (vda_ctx->queue != NULL)
> +    {
> +        top_frame = vda_ctx->queue;

> +        vda_ctx->queue = (vda_frame *)top_frame->next_frame;

the cast should be unneeded, the type seems to be matching


> +        vda_ctx->queue_depth--;
> +        ff_vda_release_vda_frame(top_frame);
> +    }
> +
> +    ff_vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_RELEASE);
> +}
> +
> +
> +/* Decoder callback that adds the vda frame to the queue in display order. */
> +static void ff_vda_decoder_callback (void *vda_hw_ctx,
> +                                     CFDictionaryRef user_info,
> +                                     OSStatus status,
> +                                     uint32_t infoFlags,
> +                                     CVImageBufferRef image_buffer)
> +{
> +    struct vda_context *vda_ctx = (struct vda_context*)vda_hw_ctx;
> +    vda_frame *new_frame = NULL;
> +    vda_frame *queue_walker = NULL;
> +
> +    if (NULL == image_buffer)
> +        return;
> +
> +    if (kCVPixelFormatType_422YpCbCr8 != CVPixelBufferGetPixelFormatType(image_buffer))
> +        return;
> +

> +    new_frame = (vda_frame *)calloc(sizeof(vda_frame), 1);

this probably should be av_mallocz()
av_free() cannot be used on calloced() data



> +    new_frame->next_frame = NULL;
> +    new_frame->cv_buffer = CVPixelBufferRetain(image_buffer);
> +    new_frame->pts = ff_vda_pts_from_dictionary(user_info);
> +
> +    ff_vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_OBTAIN);
> +
> +    queue_walker = vda_ctx->queue;
> +
> +    if (!queue_walker || (new_frame->pts < queue_walker->pts))
> +    {
> +        /* we have an empty queue, or this frame earlier than the current queue head */
> +        new_frame->next_frame = queue_walker;
> +        vda_ctx->queue = new_frame;
> +    }
> +    else
> +    {
> +        /* walk the queue and insert this frame where it belongs in display order */
> +        bool inserted = false;

> +        vda_frame *next_frame = NULL;

the variable is always written before read so the init is unneeded


> +
> +        while (!inserted)
> +        {
> +            next_frame = queue_walker->next_frame;
> +
> +            if (!next_frame || (new_frame->pts < next_frame->pts))
> +            {
> +                new_frame->next_frame = next_frame;
> +                queue_walker->next_frame = new_frame;

> +                inserted = true;

using break; here would avoid the need for the "inserted" variable


[...]
> +vda_frame *ff_vda_queue_pop(struct vda_context *vda_ctx)
> +{
> +    if (!vda_ctx->queue_depth)
> +        return NULL;

this is the only case where queue_depth is read, can it be replaced
by a   vda_ctx->queue == NULL check ?
if so you could remove the queue_depth variable and all code
maintaining its value


[...]
> +static int decode_slice(AVCodecContext *avctx,
> +                        const uint8_t *buffer,
> +                        uint32_t size)
> +{
> +    H264Context *h = avctx->priv_data;
> +    struct vda_context *vda_ctx = avctx->hwaccel_context;
> +    struct vda_picture_context *pic_ctx = h->s.current_picture_ptr->f.hwaccel_picture_private;
> +    void *tmp;
> +
> +    if (!vda_ctx->decoder)
> +        return -1;
> +

> +    tmp = NULL;
> +    tmp = av_realloc(pic_ctx->bitstream, pic_ctx->bitstream_size+size+4);

the tmp = NULL is unneeded
also please consider using *av_fast_realloc() if its possible in this
case here as its faster (*alloc is actually slow, so never downsizing
and instead reusing buffers is faster)


> +    if (!tmp)
> +        return AVERROR(ENOMEM);
> +
> +    pic_ctx->bitstream = tmp;
> +
> +    AV_WB32(pic_ctx->bitstream+pic_ctx->bitstream_size, size);
> +    memcpy(pic_ctx->bitstream+pic_ctx->bitstream_size+4, buffer, size);
> +
> +    pic_ctx->bitstream_size += size + 4;
> +
> +    return 0;
> +}
> +
> +static int end_frame(AVCodecContext *avctx)
> +{
> +    H264Context *h = avctx->priv_data;
> +    struct vda_context *vda_ctx = avctx->hwaccel_context;
> +    struct vda_picture_context *pic_ctx = h->s.current_picture_ptr->f.hwaccel_picture_private;
> +    AVFrame *frame = (AVFrame*)h->s.current_picture_ptr;
> +    int status;
> +
> +    if (!vda_ctx->decoder || !pic_ctx->bitstream)
> +        return -1;
> +
> +    status = ff_vda_decoder_decode(vda_ctx, pic_ctx->bitstream,
> +                                   pic_ctx->bitstream_size,
> +                                   frame->reordered_opaque);
> +
> +    if (status)
> +        av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
> +
> +    av_free(pic_ctx->bitstream);

av_freep() is safer (against double free bugs for example)


[...]

also, if you want to maintain this code in ffmpeg,
please add yourself to the MAINTAINERS file


-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Breaking DRM is a little like attempting to break through a door even
though the window is wide open and the only thing in the house is a bunch
of things you dont want and which you would get tomorrow for free anyway
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20111101/c24c15e8/attachment.asc>


More information about the ffmpeg-devel mailing list