[FFmpeg-devel] [PATCH] hwaccel: add VideoToolbox support.
Sebastien Zwickert
dilaroga at gmail.com
Thu Sep 13 15:40:15 CEST 2012
Hello,
On Sep 10, 2012, at 2:49 AM, Michael Niedermayer <michaelni at gmx.at> wrote:
> Hi Sebastien
>
> On Sun, Sep 09, 2012 at 11:28:19AM +0200, Sebastien Zwickert wrote:
> [...]
>
>> diff --git a/configure b/configure
>> index 7fac4e9..ff49eec 100755
>> --- a/configure
>> +++ b/configure
>> @@ -133,6 +133,7 @@ Component options:
>> --enable-dxva2 enable DXVA2 code
>> --enable-vaapi enable VAAPI code [autodetect]
>> --enable-vda enable VDA code [autodetect]
>> + --enable-vt enable VideoToolbox code [autodetect]
>> --enable-vdpau enable VDPAU code [autodetect]
>>
>> Individual component options:
>> @@ -1171,6 +1172,7 @@ CONFIG_LIST="
>> thumb
>> vaapi
>> vda
>> + vt
>> vdpau
>> version3
>> xmm_clobber_test
>
> nit++ alphabetical order (also at various other places)
Fixed.
> [...]
>
>> @@ -3532,6 +3539,11 @@ if ! disabled vda; then
>> fi
>> fi
>>
>> +# check for VideoToolbox header
>> +if ! disabled vda && check_header VideoToolbox/VideoToolbox.h; then
>
> vda is wrong here i suspect
Ooops. Fixed!
> [...]
>> new file mode 100644
>> index 0000000..d8b9e0f
>> --- /dev/null
>> +++ b/libavcodec/vt.c
>> @@ -0,0 +1,388 @@
>> +/*
>> + * VideoToolbox hardware acceleration
>> + *
>> + * copyright (c) 2012 Sebastien Zwickert
>> + *
>> + * This file is part of FFmpeg.
>> + *
>> + * FFmpeg 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.
>> + *
>> + * FFmpeg 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 FFmpeg; if not, write to the Free Software
>> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>> + */
>> +
>> +#include "libavutil/avutil.h"
>> +#include "vt_internal.h"
>> +
>
>> +static int vt_write_mp4_descr_length(PutBitContext *pb, int length, int compact)
>
> compact is 0 on all calls, is it intended to have both variants
> implemented but just one used ?
>
>
>> +{
>> + int i;
>> + uint8_t b;
>> + int nb;
>> +
>> + if (compact) {
>> + if (length <= 0x7F)
>> + nb = 1;
>> + else if (length <= 0x3FFF)
>> + nb = 2;
>> + else if (length <= 0x1FFFFF)
>> + nb = 3;
>> + else
>> + nb = 4;
>> + }
>> + else
>> + nb = 4;
>> +
>> + for (i = nb-1; i >= 0; i--) {
>> + b = (length >> (i * 7)) & 0x7F;
>> + if (i != 0) {
>> + b |= 0x80;
>> + }
>> + put_bits(pb, 8, b);
>> + }
>> +
>> + return nb;
>> +}
>> +
>> +static CFDataRef vt_esds_extradata_create(uint8_t *extradata, int size)
>> +{
>> + CFDataRef data;
>> + uint8_t *rw_extradata;
>> + PutBitContext pb;
>> + int full_size = 3 + (5 + (13 + (5 + size))) + 3;
>> + int config_size = 13 + 5 + size;
>> + int padding = 12;
>> + int s, i = 0;
>> +
>> + if (!(rw_extradata = av_mallocz(sizeof(uint8_t)*(full_size+padding))))
>> + return NULL;
>> +
>> + init_put_bits(&pb, rw_extradata, full_size+padding);
>> + put_bits(&pb, 8, 0); ///< version
>> + put_bits(&pb, 24, 0); ///< flags
>> +
>> + // elementary stream descriptor
>> + put_bits(&pb, 8, 0x03); ///< ES_DescrTag
>> + vt_write_mp4_descr_length(&pb, full_size, 0);
>> + put_bits(&pb, 16, 0); ///< esid
>> + put_bits(&pb, 8, 0); ///< stream priority (0-32)
>> +
>> + // decoder configuration descriptor
>> + put_bits(&pb, 8, 0x04); ///< DecoderConfigDescrTag
>> + vt_write_mp4_descr_length(&pb, config_size, 0);
>> + put_bits(&pb, 8, 32); ///< object type indication. 32 = CODEC_ID_MPEG4
>> + put_bits(&pb, 8, 0x11); ///< stream type
>> + put_bits(&pb, 24, 0); ///< buffer size
>> + put_bits32(&pb, 0); ///< max bitrate
>> + put_bits32(&pb, 0); ///< avg bitrate
>> +
>> + // decoder specific descriptor
>> + put_bits(&pb, 8, 0x05); ///< DecSpecificInfoTag
>> + vt_write_mp4_descr_length(&pb, size, 0);
>> + for (i = 0; i < size; i++)
>> + put_bits(&pb, 8, extradata[i]);
>> +
>> + // SLConfigDescriptor
>> + put_bits(&pb, 8, 0x06); ///< SLConfigDescrTag
>> + put_bits(&pb, 8, 0x01); ///< length
>> + put_bits(&pb, 8, 0x02); ///<
>> +
>> + flush_put_bits(&pb);
>> + s = put_bits_count(&pb) / 8;
>
> all the written values are in multiples of 8 bit, the code should be
> slightly simpler if it uses the bytestream API for this
>
> also some of this smells like duplicate relative to the mp4 code
> but i suspect factorizing this may be quite hard so this is more a
> note than a suggestion to change it unless you see an easy way to
> factorize it.
Thanks to you for the note. I did success in factorizing this. I only have to export publicly
the esds writing function for that. Maybe be should I split this part in a dedicated patch ?
> [...]
>> +int ff_vt_buffer_copy(struct vt_context *vt_ctx, const uint8_t *buffer, uint32_t size)
>> +{
>> + void *tmp;
>> + tmp = av_fast_realloc(vt_ctx->priv_bitstream,
>> + &vt_ctx->priv_allocated_size,
>> + size);
>> + if (!tmp)
>> + return AVERROR(ENOMEM);
>> +
>> + vt_ctx->priv_bitstream = tmp;
>> +
>> + memcpy(vt_ctx->priv_bitstream, buffer, size);
>
> if the buffers contents are completely overwritten then you dont
> need realloc. av_fast_malloc() should be faster
> there also can be alignment sub optimalities with realloc
Done.
Thanks to you for explanations.
>> +
>> + vt_ctx->priv_bitstream_size = size;
>> +
>> + return 0;
>> +}
>> +
>> +void ff_vt_end_frame(MpegEncContext *s)
>> +{
>> + struct vt_context * const vt_ctx = s->avctx->hwaccel_context;
>> + AVFrame *frame = &s->current_picture_ptr->f;
>> +
>> + frame->data[3] = (void*)vt_ctx->cv_buffer;
>> +}
>> +
>> +int ff_vt_session_create(struct vt_context *vt_ctx,
>> + CMVideoFormatDescriptionRef fmt_desc,
>> + CFDictionaryRef decoder_spec,
>> + CFDictionaryRef buf_attr)
>
> tabs arent allowed in ffmpeg git
Tabs removed.
> [...]
>> +void ff_vt_session_invalidate(struct vt_context *vt_ctx)
>> +{
>> + if (vt_ctx->cm_fmt_desc)
>> + CFRelease(vt_ctx->cm_fmt_desc);
>> +
>> + if (vt_ctx->session)
>> + VTDecompressionSessionInvalidate(vt_ctx->session);
>> +
>
>> + av_freep(&vt_ctx->priv_bitstream);
>
> i would suggest to pair all freeing of priv_bitstream, with setting
> its length to 0. It might be redundant but its more robust from a
> security standpoint
Thx. Done.
> [...]
>> […]
>> +
>> +static int end_frame(AVCodecContext *avctx)
>> +{
>> + struct vt_context *vt_ctx = avctx->hwaccel_context;
>> + int status;
>> +
>> + if (!vt_ctx->session || !vt_ctx->priv_bitstream)
>> + return -1;
>> +
>> + status = ff_vt_session_decode_frame(vt_ctx);
>> +
>> + if (status) {
>> + av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
>> + return status;
>> + }
>> +
>> + ff_vt_end_frame(avctx->priv_data);
>> +
>> + return status
>
> duplicates
> These can be moved to a common file and used from there
Done.
> [...]
>
> thanks!
Thanks to you for reviewing this patch. I'll send an updated patch where I fixed some comments syntax,
code style, typo, cosmetics and I give a name more readable in the configure (videotoolbox instead of vt).
Best regards,
--
Sebastien Zwickert
More information about the ffmpeg-devel
mailing list