diff --git a/Changelog b/Changelog index c6d88b6cec..0bbeae77fc 100644 --- a/Changelog +++ b/Changelog @@ -70,6 +70,7 @@ easier to use. The changes are: - 4:2:2 H.264 decoding support - Pulseaudio input device - Prores encoder +- Video Decoder Acceleration (VDA) HWAccel module. version 0.8: diff --git a/MAINTAINERS b/MAINTAINERS index e9803f3f55..829dfe1a0b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -237,6 +237,7 @@ Hardware acceleration: dxva2* Laurent Aimar libstagefright.cpp Mohamed Naufal vaapi* Gwenole Beauchesne + vda* Sebastien Zwickert vdpau* Carl Eugen Hoyos diff --git a/configure b/configure index e688f587cc..279e4167d7 100755 --- a/configure +++ b/configure @@ -111,6 +111,7 @@ Configuration options: --enable-vaapi enable VAAPI code [autodetect] --enable-vdpau enable VDPAU code [autodetect] --disable-dxva2 disable DXVA2 code + --disable-vda disable VDA code --enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary) --enable-hardcoded-tables use hardcoded tables instead of runtime generation --enable-memalign-hack emulate memalign, interferes with memory debuggers @@ -1052,6 +1053,7 @@ CONFIG_LIST=" swscale_alpha thumb vaapi + vda vdpau version3 x11grab @@ -1377,6 +1379,8 @@ h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser" h264_dxva2_hwaccel_deps="dxva2api_h" h264_dxva2_hwaccel_select="dxva2 h264_decoder" h264_vaapi_hwaccel_select="vaapi" +h264_vda_hwaccel_deps="VideoDecodeAcceleration_VDADecoder_h" +h264_vda_hwaccel_select="vda" h264_vdpau_decoder_select="vdpau h264_decoder" imc_decoder_select="fft mdct sinewin" jpegls_decoder_select="golomb" @@ -2955,6 +2959,7 @@ check_func_headers windows.h MapViewOfFile check_func_headers windows.h VirtualAlloc check_header dlfcn.h +check_header VideoDecodeAcceleration/VDADecoder.h check_header dxva2api.h -D_WIN32_WINNT=0x0600 check_header libcrystalhd/libcrystalhd_if.h check_header malloc.h @@ -2970,6 +2975,11 @@ check_header X11/extensions/XvMClib.h disabled zlib || check_lib zlib.h zlibVersion -lz || disable zlib disabled bzlib || check_lib2 bzlib.h BZ2_bzlibVersion -lbz2 || disable bzlib +# adds ldflags for VDA module +if enabled vda; then + add_ldflags -framework CoreFoundation -framework VideoDecodeAcceleration -framework QuartzCore +fi + # check for some common methods of building with pthread support # do this before the optional library checks as some of them require pthreads if ! disabled pthreads && ! enabled w32threads; then diff --git a/libavcodec/Makefile b/libavcodec/Makefile index b2c0c99214..0178f8fc6e 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -3,7 +3,7 @@ include $(SUBDIR)../config.mak 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 \ @@ -49,6 +49,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 @@ -192,6 +193,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 @@ -703,6 +705,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 1119dd1e7e..7ba2ab3f89 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 (MPEG1_VDPAU, mpeg1_vdpau); REGISTER_HWACCEL (MPEG2_DXVA2, mpeg2_dxva2); REGISTER_HWACCEL (MPEG2_VAAPI, mpeg2_vaapi); diff --git a/libavcodec/h264.c b/libavcodec/h264.c index 3302f71993..3f6bc7290b 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/mpegvideo.c b/libavcodec/mpegvideo.c index fffa36a456..29500ea7b8 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -118,6 +118,7 @@ const enum PixelFormat ff_pixfmt_list_420[] = { const enum PixelFormat ff_hwaccel_pixfmt_list_420[] = { PIX_FMT_DXVA2_VLD, PIX_FMT_VAAPI_VLD, + PIX_FMT_VDA_VLD, PIX_FMT_YUV420P, PIX_FMT_NONE }; diff --git a/libavcodec/vda.c b/libavcodec/vda.c new file mode 100644 index 0000000000..5fe8a48fa4 --- /dev/null +++ b/libavcodec/vda.c @@ -0,0 +1,271 @@ +/* + * VDA HW acceleration. + * + * copyright (c) 2011 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 "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 0000000000..3f70cf2cf2 --- /dev/null +++ b/libavcodec/vda.h @@ -0,0 +1,140 @@ +/* + * VDA HW acceleration + * + * copyright (c) 2011 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_VDA_H +#define AVCODEC_VDA_H + +#include + +// 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 +#include "avcodec.h" +#include + +/** + * 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 FFmpeg 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 0000000000..f4791a168c --- /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 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 "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 0000000000..c6dcaa8ff6 --- /dev/null +++ b/libavcodec/vda_internal.h @@ -0,0 +1,50 @@ +/* + * VDA HW acceleration + * + * copyright (c) 2011 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_VDA_INTERNAL_H +#define AVCODEC_VDA_INTERNAL_H + +#include "h264.h" +#include "h264data.h" + +#include "vda.h" + +#include +#include +#include +#include + +/** + * \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/libavcodec/version.h b/libavcodec/version.h index db9b8ddad6..ad64b6032a 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -21,7 +21,7 @@ #define AVCODEC_VERSION_H #define LIBAVCODEC_VERSION_MAJOR 53 -#define LIBAVCODEC_VERSION_MINOR 26 +#define LIBAVCODEC_VERSION_MINOR 27 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavutil/avutil.h b/libavutil/avutil.h index d7eca65e6f..94e42714f1 100644 --- a/libavutil/avutil.h +++ b/libavutil/avutil.h @@ -40,7 +40,7 @@ #define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c) #define LIBAVUTIL_VERSION_MAJOR 51 -#define LIBAVUTIL_VERSION_MINOR 22 +#define LIBAVUTIL_VERSION_MINOR 23 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 5d0a9dfaeb..6648a7e8f5 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -1003,6 +1003,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_GRAY8A] = { .name = "gray8a", .nb_components= 2, diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index 25c9ef99ff..6719e83489 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -158,6 +158,8 @@ enum PixelFormat { PIX_FMT_BGRA64LE, ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian PIX_FMT_GBR24P, ///< planar GBR, 24bpp, 8G, 8B, 8R. + 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 };