[FFmpeg-devel] [PATCH] hwaccel: add VideoToolbox support.
Michael Niedermayer
michaelni at gmx.at
Mon Sep 10 02:49:45 CEST 2012
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)
[...]
> @@ -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
> + enable vt && add_extralibs -framework CoreFoundation -framework VideoToolbox -framework CoreMedia -framework QuartzCore
> +fi
> +
> if ! disabled w32threads && ! enabled pthreads; then
> check_func _beginthreadex && enable w32threads
> fi
[...]
> 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.
[...]
> +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
> +
> + 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
[...]
> +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
[...]
> diff --git a/libavcodec/vt.h b/libavcodec/vt.h
> new file mode 100644
> index 0000000..711216e
> --- /dev/null
> +++ b/libavcodec/vt.h
> @@ -0,0 +1,185 @@
> +/*
> + * 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
> + */
> +
> +#ifndef AVCODEC_VT_H
> +#define AVCODEC_VT_H
> +
> +/**
> + * @file
> + * @ingroup lavc_codec_hwaccel_vt
> + * Public libavcodec VideoToolbox header.
> + */
> +
> +#include <stdint.h>
> +
> +#define Picture QuickdrawPicture
> +#include <VideoToolbox/VideoToolbox.h>
> +#undef Picture
> +
> +/**
> + * This structure is used to provide the necessary configurations and data
> + * to the VideoToolbox Libav HWAccel implementation.
FFmpeg HWAccel implementation
[...]
> +static int start_frame(AVCodecContext *avctx,
> + const uint8_t *buffer,
> + uint32_t size)
> +{
> + struct vt_context *vt_ctx = avctx->hwaccel_context;
> +
> + if (!vt_ctx->session)
> + return -1;
> +
> + return ff_vt_buffer_copy(vt_ctx, buffer, size);
> +}
> +
> +static int decode_slice(AVCodecContext *avctx,
> + const uint8_t *buffer,
> + uint32_t size)
> +{
> + struct vt_context *vt_ctx = avctx->hwaccel_context;
> +
> + if (!vt_ctx->session)
> + return -1;
> +
> + return 0;
> +}
> +
> +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;
> +}
> +
> +AVHWAccel ff_mpeg2_vt_hwaccel = {
> + .name = "mpeg2_vt",
> + .type = AVMEDIA_TYPE_VIDEO,
> + .id = AV_CODEC_ID_MPEG2VIDEO,
> + .pix_fmt = PIX_FMT_VT_VLD,
> + .start_frame = start_frame,
> + .end_frame = end_frame,
> + .decode_slice = decode_slice,
> +};
> diff --git a/libavcodec/vt_mpeg4.c b/libavcodec/vt_mpeg4.c
> new file mode 100644
> index 0000000..43bde56
> --- /dev/null
> +++ b/libavcodec/vt_mpeg4.c
> @@ -0,0 +1,92 @@
> +/*
> + * VideoToolbox MPEG4 / H263 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 "vt_internal.h"
> +
> +static int start_frame(AVCodecContext *avctx,
> + const uint8_t *buffer,
> + uint32_t size)
> +{
> + struct vt_context *vt_ctx = avctx->hwaccel_context;
> +
> + if (!vt_ctx->session)
> + return -1;
> +
> + return ff_vt_buffer_copy(vt_ctx, buffer, size);
> +}
> +
> +static int decode_slice(AVCodecContext *avctx,
> + const uint8_t *buffer,
> + uint32_t size)
> +{
> + struct vt_context *vt_ctx = avctx->hwaccel_context;
> +
> + if (!vt_ctx->session)
> + return -1;
> +
> + return 0;
> +}
> +
> +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
[...]
thanks!
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Concerning the gods, I have no means of knowing whether they exist or not
or of what sort they may be, because of the obscurity of the subject, and
the brevity of human life -- Protagoras
-------------- 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/20120910/92749d0e/attachment.asc>
More information about the ffmpeg-devel
mailing list