summaryrefslogtreecommitdiff
path: root/libavcodec/vda_h264.c
diff options
context:
space:
mode:
authorSebastien Zwickert <dilaroga@free.fr>2011-11-11 15:48:21 +0100
committerLuca Barbato <lu_zero@gentoo.org>2011-11-14 16:07:32 +0100
commitac3dbb4d5854e8884daca54fd1f187b7f3769183 (patch)
treede5de3a39c3a0401bde790a58ad0bdeeacfe9707 /libavcodec/vda_h264.c
parentd8a091698af2a80495b7a4377253781080946380 (diff)
hwaccel: OS X Video Decoder Acceleration (VDA) support.
Signed-off-by: Luca Barbato <lu_zero@gentoo.org>
Diffstat (limited to 'libavcodec/vda_h264.c')
-rw-r--r--libavcodec/vda_h264.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/libavcodec/vda_h264.c b/libavcodec/vda_h264.c
new file mode 100644
index 0000000000..c9022673fc
--- /dev/null
+++ b/libavcodec/vda_h264.c
@@ -0,0 +1,110 @@
+/*
+ * VDA H.264 hardware acceleration
+ *
+ * copyright (c) 2011 Sebastien Zwickert
+ *
+ * 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 "h264.h"
+#include "h264data.h"
+
+#include "vda_internal.h"
+
+/* This structure is used to store the bitstream of the current frame. */
+struct vda_picture_context {
+ uint8_t *bitstream;
+ int bitstream_size;
+};
+
+static int start_frame(AVCodecContext *avctx,
+ av_unused const uint8_t *buffer,
+ av_unused uint32_t size)
+{
+ const 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;
+
+ if (!vda_ctx->decoder)
+ return -1;
+
+ pic_ctx->bitstream = NULL;
+ pic_ctx->bitstream_size = 0;
+
+ return 0;
+}
+
+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 = av_realloc(pic_ctx->bitstream, pic_ctx->bitstream_size+size+4);
+ 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 = &h->s.current_picture_ptr->f;
+ 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_freep(&pic_ctx->bitstream);
+
+ return status;
+}
+
+AVHWAccel ff_h264_vda_hwaccel = {
+ .name = "h264_vda",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = CODEC_ID_H264,
+ .pix_fmt = PIX_FMT_VDA_VLD,
+ .capabilities = 0,
+ .start_frame = start_frame,
+ .decode_slice = decode_slice,
+ .end_frame = end_frame,
+ .priv_data_size = sizeof(struct vda_picture_context),
+};