From: Sebastien Zwickert <[email protected]> Support h264 accelerated decoding through MacOSX VDA framework
Signed-off-by: Luca Barbato <[email protected]> --- Changelog | 1 + configure | 8 ++ libavcodec/Makefile | 5 +- libavcodec/allcodecs.c | 1 + libavcodec/h264.c | 1 + libavcodec/vda.c | 271 +++++++++++++++++++++++++++++++++++++++++++++ libavcodec/vda.h | 140 +++++++++++++++++++++++ libavcodec/vda_h264.c | 107 ++++++++++++++++++ libavcodec/vda_internal.h | 50 ++++++++ libavutil/pixdesc.c | 6 + libavutil/pixfmt.h | 1 + 11 files changed, 590 insertions(+), 1 deletions(-) create mode 100644 libavcodec/vda.c create mode 100644 libavcodec/vda.h create mode 100644 libavcodec/vda_h264.c create mode 100644 libavcodec/vda_internal.h diff --git a/Changelog b/Changelog index d34c952..9939cbe 100644 --- a/Changelog +++ b/Changelog @@ -56,6 +56,7 @@ easier to use. The changes are: - Speex encoding via libspeex - 4:2:2 H.264 decoding support - Pulseaudio input device +- MacOSX Video Decoder Acceleration (VDA) support version 0.7: diff --git a/configure b/configure index c23660e..9b56cf9 100755 --- a/configure +++ b/configure @@ -108,6 +108,7 @@ Configuration options: --disable-mdct disable MDCT code --disable-rdft disable RDFT code --enable-vaapi enable VAAPI code + --disable-vda disable VDA code --enable-vdpau enable VDPAU code --disable-dxva2 disable DXVA2 code --enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary) @@ -974,6 +975,7 @@ CONFIG_LIST=" swscale_alpha thumb vaapi + vda vdpau version3 x11grab @@ -1290,6 +1292,7 @@ h264_decoder_select="golomb h264dsp h264pred" h264_dxva2_hwaccel_deps="dxva2api_h" h264_dxva2_hwaccel_select="dxva2 h264_decoder" h264_vaapi_hwaccel_select="vaapi" +h264_vda_hwaccel_select="vda" h264_vdpau_decoder_select="vdpau h264_decoder" imc_decoder_select="fft mdct sinewin" jpegls_decoder_select="golomb" @@ -1386,6 +1389,7 @@ zmbv_decoder_select="zlib" zmbv_encoder_select="zlib" vaapi_deps="va_va_h" +vda_deps="VideoDecodeAcceleration_VDADecoder_h" vdpau_deps="vdpau_vdpau_h vdpau_vdpau_x11_h" # parsers @@ -2833,6 +2837,7 @@ check_header sys/resource.h check_header sys/select.h check_header vdpau/vdpau.h check_header vdpau/vdpau_x11.h +check_header VideoDecodeAcceleration/VDADecoder.h check_header X11/extensions/XvMClib.h check_struct dxva2api.h DXVA_PictureParameters wDecodedPictureIndex @@ -2975,6 +2980,8 @@ check_func XOpenDisplay -lX11 && check_func XShmCreateImage -lX11 -lXext && check_func XFixesGetCursorImage -lX11 -lXext -lXfixes +enabled vda && add_ldflags -framework CoreFoundation -framework VideoDecodeAcceleration -framework QuartzCore + if ! disabled vdpau && enabled vdpau_vdpau_h; then check_cpp_condition \ vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" || @@ -2982,6 +2989,7 @@ check_cpp_condition \ disable vdpau; } fi + enabled debug && add_cflags -g"$debuglevel" && add_asflags -g"$debuglevel" # add some useful compiler flags if supported diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 421072e..3211ea6 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1,7 +1,7 @@ NAME = avcodec FFLIBS = avutil -HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vdpau.h version.h xvmc.h +HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vda.h vdpau.h version.h xvmc.h OBJS = allcodecs.o \ audioconvert.o \ @@ -45,6 +45,7 @@ RDFT-OBJS-$(CONFIG_HARDCODED_TABLES) += sin_tables.o OBJS-$(CONFIG_RDFT) += rdft.o $(RDFT-OBJS-yes) OBJS-$(CONFIG_SINEWIN) += sinewin.o OBJS-$(CONFIG_VAAPI) += vaapi.o +OBJS-$(CONFIG_VDA) += vda.o OBJS-$(CONFIG_VDPAU) += vdpau.o # decoders/encoders/hardware accelerators @@ -178,6 +179,7 @@ OBJS-$(CONFIG_H264_DECODER) += h264.o \ mpegvideo.o error_resilience.o OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o +OBJS-$(CONFIG_H264_VDA_HWACCEL) += vda_h264.o OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o @@ -666,6 +668,7 @@ SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h SKIPHEADERS-$(CONFIG_LIBDIRAC) += libdirac.h SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h +SKIPHEADERS-$(CONFIG_VDA) += vda_internal.h SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h SKIPHEADERS-$(HAVE_W32THREADS) += w32pthreads.h diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 23d2252..4d908ee 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -57,6 +57,7 @@ void avcodec_register_all(void) REGISTER_HWACCEL (H263_VAAPI, h263_vaapi); REGISTER_HWACCEL (H264_DXVA2, h264_dxva2); REGISTER_HWACCEL (H264_VAAPI, h264_vaapi); + REGISTER_HWACCEL (H264_VDA, h264_vda); REGISTER_HWACCEL (MPEG2_DXVA2, mpeg2_dxva2); REGISTER_HWACCEL (MPEG2_VAAPI, mpeg2_vaapi); REGISTER_HWACCEL (MPEG4_VAAPI, mpeg4_vaapi); diff --git a/libavcodec/h264.c b/libavcodec/h264.c index f7c52cd..f863573 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -56,6 +56,7 @@ static const uint8_t div6[QP_MAX_NUM+1]={ static const enum PixelFormat hwaccel_pixfmt_list_h264_jpeg_420[] = { PIX_FMT_DXVA2_VLD, PIX_FMT_VAAPI_VLD, + PIX_FMT_VDA_VLD, PIX_FMT_YUVJ420P, PIX_FMT_NONE }; diff --git a/libavcodec/vda.c b/libavcodec/vda.c new file mode 100644 index 0000000..5dd1f27 --- /dev/null +++ b/libavcodec/vda.c @@ -0,0 +1,271 @@ +/* + * VDA HW 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 "vda_internal.h" + +/** + * \addtogroup VDA_Decoding + * + * @{ + */ + +/* Mutex manager callback. */ +static int vda_lock_operation(void **mtx, enum AVLockOp op) +{ + switch(op) + { + case AV_LOCK_CREATE: + *mtx = av_malloc(sizeof(pthread_mutex_t)); + if(!*mtx) + return 1; + return !!pthread_mutex_init(*mtx, NULL); + case AV_LOCK_OBTAIN: + return !!pthread_mutex_lock(*mtx); + case AV_LOCK_RELEASE: + return !!pthread_mutex_unlock(*mtx); + case AV_LOCK_DESTROY: + pthread_mutex_destroy(*mtx); + av_freep(mtx); + return 0; + } + return 1; +} + +/* Helper to create a dictionary according to the given pts. */ +static CFDictionaryRef vda_dictionary_with_pts(int64_t i_pts) +{ + CFStringRef key = CFSTR("FF_VDA_DECODER_PTS_KEY"); + CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &i_pts); + CFDictionaryRef user_info = CFDictionaryCreate( kCFAllocatorDefault, + (const void **)&key, + (const void **)&value, + 1, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFRelease(value); + return user_info; +} + +/* Helper to retrieve the pts from the given dictionary. */ +static int64_t vda_pts_from_dictionary(CFDictionaryRef user_info) +{ + CFNumberRef pts; + int64_t outValue = 0; + + if (NULL == user_info) + return 0; + + pts = CFDictionaryGetValue(user_info, CFSTR("FF_VDA_DECODER_PTS_KEY")); + + if (pts) + CFNumberGetValue(pts, kCFNumberSInt64Type, &outValue); + + return outValue; +} + +/* Removes and releases all frames from the queue. */ +static void vda_clear_queue(struct vda_context *vda_ctx) +{ + vda_frame *top_frame; + + vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_OBTAIN); + + while (vda_ctx->queue != NULL) + { + top_frame = vda_ctx->queue; + vda_ctx->queue = top_frame->next_frame; + ff_vda_release_vda_frame(top_frame); + } + + vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_RELEASE); +} + + +/* 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, + uint32_t infoFlags, + CVImageBufferRef image_buffer) +{ + struct vda_context *vda_ctx = (struct vda_context*)vda_hw_ctx; + vda_frame *new_frame; + vda_frame *queue_walker; + + if (NULL == image_buffer) + return; + + if (kCVPixelFormatType_422YpCbCr8 != CVPixelBufferGetPixelFormatType(image_buffer)) + return; + + new_frame = (vda_frame *)av_mallocz(sizeof(vda_frame)); + new_frame->next_frame = NULL; + new_frame->cv_buffer = CVPixelBufferRetain(image_buffer); + new_frame->pts = vda_pts_from_dictionary(user_info); + + vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_OBTAIN); + + queue_walker = vda_ctx->queue; + + if (!queue_walker || (new_frame->pts < queue_walker->pts)) + { + /* we have an empty queue, or this frame earlier than the current queue head */ + new_frame->next_frame = queue_walker; + vda_ctx->queue = new_frame; + } + else + { + /* walk the queue and insert this frame where it belongs in display order */ + vda_frame *next_frame; + + while (1) + { + next_frame = queue_walker->next_frame; + + if (!next_frame || (new_frame->pts < next_frame->pts)) + { + new_frame->next_frame = next_frame; + queue_walker->next_frame = new_frame; + break; + } + queue_walker = next_frame; + } + } + + vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_RELEASE); +} + +int ff_vda_create_decoder(struct vda_context *vda_ctx, + uint8_t *extradata, + int extradata_size) +{ + OSStatus status = kVDADecoderNoErr; + CFNumberRef height; + CFNumberRef width; + CFNumberRef format; + CFDataRef avc_data; + CFMutableDictionaryRef config_info; + + if (av_lockmgr_register(vda_lock_operation)) + return -1; + + vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_CREATE); + + config_info = (CFDictionaryCreateMutable(kCFAllocatorDefault, + 4, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + + height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->height); + width = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->width); + format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->format); + avc_data = CFDataCreate(kCFAllocatorDefault, extradata, extradata_size); + + CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height); + CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width); + CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format); + CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data); + + status = VDADecoderCreate( config_info, + NULL, + (VDADecoderOutputCallback *)vda_decoder_callback, + (void *)vda_ctx, + &vda_ctx->decoder ); + + CFRelease(height); + CFRelease(width); + CFRelease(format); + CFRelease(avc_data); + CFRelease(config_info); + + if (kVDADecoderNoErr != status) + return status; + + return 0; +} + +int ff_vda_destroy_decoder(struct vda_context *vda_ctx) +{ + OSStatus status = kVDADecoderNoErr; + + if (vda_ctx->decoder) + status = VDADecoderDestroy(vda_ctx->decoder); + + vda_clear_queue(vda_ctx); + + if (vda_ctx->queue_mutex != NULL) + vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_DESTROY); + + if (kVDADecoderNoErr != status) + return status; + + return 0; +} + +vda_frame *ff_vda_queue_pop(struct vda_context *vda_ctx) +{ + vda_frame *top_frame; + + if (!vda_ctx->queue) + return NULL; + + vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_OBTAIN); + top_frame = vda_ctx->queue; + vda_ctx->queue = top_frame->next_frame; + vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_RELEASE); + + return top_frame; +} + +void ff_vda_release_vda_frame(vda_frame *frame) +{ + if (frame != NULL) + { + CVPixelBufferRelease(frame->cv_buffer); + av_freep(&frame); + } +} + +int ff_vda_decoder_decode(struct vda_context *vda_ctx, + uint8_t *bitstream, + int bitstream_size, + int64_t frame_pts) +{ + OSStatus status = kVDADecoderNoErr; + CFDictionaryRef user_info; + CFDataRef coded_frame; + + coded_frame = CFDataCreate(kCFAllocatorDefault, bitstream, bitstream_size); + user_info = vda_dictionary_with_pts(frame_pts); + + status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, user_info); + + CFRelease(user_info); + CFRelease(coded_frame); + + if (kVDADecoderNoErr != status) + return status; + + return 0; +} + +/* @} */ diff --git a/libavcodec/vda.h b/libavcodec/vda.h new file mode 100644 index 0000000..ab6a8d4 --- /dev/null +++ b/libavcodec/vda.h @@ -0,0 +1,140 @@ +/* + * VDA HW 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 + */ + +#ifndef AVCODEC_VDA_H +#define AVCODEC_VDA_H + +#include <stdint.h> + +// emmintrin.h is unable to compile with -std=c99 -Werror=missing-prototypes +// http://openradar.appspot.com/8026390 +#undef __GNUC_STDC_INLINE__ + +#define Picture QuickdrawPicture + +#include <pthread.h> +#include "avcodec.h" +#include <VideoDecodeAcceleration/VDADecoder.h> + +/** + * This structure is used to store a decoded frame information and data. + */ +typedef struct +{ + /** + * The PTS of the frame. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + int64_t pts; + + /** + * The CoreVideo buffer that contains the decoded data. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + CVPixelBufferRef cv_buffer; + + /** + * A pointer to the next frame. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + struct vda_frame *next_frame; + +} vda_frame; + +/** + * This structure is used to provide the necessary configurations and data + * to the VDA Libav HWAccel implementation. + * + * The application must make it available as AVCodecContext.hwaccel_context. + */ +struct vda_context { + + /** + * VDA decoder object. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + VDADecoder decoder; + + /** + * VDA frames queue ordered by presentation timestamp. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + vda_frame *queue; + + /** + * Mutex for locking queue operations. + * + * - encoding: unused + * - decoding: Set/Unset by libavcodec. + */ + void *queue_mutex; + + /** + * The frame width. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + int width; + + /** + * The frame height. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + int height; + + /** + * The frame format. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + int format; +}; + +/** Creates the video decoder. */ +int ff_vda_create_decoder(struct vda_context *vda_ctx, + uint8_t *extradata, + int extradata_size); + +/** Destroys the video decoder. */ +int ff_vda_destroy_decoder(struct vda_context *vda_ctx); + +/** Returns the top frame of the queue. */ +vda_frame *ff_vda_queue_pop(struct vda_context *vda_ctx); + +/** Releases the given frame. */ +void ff_vda_release_vda_frame(vda_frame *frame); + +#endif /* AVCODEC_VDA_H */ diff --git a/libavcodec/vda_h264.c b/libavcodec/vda_h264.c new file mode 100644 index 0000000..2433d62 --- /dev/null +++ b/libavcodec/vda_h264.c @@ -0,0 +1,107 @@ +/* + * VDA H264 HW 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 "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 = (AVFrame*)h->s.current_picture_ptr; + 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), +}; diff --git a/libavcodec/vda_internal.h b/libavcodec/vda_internal.h new file mode 100644 index 0000000..6b7f531 --- /dev/null +++ b/libavcodec/vda_internal.h @@ -0,0 +1,50 @@ +/* + * VDA HW 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 + */ + +#ifndef AVCODEC_VDA_INTERNAL_H +#define AVCODEC_VDA_INTERNAL_H + +#include "h264.h" +#include "h264data.h" + +#include "vda.h" + +#include <CoreFoundation/CFDictionary.h> +#include <CoreFoundation/CFNumber.h> +#include <CoreFoundation/CFData.h> +#include <CoreFoundation/CFString.h> + +/** + * \addtogroup VDA_Decoding + * + * @{ + */ + +/** Send a frame data to the hardware decoder. */ +int ff_vda_decoder_decode(struct vda_context *vda_ctx, + uint8_t *bitstream, + int bitstream_size, + int64_t frame_pts); + +/* @} */ + +#endif /* AVCODEC_VDA_INTERNAL_H */ diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index f7df0eb..e0616df 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -740,6 +740,12 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[PIX_FMT_NB] = { .log2_chroma_h = 1, .flags = PIX_FMT_HWACCEL, }, + [PIX_FMT_VDA_VLD] = { + .name = "vda_vld", + .log2_chroma_w = 1, + .log2_chroma_h = 1, + .flags = PIX_FMT_HWACCEL, + }, [PIX_FMT_YUV420P9LE] = { .name = "yuv420p9le", .nb_components= 3, diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index 7068b43..6d01bb6 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -147,6 +147,7 @@ enum PixelFormat { PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian + PIX_FMT_VDA_VLD, ///< HW decoding through VDA. PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions }; -- 1.7.7 _______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
