diff options
Diffstat (limited to 'libavcodec/vda_h264.c')
-rw-r--r-- | libavcodec/vda_h264.c | 198 |
1 files changed, 63 insertions, 135 deletions
diff --git a/libavcodec/vda_h264.c b/libavcodec/vda_h264.c index 037715da81..7b88ec7015 100644 --- a/libavcodec/vda_h264.c +++ b/libavcodec/vda_h264.c @@ -1,49 +1,40 @@ /* - * 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 "h264dec.h" -#include "internal.h" -#include "vda.h" -#include "vda_internal.h" - -typedef struct VDAContext { - // The current bitstream buffer. - uint8_t *bitstream; - - // The current size of the bitstream. - int bitstream_size; - - // The reference size used for fast reallocation. - int allocated_size; - CVImageBufferRef frame; -} VDAContext; +struct vda_buffer { + CVPixelBufferRef cv_buffer; +}; +#include "internal.h" +#include "vda_vt_internal.h" -/* 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 +43,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; @@ -61,7 +55,7 @@ static void vda_decoder_callback(void *vda_hw_ctx, vda_ctx->cv_buffer = CVPixelBufferRetain(image_buffer); } -static int vda_sync_decode(VDAContext *ctx, struct vda_context *vda_ctx) +static int vda_sync_decode(VTContext *ctx, struct vda_context *vda_ctx) { OSStatus status; CFDataRef coded_frame; @@ -86,8 +80,8 @@ static int vda_old_h264_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size) { - VDAContext *vda = avctx->internal->hwaccel_priv_data; - struct vda_context *vda_ctx = avctx->hwaccel_context; + VTContext *vda = avctx->internal->hwaccel_priv_data; + struct vda_context *vda_ctx = avctx->hwaccel_context; if (!vda_ctx->decoder) return -1; @@ -101,8 +95,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; + VTContext *vda = avctx->internal->hwaccel_priv_data; + struct vda_context *vda_ctx = avctx->hwaccel_context; void *tmp; if (!vda_ctx->decoder) @@ -124,12 +118,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; + VTContext *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 +144,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 +165,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,6 +175,9 @@ int ff_vda_create_decoder(struct vda_context *vda_ctx, CFMutableDictionaryRef io_surface_properties; CFNumberRef cv_pix_fmt; + 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. */ @@ -200,9 +220,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); @@ -238,15 +258,6 @@ int ff_vda_destroy_decoder(struct vda_context *vda_ctx) return status; } -static int vda_h264_uninit(AVCodecContext *avctx) -{ - VDAContext *vda = avctx->internal->hwaccel_priv_data; - av_freep(&vda->bitstream); - if (vda->frame) - CVPixelBufferRelease(vda->frame); - return 0; -} - AVHWAccel ff_h264_vda_old_hwaccel = { .name = "h264_vda", .type = AVMEDIA_TYPE_VIDEO, @@ -255,8 +266,8 @@ AVHWAccel ff_h264_vda_old_hwaccel = { .start_frame = vda_old_h264_start_frame, .decode_slice = vda_old_h264_decode_slice, .end_frame = vda_old_h264_end_frame, - .uninit = vda_h264_uninit, - .priv_data_size = sizeof(VDAContext), + .uninit = ff_videotoolbox_uninit, + .priv_data_size = sizeof(VTContext), }; void ff_vda_output_callback(void *opaque, @@ -266,7 +277,7 @@ void ff_vda_output_callback(void *opaque, CVImageBufferRef image_buffer) { AVCodecContext *ctx = opaque; - VDAContext *vda = ctx->internal->hwaccel_priv_data; + VTContext *vda = ctx->internal->hwaccel_priv_data; if (vda->frame) { @@ -280,50 +291,10 @@ void ff_vda_output_callback(void *opaque, vda->frame = CVPixelBufferRetain(image_buffer); } -static int vda_h264_start_frame(AVCodecContext *avctx, - const uint8_t *buffer, - uint32_t size) -{ - VDAContext *vda = avctx->internal->hwaccel_priv_data; - - vda->bitstream_size = 0; - - return 0; -} - -static int vda_h264_decode_slice(AVCodecContext *avctx, - const uint8_t *buffer, - uint32_t size) -{ - VDAContext *vda = avctx->internal->hwaccel_priv_data; - void *tmp; - - tmp = av_fast_realloc(vda->bitstream, - &vda->allocated_size, - vda->bitstream_size + size + 4); - if (!tmp) - return AVERROR(ENOMEM); - - vda->bitstream = tmp; - - AV_WB32(vda->bitstream + vda->bitstream_size, size); - memcpy(vda->bitstream + vda->bitstream_size + 4, buffer, size); - - vda->bitstream_size += size + 4; - - return 0; -} - -static void release_buffer(void *opaque, uint8_t *data) -{ - CVImageBufferRef frame = (CVImageBufferRef)data; - CVPixelBufferRelease(frame); -} - static int vda_h264_end_frame(AVCodecContext *avctx) { H264Context *h = avctx->priv_data; - VDAContext *vda = avctx->internal->hwaccel_priv_data; + VTContext *vda = avctx->internal->hwaccel_priv_data; AVVDAContext *vda_ctx = avctx->hwaccel_context; AVFrame *frame = h->cur_pic_ptr->f; uint32_t flush_flags = 1 << 0; ///< kVDADecoderFlush_emitFrames @@ -353,19 +324,7 @@ static int vda_h264_end_frame(AVCodecContext *avctx) return AVERROR_UNKNOWN; } - av_buffer_unref(&frame->buf[0]); - - frame->buf[0] = av_buffer_create((uint8_t*)vda->frame, - sizeof(vda->frame), - release_buffer, NULL, - AV_BUFFER_FLAG_READONLY); - if (!frame->buf[0]) - return AVERROR(ENOMEM); - - frame->data[3] = (uint8_t*)vda->frame; - vda->frame = NULL; - - return 0; + return ff_videotoolbox_buffer_create(vda, frame); } int ff_vda_default_init(AVCodecContext *avctx) @@ -384,26 +343,7 @@ int ff_vda_default_init(AVCodecContext *avctx) // kCVPixelFormatType_420YpCbCr8Planar; - /* 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) { - uint8_t *rw_extradata; - - if (!(rw_extradata = av_malloc(avctx->extradata_size))) - return AVERROR(ENOMEM); - - memcpy(rw_extradata, avctx->extradata, avctx->extradata_size); - - rw_extradata[4] |= 0x03; - - avc_data = CFDataCreate(kCFAllocatorDefault, rw_extradata, avctx->extradata_size); - - av_freep(&rw_extradata); - } else { - avc_data = CFDataCreate(kCFAllocatorDefault, - avctx->extradata, avctx->extradata_size); - } + avc_data = ff_videotoolbox_avcc_extradata_create(avctx); config_info = CFDictionaryCreateMutable(kCFAllocatorDefault, 4, @@ -471,27 +411,15 @@ int ff_vda_default_init(AVCodecContext *avctx) } } -static int vda_h264_alloc_frame(AVCodecContext *avctx, AVFrame *frame) -{ - frame->width = avctx->width; - frame->height = avctx->height; - frame->format = avctx->pix_fmt; - frame->buf[0] = av_buffer_alloc(1); - - if (!frame->buf[0]) - return AVERROR(ENOMEM); - return 0; -} - AVHWAccel ff_h264_vda_hwaccel = { .name = "h264_vda", .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_H264, .pix_fmt = AV_PIX_FMT_VDA, - .alloc_frame = vda_h264_alloc_frame, - .start_frame = vda_h264_start_frame, - .decode_slice = vda_h264_decode_slice, + .alloc_frame = ff_videotoolbox_alloc_frame, + .start_frame = ff_videotoolbox_h264_start_frame, + .decode_slice = ff_videotoolbox_h264_decode_slice, .end_frame = vda_h264_end_frame, - .uninit = vda_h264_uninit, - .priv_data_size = sizeof(VDAContext), + .uninit = ff_videotoolbox_uninit, + .priv_data_size = sizeof(VTContext), }; |