diff options
Diffstat (limited to 'libavcodec/vda_h264.c')
-rw-r--r-- | libavcodec/vda_h264.c | 96 |
1 files changed, 73 insertions, 23 deletions
diff --git a/libavcodec/vda_h264.c b/libavcodec/vda_h264.c index 62ad5e9..a1179f1 100644 --- a/libavcodec/vda_h264.c +++ b/libavcodec/vda_h264.c @@ -1,33 +1,37 @@ /* - * VDA H.264 hardware acceleration + * VDA H264 HW acceleration. * * copyright (c) 2011 Sebastien Zwickert * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * 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. * - * Libav is distributed in the hope that it will be useful, + * 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 Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <CoreFoundation/CFDictionary.h> #include <CoreFoundation/CFNumber.h> #include <CoreFoundation/CFData.h> -#include <CoreFoundation/CFString.h> +#include "vda.h" #include "libavutil/avutil.h" #include "h264.h" + +struct vda_buffer { + CVPixelBufferRef cv_buffer; +}; #include "internal.h" -#include "vda.h" #include "vda_internal.h" typedef struct VDAContext { @@ -43,7 +47,7 @@ typedef struct VDAContext { CVImageBufferRef frame; } VDAContext; -/* Decoder callback that adds the VDA frame to the queue in display order. */ +/* Decoder callback that adds the vda frame to the queue in display order. */ static void vda_decoder_callback(void *vda_hw_ctx, CFDictionaryRef user_info, OSStatus status, @@ -52,6 +56,9 @@ static void vda_decoder_callback(void *vda_hw_ctx, { struct vda_context *vda_ctx = vda_hw_ctx; + if (infoFlags & kVDADecodeInfo_FrameDropped) + vda_ctx->cv_buffer = NULL; + if (!image_buffer) return; @@ -87,7 +94,7 @@ static int vda_old_h264_start_frame(AVCodecContext *avctx, av_unused uint32_t size) { VDAContext *vda = avctx->internal->hwaccel_priv_data; - struct vda_context *vda_ctx = avctx->hwaccel_context; + struct vda_context *vda_ctx = avctx->hwaccel_context; if (!vda_ctx->decoder) return -1; @@ -101,8 +108,8 @@ static int vda_old_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) { - VDAContext *vda = avctx->internal->hwaccel_priv_data; - struct vda_context *vda_ctx = avctx->hwaccel_context; + VDAContext *vda = avctx->internal->hwaccel_priv_data; + struct vda_context *vda_ctx = avctx->hwaccel_context; void *tmp; if (!vda_ctx->decoder) @@ -124,12 +131,21 @@ static int vda_old_h264_decode_slice(AVCodecContext *avctx, return 0; } +static void vda_h264_release_buffer(void *opaque, uint8_t *data) +{ + struct vda_buffer *context = opaque; + CVPixelBufferRelease(context->cv_buffer); + av_free(context); +} + static int vda_old_h264_end_frame(AVCodecContext *avctx) { H264Context *h = avctx->priv_data; VDAContext *vda = avctx->internal->hwaccel_priv_data; struct vda_context *vda_ctx = avctx->hwaccel_context; AVFrame *frame = h->cur_pic_ptr->f; + struct vda_buffer *context; + AVBufferRef *buffer; int status; if (!vda_ctx->decoder || !vda->bitstream) @@ -141,6 +157,20 @@ static int vda_old_h264_end_frame(AVCodecContext *avctx) if (status) av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status); + if (!vda_ctx->use_ref_buffer || status) + return status; + + context = av_mallocz(sizeof(*context)); + buffer = av_buffer_create(NULL, 0, vda_h264_release_buffer, context, 0); + if (!context || !buffer) { + CVPixelBufferRelease(vda_ctx->cv_buffer); + av_free(context); + return -1; + } + + context->cv_buffer = vda_ctx->cv_buffer; + frame->buf[3] = buffer; + return status; } @@ -148,7 +178,7 @@ int ff_vda_create_decoder(struct vda_context *vda_ctx, uint8_t *extradata, int extradata_size) { - OSStatus status = kVDADecoderNoErr; + OSStatus status; CFNumberRef height; CFNumberRef width; CFNumberRef format; @@ -158,7 +188,10 @@ int ff_vda_create_decoder(struct vda_context *vda_ctx, CFMutableDictionaryRef io_surface_properties; CFNumberRef cv_pix_fmt; - /* Each VCL NAL in the bistream sent to the decoder + vda_ctx->priv_bitstream = NULL; + vda_ctx->priv_allocated_size = 0; + + /* Each VCL NAL in the bitstream sent to the decoder * is preceded by a 4 bytes length header. * Change the avcC atom header if needed, to signal headers of 4 bytes. */ if (extradata_size >= 4 && (extradata[4] & 0x03) != 0x03) { @@ -200,9 +233,9 @@ int ff_vda_create_decoder(struct vda_context *vda_ctx, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, - kCFNumberSInt32Type, - &vda_ctx->cv_pix_fmt_type); + cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, + kCFNumberSInt32Type, + &vda_ctx->cv_pix_fmt_type); CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt); @@ -241,9 +274,11 @@ int ff_vda_destroy_decoder(struct vda_context *vda_ctx) static int vda_h264_uninit(AVCodecContext *avctx) { VDAContext *vda = avctx->internal->hwaccel_priv_data; - av_freep(&vda->bitstream); - if (vda->frame) - CVPixelBufferRelease(vda->frame); + if (vda) { + av_freep(&vda->bitstream); + if (vda->frame) + CVPixelBufferRelease(vda->frame); + } return 0; } @@ -285,9 +320,20 @@ static int vda_h264_start_frame(AVCodecContext *avctx, uint32_t size) { VDAContext *vda = avctx->internal->hwaccel_priv_data; - - vda->bitstream_size = 0; - + H264Context *h = avctx->priv_data; + + if (h->is_avc == 1) { + void *tmp; + vda->bitstream_size = 0; + tmp = av_fast_realloc(vda->bitstream, + &vda->allocated_size, + size); + vda->bitstream = tmp; + memcpy(vda->bitstream, buffer, size); + vda->bitstream_size = size; + } else { + vda->bitstream_size = 0; + } return 0; } @@ -296,8 +342,12 @@ static int vda_h264_decode_slice(AVCodecContext *avctx, uint32_t size) { VDAContext *vda = avctx->internal->hwaccel_priv_data; + H264Context *h = avctx->priv_data; void *tmp; + if (h->is_avc == 1) + return 0; + tmp = av_fast_realloc(vda->bitstream, &vda->allocated_size, vda->bitstream_size + size + 4); @@ -384,7 +434,7 @@ int ff_vda_default_init(AVCodecContext *avctx) // kCVPixelFormatType_420YpCbCr8Planar; - /* Each VCL NAL in the bistream sent to the decoder + /* Each VCL NAL in the bitstream sent to the decoder * is preceded by a 4 bytes length header. * Change the avcC atom header if needed, to signal headers of 4 bytes. */ if (avctx->extradata_size >= 4 && (avctx->extradata[4] & 0x03) != 0x03) { |