From d8a091698af2a80495b7a4377253781080946380 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Sun, 13 Nov 2011 19:32:35 +0100 Subject: [PATCH 1/5] doc: add support for an optional navigation bar in texi2html pages The navigation header for the web pages lives in a different repository. Read it during documentation regeneration to use the same navigation bar on all pages. --- doc/t2h.init | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/t2h.init b/doc/t2h.init index 59a5ed8d5e..7c35cd8c53 100644 --- a/doc/t2h.init +++ b/doc/t2h.init @@ -9,9 +9,13 @@ $EXTRA_HEAD = '; + +my $LIBAV_NAVBAR = $ENV{"LIBAV_NAVBAR"} || ''; + $AFTER_BODY_OPEN = -'
-
'; +'
' . +"\n$LIBAV_NAVBAR\n" . +'
'; $PRE_BODY_CLOSE = '
'; From ac3dbb4d5854e8884daca54fd1f187b7f3769183 Mon Sep 17 00:00:00 2001 From: Sebastien Zwickert Date: Fri, 11 Nov 2011 15:48:21 +0100 Subject: [PATCH 2/5] hwaccel: OS X Video Decoder Acceleration (VDA) support. Signed-off-by: Luca Barbato --- Changelog | 1 + configure | 9 ++ libavcodec/Makefile | 5 +- libavcodec/allcodecs.c | 1 + libavcodec/h264.c | 1 + libavcodec/mpegvideo.c | 1 + libavcodec/vda.c | 259 ++++++++++++++++++++++++++++++++++++++ libavcodec/vda.h | 144 +++++++++++++++++++++ libavcodec/vda_h264.c | 110 ++++++++++++++++ libavcodec/vda_internal.h | 42 +++++++ libavcodec/version.h | 2 +- libavutil/avutil.h | 2 +- libavutil/pixdesc.c | 6 + libavutil/pixfmt.h | 1 + 14 files changed, 581 insertions(+), 3 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 a322c9d0d5..b9b5f26ae8 100644 --- a/Changelog +++ b/Changelog @@ -101,6 +101,7 @@ easier to use. The changes are: - Encrypted OMA files support - Discworld II BMV decoding support - VBLE Decoder +- OS X Video Decoder Acceleration (VDA) support version 0.7: diff --git a/configure b/configure index fa23619d39..6e4259f903 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 + --enable-vda enable VDA code --enable-vdpau enable VDPAU code --disable-dxva2 disable DXVA2 code --enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary) @@ -978,6 +979,7 @@ CONFIG_LIST=" swscale_alpha thumb vaapi + vda vdpau version3 x11grab @@ -1294,6 +1296,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_decoder" +h264_vda_hwaccel_select="vda h264_decoder" h264_vdpau_decoder_select="vdpau h264_decoder" imc_decoder_select="fft mdct sinewin" jpegls_decoder_select="golomb" @@ -1390,6 +1393,7 @@ zmbv_decoder_select="zlib" zmbv_encoder_select="zlib" vaapi_deps="va_va_h" +vda_deps="VideoDecodeAcceleration_VDADecoder_h pthreads" vdpau_deps="vdpau_vdpau_h vdpau_vdpau_x11_h" # parsers @@ -2988,6 +2992,11 @@ check_func XOpenDisplay -lX11 && check_func XShmCreateImage -lX11 -lXext && check_func XFixesGetCursorImage -lX11 -lXext -lXfixes +# check for VDA header +if ! disabled vda && check_header VideoDecodeAcceleration/VDADecoder.h; then + enable vda && add_ldflags -framework CoreFoundation -framework VideoDecodeAcceleration -framework QuartzCore +fi + if ! disabled vdpau && enabled vdpau_vdpau_h; then check_cpp_condition \ vdpau/vdpau.h "defined VDP_DECODER_PROFILE_MPEG4_PART2_ASP" || diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 76d5ce0707..b9ed8db2dc 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 @@ -180,6 +181,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 @@ -670,6 +672,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.h 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 a4a2147f94..db213a1ae0 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 2475095f20..d959d5652a 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 effc9b7baf..4c149f232f 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..34739f8e0c --- /dev/null +++ b/libavcodec/vda.c @@ -0,0 +1,259 @@ +/* + * VDA 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 +#include +#include +#include +#include + +#include "libavutil/avutil.h" +#include "vda_internal.h" + +/* 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 (!user_info) + return 0; + + pts = CFDictionaryGetValue(user_info, CFSTR("FF_VDA_DECODER_PTS_KEY")); + + if (pts) + CFNumberGetValue(pts, kCFNumberSInt64Type, &outValue); + + return outValue; +} + +/* Remove and release all frames from the queue. */ +static void vda_clear_queue(struct vda_context *vda_ctx) +{ + vda_frame *top_frame; + + pthread_mutex_lock(&vda_ctx->queue_mutex); + + while (vda_ctx->queue) { + top_frame = vda_ctx->queue; + vda_ctx->queue = top_frame->next_frame; + ff_vda_release_vda_frame(top_frame); + } + + pthread_mutex_unlock(&vda_ctx->queue_mutex); +} + +/* 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 = vda_hw_ctx; + vda_frame *new_frame; + vda_frame *queue_walker; + + if (!image_buffer) + return; + + if (vda_ctx->cv_pix_fmt_type != CVPixelBufferGetPixelFormatType(image_buffer)) + return; + + if (!(new_frame = av_mallocz(sizeof(vda_frame)))) + return; + new_frame->next_frame = NULL; + new_frame->cv_buffer = CVPixelBufferRetain(image_buffer); + new_frame->pts = vda_pts_from_dictionary(user_info); + + pthread_mutex_lock(&vda_ctx->queue_mutex); + + 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; + } + } + + pthread_mutex_unlock(&vda_ctx->queue_mutex); +} + +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; + CFMutableDictionaryRef buffer_attributes; + CFMutableDictionaryRef io_surface_properties; + CFNumberRef cv_pix_fmt; + + pthread_mutex_init(&vda_ctx->queue_mutex, NULL); + + 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); + + buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, + 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault, + 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, + kCFNumberSInt32Type, + &vda_ctx->cv_pix_fmt_type); + CFDictionarySetValue(buffer_attributes, + kCVPixelBufferPixelFormatTypeKey, + cv_pix_fmt); + CFDictionarySetValue(buffer_attributes, + kCVPixelBufferIOSurfacePropertiesKey, + io_surface_properties); + + status = VDADecoderCreate(config_info, + buffer_attributes, + vda_decoder_callback, + vda_ctx, + &vda_ctx->decoder); + + CFRelease(height); + CFRelease(width); + CFRelease(format); + CFRelease(avc_data); + CFRelease(config_info); + CFRelease(io_surface_properties); + CFRelease(cv_pix_fmt); + CFRelease(buffer_attributes); + + 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); + + pthread_mutex_destroy(&vda_ctx->queue_mutex); + + 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; + + pthread_mutex_lock(&vda_ctx->queue_mutex); + top_frame = vda_ctx->queue; + vda_ctx->queue = top_frame->next_frame; + pthread_mutex_unlock(&vda_ctx->queue_mutex); + + return top_frame; +} + +void ff_vda_release_vda_frame(vda_frame *frame) +{ + if (frame) { + 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..2cb51c5f53 --- /dev/null +++ b/libavcodec/vda.h @@ -0,0 +1,144 @@ +/* + * 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 +#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 +#undef Picture + +/** + * This structure is used to store a decoded frame information and data. + */ +typedef struct vda_frame { + /** + * 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. + */ + pthread_mutex_t 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; + + /** + * The pixel format for output image buffers. + * + * - encoding: unused + * - decoding: Set/Unset by user. + */ + OSType cv_pix_fmt_type; +}; + +/** Create the video decoder. */ +int ff_vda_create_decoder(struct vda_context *vda_ctx, + uint8_t *extradata, + int extradata_size); + +/** Destroy the video decoder. */ +int ff_vda_destroy_decoder(struct vda_context *vda_ctx); + +/** Return the top frame of the queue. */ +vda_frame *ff_vda_queue_pop(struct vda_context *vda_ctx); + +/** Release 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..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), +}; diff --git a/libavcodec/vda_internal.h b/libavcodec/vda_internal.h new file mode 100644 index 0000000000..364ebfb53e --- /dev/null +++ b/libavcodec/vda_internal.h @@ -0,0 +1,42 @@ +/* + * VDA 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 + */ + +#ifndef AVCODEC_VDA_INTERNAL_H +#define AVCODEC_VDA_INTERNAL_H + +#include "vda.h" + +/** + * @addtogroup VDA_Decoding + * + * @{ + */ + +/** Send 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 756ad1d223..356ecbb15c 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 19 +#define LIBAVCODEC_VERSION_MINOR 20 #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 5ad7034fab..4b226e0fb9 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 14 +#define LIBAVUTIL_VERSION_MINOR 15 #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 f7df0eba65..e0616df828 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 7068b43fed..1861fdfb9a 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, ///< hardware 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 }; From caf27e37b654d6f525d47bc62b914cbee4ca6a4b Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 14 Nov 2011 12:24:21 +0100 Subject: [PATCH 3/5] lavf: simplify format_child_class_next() And fix the error introduced when adding private option to avio. See 32caa7b13cecca59213c73fa94dd683c2b003bfd --- libavformat/options.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/libavformat/options.c b/libavformat/options.c index 66e01a4082..a9e2c1cd93 100644 --- a/libavformat/options.c +++ b/libavformat/options.c @@ -53,26 +53,29 @@ static const AVClass *format_child_class_next(const AVClass *prev) AVInputFormat *ifmt = NULL; AVOutputFormat *ofmt = NULL; - while (prev && (ifmt = av_iformat_next(ifmt))) + if (!prev) +#if !FF_API_OLD_AVIO + return &ffio_url_class; +#else + prev = (void *)&ifmt; // Dummy pointer; +#endif + + while ((ifmt = av_iformat_next(ifmt))) if (ifmt->priv_class == prev) break; - if ((prev && ifmt) || (!prev)) + + if (!ifmt) + while ((ofmt = av_oformat_next(ofmt))) + if (ofmt->priv_class == prev) + break; + if (!ofmt) while (ifmt = av_iformat_next(ifmt)) if (ifmt->priv_class) return ifmt->priv_class; - while (prev && (ofmt = av_oformat_next(ofmt))) - if (ofmt->priv_class == prev) - break; - if ((prev && ofmt) || (!prev)) - while (ofmt = av_oformat_next(ofmt)) - if (ofmt->priv_class) - return ofmt->priv_class; - -#if !FF_API_OLD_AVIO - if (prev != &ffio_url_class) - return &ffio_url_class; -#endif + while (ofmt = av_oformat_next(ofmt)) + if (ofmt->priv_class) + return ofmt->priv_class; return NULL; } From 2625b621ce7eb2d5f2f42d2a6dff37bffce3c726 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 14 Nov 2011 15:53:59 +0100 Subject: [PATCH 4/5] pulse: compute frame_duration once and fix it The frame duration was calculated without taking in account the bytes per sample. Thanks to Lorenzo Pistone for pointing the issue and providing an initial fix. --- libavdevice/pulse.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavdevice/pulse.c b/libavdevice/pulse.c index 1edd24fdd9..41f88b541f 100644 --- a/libavdevice/pulse.c +++ b/libavdevice/pulse.c @@ -46,6 +46,7 @@ typedef struct PulseData { int fragment_size; pa_simple *s; int64_t pts; + int64_t frame_duration; } PulseData; static pa_sample_format_t codec_id_to_pulse_format(int codec_id) { @@ -110,6 +111,8 @@ static av_cold int pulse_read_header(AVFormatContext *s, av_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ pd->pts = AV_NOPTS_VALUE; + pd->frame_duration = (pd->frame_size * 1000000LL * 8) / + (pd->sample_rate * pd->channels * av_get_bits_per_sample(codec_id)); return 0; } @@ -119,8 +122,6 @@ static int pulse_read_packet(AVFormatContext *s, AVPacket *pkt) PulseData *pd = s->priv_data; int res; pa_usec_t latency; - uint64_t frame_duration = - (pd->frame_size*1000000LL) / (pd->sample_rate * pd->channels); if (av_new_packet(pkt, pd->frame_size) < 0) { return AVERROR(ENOMEM); @@ -145,7 +146,7 @@ static int pulse_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->pts = pd->pts; - pd->pts += frame_duration; + pd->pts += pd->frame_duration; return 0; } From 3f5d6a665aba439a9309ed735e71403d236a313d Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sun, 13 Nov 2011 15:25:53 +0000 Subject: [PATCH 5/5] binkvideo: simplify and remove invalid shifts Signed-off-by: Mans Rullgard --- libavcodec/bink.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libavcodec/bink.c b/libavcodec/bink.c index 474e5c4801..b55ea07699 100644 --- a/libavcodec/bink.c +++ b/libavcodec/bink.c @@ -595,7 +595,7 @@ static int read_dct_coeffs(GetBitContext *gb, int32_t block[64], const uint8_t * { int coef_list[128]; int mode_list[128]; - int i, t, mask, bits, ccoef, mode, sign; + int i, t, bits, ccoef, mode, sign; int list_start = 64, list_end = 64, list_pos; int coef_count = 0; int coef_idx[64]; @@ -609,8 +609,7 @@ static int read_dct_coeffs(GetBitContext *gb, int32_t block[64], const uint8_t * coef_list[list_end] = 2; mode_list[list_end++] = 3; coef_list[list_end] = 3; mode_list[list_end++] = 3; - bits = get_bits(gb, 4) - 1; - for (mask = 1 << bits; bits >= 0; mask >>= 1, bits--) { + for (bits = get_bits(gb, 4) - 1; bits >= 0; bits--) { list_pos = list_start; while (list_pos < list_end) { if (!(mode_list[list_pos] | coef_list[list_pos]) || !get_bits1(gb)) { @@ -636,7 +635,7 @@ static int read_dct_coeffs(GetBitContext *gb, int32_t block[64], const uint8_t * if (!bits) { t = 1 - (get_bits1(gb) << 1); } else { - t = get_bits(gb, bits) | mask; + t = get_bits(gb, bits) | 1 << bits; sign = -get_bits1(gb); t = (t ^ sign) - sign; } @@ -657,7 +656,7 @@ static int read_dct_coeffs(GetBitContext *gb, int32_t block[64], const uint8_t * if (!bits) { t = 1 - (get_bits1(gb) << 1); } else { - t = get_bits(gb, bits) | mask; + t = get_bits(gb, bits) | 1 << bits; sign = -get_bits1(gb); t = (t ^ sign) - sign; }