mirror of
https://github.com/xenia-project/FFmpeg.git
synced 2024-11-27 05:20:48 +00:00
lavc: drop VDA
Deprecated (aka removed) in OSX 10.11, and we have a replacement for it (VideoToolbox).
This commit is contained in:
parent
3605b312f6
commit
2b32031827
@ -5,6 +5,7 @@ version <next>:
|
||||
- Bitstream filters for editing metadata in H.264, HEVC and MPEG-2 streams
|
||||
- Dropped support for OpenJPEG versions 2.0 and below. Using OpenJPEG now
|
||||
requires 2.1 (or later) and pkg-config.
|
||||
- VDA dropped (use VideoToolbox instead)
|
||||
|
||||
|
||||
version 3.4:
|
||||
|
@ -244,7 +244,6 @@ Codecs:
|
||||
txd.c Ivo van Poorten
|
||||
vc2* Rostislav Pehlivanov
|
||||
vcr1.c Michael Niedermayer
|
||||
vda_h264_dec.c Xidorn Quan
|
||||
videotoolboxenc.c Rick Kern
|
||||
vima.c Paul B Mahol
|
||||
vorbisdec.c Denes Balatoni, David Conrad
|
||||
|
14
configure
vendored
14
configure
vendored
@ -318,7 +318,6 @@ External library support:
|
||||
--enable-omx-rpi enable OpenMAX IL code for Raspberry Pi [no]
|
||||
--enable-rkmpp enable Rockchip Media Process Platform code [no]
|
||||
--disable-vaapi disable Video Acceleration API (mainly Unix/Intel) code [autodetect]
|
||||
--disable-vda disable Apple Video Decode Acceleration code [autodetect]
|
||||
--disable-vdpau disable Nvidia Video Decode and Presentation API for Unix code [autodetect]
|
||||
--disable-videotoolbox disable VideoToolbox code [autodetect]
|
||||
|
||||
@ -1650,7 +1649,6 @@ HWACCEL_AUTODETECT_LIBRARY_LIST="
|
||||
dxva2
|
||||
nvenc
|
||||
vaapi
|
||||
vda
|
||||
vdpau
|
||||
videotoolbox
|
||||
v4l2_m2m
|
||||
@ -2660,10 +2658,6 @@ cuda_deps_any="libdl LoadLibrary"
|
||||
cuvid_deps="cuda"
|
||||
d3d11va_deps="d3d11_h dxva_h ID3D11VideoDecoder ID3D11VideoContext"
|
||||
dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32"
|
||||
vda_framework_deps="VideoDecodeAcceleration_VDADecoder_h blocks_extension"
|
||||
vda_framework_extralibs="-framework VideoDecodeAcceleration"
|
||||
vda_deps="vda_framework pthreads corefoundation"
|
||||
vda_extralibs="-framework QuartzCore"
|
||||
videotoolbox_hwaccel_deps="videotoolbox pthreads"
|
||||
videotoolbox_hwaccel_extralibs="-framework QuartzCore"
|
||||
xvmc_deps="X11_extensions_XvMClib_h"
|
||||
@ -2685,10 +2679,6 @@ h264_mmal_hwaccel_deps="mmal"
|
||||
h264_qsv_hwaccel_deps="libmfx"
|
||||
h264_vaapi_hwaccel_deps="vaapi"
|
||||
h264_vaapi_hwaccel_select="h264_decoder"
|
||||
h264_vda_hwaccel_deps="vda"
|
||||
h264_vda_hwaccel_select="h264_decoder"
|
||||
h264_vda_old_hwaccel_deps="vda"
|
||||
h264_vda_old_hwaccel_select="h264_decoder"
|
||||
h264_vdpau_hwaccel_deps="vdpau"
|
||||
h264_vdpau_hwaccel_select="h264_decoder"
|
||||
h264_videotoolbox_hwaccel_deps="videotoolbox"
|
||||
@ -2822,8 +2812,6 @@ h264_rkmpp_decoder_deps="rkmpp"
|
||||
h264_rkmpp_decoder_select="h264_mp4toannexb_bsf"
|
||||
h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264"
|
||||
h264_vaapi_encoder_select="cbs_h264 vaapi_encode"
|
||||
h264_vda_decoder_deps="vda"
|
||||
h264_vda_decoder_select="h264_decoder"
|
||||
h264_vdpau_decoder_deps="vdpau"
|
||||
h264_vdpau_decoder_select="h264_decoder"
|
||||
h264_v4l2m2m_decoder_deps="v4l2_m2m h264_v4l2_m2m"
|
||||
@ -3011,7 +2999,6 @@ libzvbi_teletext_decoder_deps="libzvbi"
|
||||
videotoolbox_suggest="coreservices"
|
||||
videotoolbox_deps="corefoundation coremedia corevideo"
|
||||
videotoolbox_encoder_deps="videotoolbox VTCompressionSessionPrepareToEncodeFrames"
|
||||
videotoolbox_encoder_suggest="vda_framework"
|
||||
|
||||
# demuxers / muxers
|
||||
ac3_demuxer_select="ac3_parser"
|
||||
@ -5847,7 +5834,6 @@ check_header sys/un.h
|
||||
check_header termios.h
|
||||
check_header unistd.h
|
||||
check_header valgrind/valgrind.h
|
||||
check_header VideoDecodeAcceleration/VDADecoder.h
|
||||
check_func_headers VideoToolbox/VTCompressionSession.h VTCompressionSessionPrepareToEncodeFrames -framework VideoToolbox
|
||||
check_header windows.h
|
||||
check_header X11/extensions/XvMClib.h
|
||||
|
@ -786,9 +786,6 @@ Do not use any hardware acceleration (the default).
|
||||
@item auto
|
||||
Automatically select the hardware acceleration method.
|
||||
|
||||
@item vda
|
||||
Use Apple VDA hardware acceleration.
|
||||
|
||||
@item vdpau
|
||||
Use VDPAU (Video Decode and Presentation API for Unix) hardware acceleration.
|
||||
|
||||
|
@ -63,7 +63,6 @@ enum HWAccelID {
|
||||
HWACCEL_AUTO,
|
||||
HWACCEL_VDPAU,
|
||||
HWACCEL_DXVA2,
|
||||
HWACCEL_VDA,
|
||||
HWACCEL_VIDEOTOOLBOX,
|
||||
HWACCEL_QSV,
|
||||
HWACCEL_VAAPI,
|
||||
@ -661,7 +660,6 @@ int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame);
|
||||
|
||||
int ffmpeg_parse_options(int argc, char **argv);
|
||||
|
||||
int vda_init(AVCodecContext *s);
|
||||
int videotoolbox_init(AVCodecContext *s);
|
||||
int qsv_init(AVCodecContext *s);
|
||||
int cuvid_init(AVCodecContext *s);
|
||||
|
@ -78,10 +78,6 @@ const HWAccel hwaccels[] = {
|
||||
{ "dxva2", hwaccel_decode_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD,
|
||||
AV_HWDEVICE_TYPE_DXVA2 },
|
||||
#endif
|
||||
#if CONFIG_VDA
|
||||
{ "vda", videotoolbox_init, HWACCEL_VDA, AV_PIX_FMT_VDA,
|
||||
AV_HWDEVICE_TYPE_NONE },
|
||||
#endif
|
||||
#if CONFIG_VIDEOTOOLBOX
|
||||
{ "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX,
|
||||
AV_HWDEVICE_TYPE_NONE },
|
||||
@ -3631,7 +3627,7 @@ const OptionDef options[] = {
|
||||
{ "hwaccel_output_format", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT |
|
||||
OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_output_formats) },
|
||||
"select output format used with HW accelerated decoding", "format" },
|
||||
#if CONFIG_VDA || CONFIG_VIDEOTOOLBOX
|
||||
#if CONFIG_VIDEOTOOLBOX
|
||||
{ "videotoolbox_pixfmt", HAS_ARG | OPT_STRING | OPT_EXPERT, { &videotoolbox_pixfmt}, "" },
|
||||
#endif
|
||||
{ "hwaccels", OPT_EXIT, { .func_arg = show_hwaccels },
|
||||
|
@ -23,12 +23,7 @@
|
||||
#endif
|
||||
|
||||
#include "libavcodec/avcodec.h"
|
||||
#if CONFIG_VDA
|
||||
# include "libavcodec/vda.h"
|
||||
#endif
|
||||
#if CONFIG_VIDEOTOOLBOX
|
||||
# include "libavcodec/videotoolbox.h"
|
||||
#endif
|
||||
#include "libavcodec/videotoolbox.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
#include "ffmpeg.h"
|
||||
|
||||
@ -114,15 +109,7 @@ static void videotoolbox_uninit(AVCodecContext *s)
|
||||
|
||||
av_frame_free(&vt->tmp_frame);
|
||||
|
||||
if (ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX) {
|
||||
#if CONFIG_VIDEOTOOLBOX
|
||||
av_videotoolbox_default_free(s);
|
||||
#endif
|
||||
} else {
|
||||
#if CONFIG_VDA
|
||||
av_vda_default_free(s);
|
||||
#endif
|
||||
}
|
||||
av_videotoolbox_default_free(s);
|
||||
av_freep(&ist->hwaccel_ctx);
|
||||
}
|
||||
|
||||
@ -147,8 +134,7 @@ int videotoolbox_init(AVCodecContext *s)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX) {
|
||||
#if CONFIG_VIDEOTOOLBOX
|
||||
// TODO: reindent
|
||||
if (!videotoolbox_pixfmt) {
|
||||
ret = av_videotoolbox_default_init(s);
|
||||
} else {
|
||||
@ -166,31 +152,8 @@ int videotoolbox_init(AVCodecContext *s)
|
||||
ret = av_videotoolbox_default_init2(s, vtctx);
|
||||
CFRelease(pixfmt_str);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if CONFIG_VDA
|
||||
if (!videotoolbox_pixfmt) {
|
||||
ret = av_vda_default_init(s);
|
||||
} else {
|
||||
AVVDAContext *vdactx = av_vda_alloc_context();
|
||||
CFStringRef pixfmt_str = CFStringCreateWithCString(kCFAllocatorDefault,
|
||||
videotoolbox_pixfmt,
|
||||
kCFStringEncodingUTF8);
|
||||
#if HAVE_UTGETOSTYPEFROMSTRING
|
||||
vdactx->cv_pix_fmt_type = UTGetOSTypeFromString(pixfmt_str);
|
||||
#else
|
||||
av_log(s, loglevel, "UTGetOSTypeFromString() is not available "
|
||||
"on this platform, %s pixel format can not be honored from "
|
||||
"the command line\n", videotoolbox_pixfmt);
|
||||
#endif
|
||||
ret = av_vda_default_init2(s, vdactx);
|
||||
CFRelease(pixfmt_str);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (ret < 0) {
|
||||
av_log(NULL, loglevel,
|
||||
"Error creating %s decoder.\n", ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX ? "Videotoolbox" : "VDA");
|
||||
av_log(NULL, loglevel, "Error creating Videotoolbox decoder.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,6 @@ HEADERS = avcodec.h \
|
||||
mediacodec.h \
|
||||
qsv.h \
|
||||
vaapi.h \
|
||||
vda.h \
|
||||
vdpau.h \
|
||||
version.h \
|
||||
videotoolbox.h \
|
||||
@ -338,7 +337,6 @@ OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o
|
||||
OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o
|
||||
OBJS-$(CONFIG_NVENC_ENCODER) += nvenc_h264.o
|
||||
OBJS-$(CONFIG_NVENC_H264_ENCODER) += nvenc_h264.o
|
||||
OBJS-$(CONFIG_H264_VDA_DECODER) += vda_h264_dec.o
|
||||
OBJS-$(CONFIG_H264_OMX_ENCODER) += omx.o
|
||||
OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec_h2645.o
|
||||
OBJS-$(CONFIG_H264_QSV_ENCODER) += qsvenc_h264.o
|
||||
@ -824,7 +822,6 @@ OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcmenc.o adpcm_data.o
|
||||
OBJS-$(CONFIG_D3D11VA) += dxva2.o
|
||||
OBJS-$(CONFIG_DXVA2) += dxva2.o
|
||||
OBJS-$(CONFIG_VAAPI) += vaapi_decode.o
|
||||
OBJS-$(CONFIG_VDA) += vda.o videotoolbox.o
|
||||
OBJS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.o
|
||||
OBJS-$(CONFIG_VDPAU) += vdpau.o
|
||||
|
||||
@ -834,7 +831,6 @@ OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o
|
||||
OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o
|
||||
OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec_h2645.o
|
||||
OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o
|
||||
OBJS-$(CONFIG_H264_VDA_HWACCEL) += vda_h264.o
|
||||
OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o
|
||||
OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
|
||||
OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.o
|
||||
@ -1066,9 +1062,8 @@ SKIPHEADERS-$(CONFIG_QSVDEC) += qsvdec.h
|
||||
SKIPHEADERS-$(CONFIG_QSVENC) += qsvenc.h
|
||||
SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h
|
||||
SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_decode.h vaapi_encode.h
|
||||
SKIPHEADERS-$(CONFIG_VDA) += vda.h vda_vt_internal.h
|
||||
SKIPHEADERS-$(CONFIG_VDPAU) += vdpau.h vdpau_internal.h
|
||||
SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.h vda_vt_internal.h
|
||||
SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.h vt_internal.h
|
||||
SKIPHEADERS-$(CONFIG_V4L2_M2M) += v4l2_buffers.h v4l2_context.h v4l2_m2m.h
|
||||
|
||||
TESTPROGS = avpacket \
|
||||
|
@ -72,8 +72,6 @@ static void register_all(void)
|
||||
REGISTER_HWACCEL(H264_MMAL, h264_mmal);
|
||||
REGISTER_HWACCEL(H264_QSV, h264_qsv);
|
||||
REGISTER_HWACCEL(H264_VAAPI, h264_vaapi);
|
||||
REGISTER_HWACCEL(H264_VDA, h264_vda);
|
||||
REGISTER_HWACCEL(H264_VDA_OLD, h264_vda_old);
|
||||
REGISTER_HWACCEL(H264_VDPAU, h264_vdpau);
|
||||
REGISTER_HWACCEL(H264_VIDEOTOOLBOX, h264_videotoolbox);
|
||||
REGISTER_HWACCEL(HEVC_CUVID, hevc_cuvid);
|
||||
@ -217,7 +215,6 @@ static void register_all(void)
|
||||
REGISTER_DECODER(H264_MMAL, h264_mmal);
|
||||
REGISTER_DECODER(H264_QSV, h264_qsv);
|
||||
REGISTER_DECODER(H264_RKMPP, h264_rkmpp);
|
||||
REGISTER_DECODER(H264_VDA, h264_vda);
|
||||
#if FF_API_VDPAU
|
||||
REGISTER_DECODER(H264_VDPAU, h264_vdpau);
|
||||
#endif
|
||||
|
@ -755,7 +755,6 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
|
||||
#define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \
|
||||
(CONFIG_H264_D3D11VA_HWACCEL * 2) + \
|
||||
CONFIG_H264_VAAPI_HWACCEL + \
|
||||
(CONFIG_H264_VDA_HWACCEL * 2) + \
|
||||
CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \
|
||||
CONFIG_H264_VDPAU_HWACCEL)
|
||||
enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts;
|
||||
@ -834,10 +833,6 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
|
||||
#if CONFIG_H264_VAAPI_HWACCEL
|
||||
*fmt++ = AV_PIX_FMT_VAAPI;
|
||||
#endif
|
||||
#if CONFIG_H264_VDA_HWACCEL
|
||||
*fmt++ = AV_PIX_FMT_VDA_VLD;
|
||||
*fmt++ = AV_PIX_FMT_VDA;
|
||||
#endif
|
||||
#if CONFIG_H264_VIDEOTOOLBOX_HWACCEL
|
||||
*fmt++ = AV_PIX_FMT_VIDEOTOOLBOX;
|
||||
#endif
|
||||
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* 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 "config.h"
|
||||
|
||||
#include "libavutil/mem.h"
|
||||
|
||||
#include "vda.h"
|
||||
#include "vda_vt_internal.h"
|
||||
|
||||
#if CONFIG_H264_VDA_HWACCEL
|
||||
AVVDAContext *av_vda_alloc_context(void)
|
||||
{
|
||||
AVVDAContext *ret = av_mallocz(sizeof(*ret));
|
||||
|
||||
if (ret) {
|
||||
ret->output_callback = ff_vda_output_callback;
|
||||
ret->cv_pix_fmt_type = kCVPixelFormatType_422YpCbCr8;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int av_vda_default_init(AVCodecContext *avctx)
|
||||
{
|
||||
return av_vda_default_init2(avctx, NULL);
|
||||
}
|
||||
|
||||
int av_vda_default_init2(AVCodecContext *avctx, AVVDAContext *vdactx)
|
||||
{
|
||||
avctx->hwaccel_context = vdactx ?: av_vda_alloc_context();
|
||||
if (!avctx->hwaccel_context)
|
||||
return AVERROR(ENOMEM);
|
||||
return ff_vda_default_init(avctx);
|
||||
}
|
||||
|
||||
void av_vda_default_free(AVCodecContext *avctx)
|
||||
{
|
||||
ff_vda_default_free(avctx);
|
||||
av_freep(&avctx->hwaccel_context);
|
||||
}
|
||||
|
||||
void ff_vda_default_free(AVCodecContext *avctx)
|
||||
{
|
||||
AVVDAContext *vda = avctx->hwaccel_context;
|
||||
if (vda && vda->decoder)
|
||||
VDADecoderDestroy(vda->decoder);
|
||||
}
|
||||
|
||||
#else
|
||||
AVVDAContext *av_vda_alloc_context(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int av_vda_default_init(AVCodecContext *avctx)
|
||||
{
|
||||
return AVERROR(ENOSYS);
|
||||
}
|
||||
|
||||
int av_vda_default_init2(AVCodecContext *avctx, AVVDAContext *vdactx)
|
||||
{
|
||||
return AVERROR(ENOSYS);
|
||||
}
|
||||
|
||||
void av_vda_default_free(AVCodecContext *ctx)
|
||||
{
|
||||
}
|
||||
#endif
|
230
libavcodec/vda.h
230
libavcodec/vda.h
@ -1,230 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @ingroup lavc_codec_hwaccel_vda
|
||||
* Public libavcodec VDA header.
|
||||
*/
|
||||
|
||||
#include "libavcodec/avcodec.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 <VideoDecodeAcceleration/VDADecoder.h>
|
||||
#undef Picture
|
||||
|
||||
#include "libavcodec/version.h"
|
||||
|
||||
// extra flags not defined in VDADecoder.h
|
||||
enum {
|
||||
kVDADecodeInfo_Asynchronous = 1UL << 0,
|
||||
kVDADecodeInfo_FrameDropped = 1UL << 1
|
||||
};
|
||||
|
||||
/**
|
||||
* @defgroup lavc_codec_hwaccel_vda VDA
|
||||
* @ingroup lavc_codec_hwaccel
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* The Core Video pixel buffer that contains the current image data.
|
||||
*
|
||||
* encoding: unused
|
||||
* decoding: Set by libavcodec. Unset by user.
|
||||
*/
|
||||
CVPixelBufferRef cv_buffer;
|
||||
|
||||
/**
|
||||
* Use the hardware decoder in synchronous mode.
|
||||
*
|
||||
* encoding: unused
|
||||
* decoding: Set by user.
|
||||
*/
|
||||
int use_sync_decoding;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* unused
|
||||
*/
|
||||
uint8_t *priv_bitstream;
|
||||
|
||||
/**
|
||||
* unused
|
||||
*/
|
||||
int priv_bitstream_size;
|
||||
|
||||
/**
|
||||
* unused
|
||||
*/
|
||||
int priv_allocated_size;
|
||||
|
||||
/**
|
||||
* Use av_buffer to manage buffer.
|
||||
* When the flag is set, the CVPixelBuffers returned by the decoder will
|
||||
* be released automatically, so you have to retain them if necessary.
|
||||
* Not setting this flag may cause memory leak.
|
||||
*
|
||||
* encoding: unused
|
||||
* decoding: Set by user.
|
||||
*/
|
||||
int use_ref_buffer;
|
||||
};
|
||||
|
||||
/** 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);
|
||||
|
||||
/**
|
||||
* This struct holds all the information that needs to be passed
|
||||
* between the caller and libavcodec for initializing VDA decoding.
|
||||
* Its size is not a part of the public ABI, it must be allocated with
|
||||
* av_vda_alloc_context() and freed with av_free().
|
||||
*/
|
||||
typedef struct AVVDAContext {
|
||||
/**
|
||||
* VDA decoder object. Created and freed by the caller.
|
||||
*/
|
||||
VDADecoder decoder;
|
||||
|
||||
/**
|
||||
* The output callback that must be passed to VDADecoderCreate.
|
||||
* Set by av_vda_alloc_context().
|
||||
*/
|
||||
VDADecoderOutputCallback output_callback;
|
||||
|
||||
/**
|
||||
* CVPixelBuffer Format Type that VDA will use for decoded frames; set by
|
||||
* the caller.
|
||||
*/
|
||||
OSType cv_pix_fmt_type;
|
||||
} AVVDAContext;
|
||||
|
||||
/**
|
||||
* Allocate and initialize a VDA context.
|
||||
*
|
||||
* This function should be called from the get_format() callback when the caller
|
||||
* selects the AV_PIX_FMT_VDA format. The caller must then create the decoder
|
||||
* object (using the output callback provided by libavcodec) that will be used
|
||||
* for VDA-accelerated decoding.
|
||||
*
|
||||
* When decoding with VDA is finished, the caller must destroy the decoder
|
||||
* object and free the VDA context using av_free().
|
||||
*
|
||||
* @return the newly allocated context or NULL on failure
|
||||
*/
|
||||
AVVDAContext *av_vda_alloc_context(void);
|
||||
|
||||
/**
|
||||
* This is a convenience function that creates and sets up the VDA context using
|
||||
* an internal implementation.
|
||||
*
|
||||
* @param avctx the corresponding codec context
|
||||
*
|
||||
* @return >= 0 on success, a negative AVERROR code on failure
|
||||
*/
|
||||
int av_vda_default_init(AVCodecContext *avctx);
|
||||
|
||||
/**
|
||||
* This is a convenience function that creates and sets up the VDA context using
|
||||
* an internal implementation.
|
||||
*
|
||||
* @param avctx the corresponding codec context
|
||||
* @param vdactx the VDA context to use
|
||||
*
|
||||
* @return >= 0 on success, a negative AVERROR code on failure
|
||||
*/
|
||||
int av_vda_default_init2(AVCodecContext *avctx, AVVDAContext *vdactx);
|
||||
|
||||
/**
|
||||
* This function must be called to free the VDA context initialized with
|
||||
* av_vda_default_init().
|
||||
*
|
||||
* @param avctx the corresponding codec context
|
||||
*/
|
||||
void av_vda_default_free(AVCodecContext *avctx);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* AVCODEC_VDA_H */
|
@ -1,425 +0,0 @@
|
||||
/*
|
||||
* 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 <CoreFoundation/CFDictionary.h>
|
||||
#include <CoreFoundation/CFNumber.h>
|
||||
#include <CoreFoundation/CFData.h>
|
||||
|
||||
#include "vda.h"
|
||||
#include "libavutil/avutil.h"
|
||||
#include "h264dec.h"
|
||||
|
||||
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. */
|
||||
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;
|
||||
|
||||
if (infoFlags & kVDADecodeInfo_FrameDropped)
|
||||
vda_ctx->cv_buffer = NULL;
|
||||
|
||||
if (!image_buffer)
|
||||
return;
|
||||
|
||||
if (vda_ctx->cv_pix_fmt_type != CVPixelBufferGetPixelFormatType(image_buffer))
|
||||
return;
|
||||
|
||||
vda_ctx->cv_buffer = CVPixelBufferRetain(image_buffer);
|
||||
}
|
||||
|
||||
static int vda_sync_decode(VTContext *ctx, struct vda_context *vda_ctx)
|
||||
{
|
||||
OSStatus status;
|
||||
CFDataRef coded_frame;
|
||||
uint32_t flush_flags = 1 << 0; ///< kVDADecoderFlush_emitFrames
|
||||
|
||||
coded_frame = CFDataCreate(kCFAllocatorDefault,
|
||||
ctx->bitstream,
|
||||
ctx->bitstream_size);
|
||||
|
||||
status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, NULL);
|
||||
|
||||
if (kVDADecoderNoErr == status)
|
||||
status = VDADecoderFlush(vda_ctx->decoder, flush_flags);
|
||||
|
||||
CFRelease(coded_frame);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static int vda_old_h264_start_frame(AVCodecContext *avctx,
|
||||
av_unused const uint8_t *buffer,
|
||||
av_unused uint32_t size)
|
||||
{
|
||||
VTContext *vda = avctx->internal->hwaccel_priv_data;
|
||||
struct vda_context *vda_ctx = avctx->hwaccel_context;
|
||||
|
||||
if (!vda_ctx->decoder)
|
||||
return -1;
|
||||
|
||||
vda->bitstream_size = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vda_old_h264_decode_slice(AVCodecContext *avctx,
|
||||
const uint8_t *buffer,
|
||||
uint32_t size)
|
||||
{
|
||||
VTContext *vda = avctx->internal->hwaccel_priv_data;
|
||||
struct vda_context *vda_ctx = avctx->hwaccel_context;
|
||||
void *tmp;
|
||||
|
||||
if (!vda_ctx->decoder)
|
||||
return -1;
|
||||
|
||||
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 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;
|
||||
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)
|
||||
return -1;
|
||||
|
||||
status = vda_sync_decode(vda, vda_ctx);
|
||||
frame->data[3] = (void*)vda_ctx->cv_buffer;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int ff_vda_create_decoder(struct vda_context *vda_ctx,
|
||||
uint8_t *extradata,
|
||||
int extradata_size)
|
||||
{
|
||||
OSStatus status;
|
||||
CFNumberRef height;
|
||||
CFNumberRef width;
|
||||
CFNumberRef format;
|
||||
CFDataRef avc_data;
|
||||
CFMutableDictionaryRef config_info;
|
||||
CFMutableDictionaryRef buffer_attributes;
|
||||
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. */
|
||||
if (extradata_size >= 4 && (extradata[4] & 0x03) != 0x03) {
|
||||
uint8_t *rw_extradata;
|
||||
|
||||
if (!(rw_extradata = av_malloc(extradata_size)))
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
memcpy(rw_extradata, extradata, extradata_size);
|
||||
|
||||
rw_extradata[4] |= 0x03;
|
||||
|
||||
avc_data = CFDataCreate(kCFAllocatorDefault, rw_extradata, extradata_size);
|
||||
|
||||
av_freep(&rw_extradata);
|
||||
} else {
|
||||
avc_data = CFDataCreate(kCFAllocatorDefault, extradata, extradata_size);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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,
|
||||
(VDADecoderOutputCallback *)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);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int ff_vda_destroy_decoder(struct vda_context *vda_ctx)
|
||||
{
|
||||
OSStatus status = kVDADecoderNoErr;
|
||||
|
||||
if (vda_ctx->decoder)
|
||||
status = VDADecoderDestroy(vda_ctx->decoder);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
AVHWAccel ff_h264_vda_old_hwaccel = {
|
||||
.name = "h264_vda",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_H264,
|
||||
.pix_fmt = AV_PIX_FMT_VDA_VLD,
|
||||
.start_frame = vda_old_h264_start_frame,
|
||||
.decode_slice = vda_old_h264_decode_slice,
|
||||
.end_frame = vda_old_h264_end_frame,
|
||||
.uninit = ff_videotoolbox_uninit,
|
||||
.priv_data_size = sizeof(VTContext),
|
||||
};
|
||||
|
||||
void ff_vda_output_callback(void *opaque,
|
||||
CFDictionaryRef user_info,
|
||||
OSStatus status,
|
||||
uint32_t infoFlags,
|
||||
CVImageBufferRef image_buffer)
|
||||
{
|
||||
AVCodecContext *ctx = opaque;
|
||||
VTContext *vda = ctx->internal->hwaccel_priv_data;
|
||||
|
||||
|
||||
if (vda->frame) {
|
||||
CVPixelBufferRelease(vda->frame);
|
||||
vda->frame = NULL;
|
||||
}
|
||||
|
||||
if (!image_buffer)
|
||||
return;
|
||||
|
||||
vda->frame = CVPixelBufferRetain(image_buffer);
|
||||
}
|
||||
|
||||
static int vda_h264_end_frame(AVCodecContext *avctx)
|
||||
{
|
||||
H264Context *h = avctx->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
|
||||
CFDataRef coded_frame;
|
||||
OSStatus status;
|
||||
|
||||
if (!vda->bitstream_size)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
|
||||
coded_frame = CFDataCreate(kCFAllocatorDefault,
|
||||
vda->bitstream,
|
||||
vda->bitstream_size);
|
||||
|
||||
status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, NULL);
|
||||
|
||||
if (status == kVDADecoderNoErr)
|
||||
status = VDADecoderFlush(vda_ctx->decoder, flush_flags);
|
||||
|
||||
CFRelease(coded_frame);
|
||||
|
||||
if (!vda->frame)
|
||||
return AVERROR_UNKNOWN;
|
||||
|
||||
if (status != kVDADecoderNoErr) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
|
||||
return AVERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
return ff_videotoolbox_buffer_create(vda, frame);
|
||||
}
|
||||
|
||||
int ff_vda_default_init(AVCodecContext *avctx)
|
||||
{
|
||||
AVVDAContext *vda_ctx = avctx->hwaccel_context;
|
||||
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;
|
||||
int32_t fmt = 'avc1', pix_fmt = vda_ctx->cv_pix_fmt_type;
|
||||
|
||||
// kCVPixelFormatType_420YpCbCr8Planar;
|
||||
|
||||
avc_data = ff_videotoolbox_avcc_extradata_create(avctx);
|
||||
|
||||
config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
|
||||
4,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->height);
|
||||
width = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->width);
|
||||
format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &fmt);
|
||||
CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height);
|
||||
CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width);
|
||||
CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data);
|
||||
CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format);
|
||||
|
||||
buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
|
||||
2,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
|
||||
0,
|
||||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault,
|
||||
kCFNumberSInt32Type,
|
||||
&pix_fmt);
|
||||
|
||||
CFDictionarySetValue(buffer_attributes,
|
||||
kCVPixelBufferPixelFormatTypeKey,
|
||||
cv_pix_fmt);
|
||||
CFDictionarySetValue(buffer_attributes,
|
||||
kCVPixelBufferIOSurfacePropertiesKey,
|
||||
io_surface_properties);
|
||||
|
||||
status = VDADecoderCreate(config_info,
|
||||
buffer_attributes,
|
||||
(VDADecoderOutputCallback *)ff_vda_output_callback,
|
||||
avctx,
|
||||
&vda_ctx->decoder);
|
||||
|
||||
CFRelease(format);
|
||||
CFRelease(height);
|
||||
CFRelease(width);
|
||||
CFRelease(avc_data);
|
||||
CFRelease(config_info);
|
||||
CFRelease(cv_pix_fmt);
|
||||
CFRelease(io_surface_properties);
|
||||
CFRelease(buffer_attributes);
|
||||
|
||||
if (status != kVDADecoderNoErr) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Cannot initialize VDA %d\n", status);
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case kVDADecoderHardwareNotSupportedErr:
|
||||
case kVDADecoderFormatNotSupportedErr:
|
||||
return AVERROR(ENOSYS);
|
||||
case kVDADecoderConfigurationError:
|
||||
return AVERROR(EINVAL);
|
||||
case kVDADecoderDecoderFailedErr:
|
||||
return AVERROR_INVALIDDATA;
|
||||
case kVDADecoderNoErr:
|
||||
return 0;
|
||||
default:
|
||||
return AVERROR_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
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 = 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 = ff_videotoolbox_uninit,
|
||||
.priv_data_size = sizeof(VTContext),
|
||||
};
|
@ -1,263 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Xidorn Quan
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* H.264 decoder via VDA
|
||||
* @author Xidorn Quan <quanxunzhen@gmail.com>
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#include "vda.h"
|
||||
#include "h264dec.h"
|
||||
#include "avcodec.h"
|
||||
|
||||
#ifndef kCFCoreFoundationVersionNumber10_7
|
||||
#define kCFCoreFoundationVersionNumber10_7 635.00
|
||||
#endif
|
||||
|
||||
extern AVCodec ff_h264_decoder, ff_h264_vda_decoder;
|
||||
|
||||
static const enum AVPixelFormat vda_pixfmts_prior_10_7[] = {
|
||||
AV_PIX_FMT_UYVY422,
|
||||
AV_PIX_FMT_YUV420P,
|
||||
AV_PIX_FMT_NONE
|
||||
};
|
||||
|
||||
static const enum AVPixelFormat vda_pixfmts[] = {
|
||||
AV_PIX_FMT_UYVY422,
|
||||
AV_PIX_FMT_YUYV422,
|
||||
AV_PIX_FMT_NV12,
|
||||
AV_PIX_FMT_YUV420P,
|
||||
AV_PIX_FMT_NONE
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
H264Context h264ctx;
|
||||
int h264_initialized;
|
||||
struct vda_context vda_ctx;
|
||||
enum AVPixelFormat pix_fmt;
|
||||
|
||||
/* for backing-up fields set by user.
|
||||
* we have to gain full control of such fields here */
|
||||
void *hwaccel_context;
|
||||
enum AVPixelFormat (*get_format)(struct AVCodecContext *s, const enum AVPixelFormat * fmt);
|
||||
int (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, int flags);
|
||||
} VDADecoderContext;
|
||||
|
||||
static enum AVPixelFormat get_format(struct AVCodecContext *avctx,
|
||||
const enum AVPixelFormat *fmt)
|
||||
{
|
||||
return AV_PIX_FMT_VDA_VLD;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
CVPixelBufferRef cv_buffer;
|
||||
} VDABufferContext;
|
||||
|
||||
static void release_buffer(void *opaque, uint8_t *data)
|
||||
{
|
||||
VDABufferContext *context = opaque;
|
||||
CVPixelBufferUnlockBaseAddress(context->cv_buffer, 0);
|
||||
CVPixelBufferRelease(context->cv_buffer);
|
||||
av_free(context);
|
||||
}
|
||||
|
||||
static int get_buffer2(AVCodecContext *avctx, AVFrame *pic, int flag)
|
||||
{
|
||||
VDABufferContext *context = av_mallocz(sizeof(VDABufferContext));
|
||||
AVBufferRef *buffer = av_buffer_create(NULL, 0, release_buffer, context, 0);
|
||||
if (!context || !buffer) {
|
||||
av_free(context);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
pic->buf[0] = buffer;
|
||||
pic->data[0] = (void *)1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void set_context(AVCodecContext *avctx)
|
||||
{
|
||||
VDADecoderContext *ctx = avctx->priv_data;
|
||||
ctx->hwaccel_context = avctx->hwaccel_context;
|
||||
avctx->hwaccel_context = &ctx->vda_ctx;
|
||||
ctx->get_format = avctx->get_format;
|
||||
avctx->get_format = get_format;
|
||||
ctx->get_buffer2 = avctx->get_buffer2;
|
||||
avctx->get_buffer2 = get_buffer2;
|
||||
}
|
||||
|
||||
static inline void restore_context(AVCodecContext *avctx)
|
||||
{
|
||||
VDADecoderContext *ctx = avctx->priv_data;
|
||||
avctx->hwaccel_context = ctx->hwaccel_context;
|
||||
avctx->get_format = ctx->get_format;
|
||||
avctx->get_buffer2 = ctx->get_buffer2;
|
||||
}
|
||||
|
||||
static int vdadec_decode(AVCodecContext *avctx,
|
||||
void *data, int *got_frame, AVPacket *avpkt)
|
||||
{
|
||||
VDADecoderContext *ctx = avctx->priv_data;
|
||||
AVFrame *pic = data;
|
||||
int ret;
|
||||
|
||||
set_context(avctx);
|
||||
ret = ff_h264_decoder.decode(avctx, data, got_frame, avpkt);
|
||||
restore_context(avctx);
|
||||
if (*got_frame) {
|
||||
AVBufferRef *buffer = pic->buf[0];
|
||||
VDABufferContext *context = av_buffer_get_opaque(buffer);
|
||||
CVPixelBufferRef cv_buffer = (CVPixelBufferRef)pic->data[3];
|
||||
|
||||
CVPixelBufferRetain(cv_buffer);
|
||||
CVPixelBufferLockBaseAddress(cv_buffer, 0);
|
||||
context->cv_buffer = cv_buffer;
|
||||
pic->format = ctx->pix_fmt;
|
||||
if (CVPixelBufferIsPlanar(cv_buffer)) {
|
||||
int i, count = CVPixelBufferGetPlaneCount(cv_buffer);
|
||||
av_assert0(count < 4);
|
||||
for (i = 0; i < count; i++) {
|
||||
pic->data[i] = CVPixelBufferGetBaseAddressOfPlane(cv_buffer, i);
|
||||
pic->linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(cv_buffer, i);
|
||||
}
|
||||
} else {
|
||||
pic->data[0] = CVPixelBufferGetBaseAddress(cv_buffer);
|
||||
pic->linesize[0] = CVPixelBufferGetBytesPerRow(cv_buffer);
|
||||
}
|
||||
}
|
||||
avctx->pix_fmt = ctx->pix_fmt;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static av_cold int vdadec_close(AVCodecContext *avctx)
|
||||
{
|
||||
VDADecoderContext *ctx = avctx->priv_data;
|
||||
/* release buffers and decoder */
|
||||
ff_vda_destroy_decoder(&ctx->vda_ctx);
|
||||
/* close H.264 decoder */
|
||||
if (ctx->h264_initialized) {
|
||||
set_context(avctx);
|
||||
ff_h264_decoder.close(avctx);
|
||||
restore_context(avctx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_cold int vdadec_init(AVCodecContext *avctx)
|
||||
{
|
||||
VDADecoderContext *ctx = avctx->priv_data;
|
||||
struct vda_context *vda_ctx = &ctx->vda_ctx;
|
||||
OSStatus status;
|
||||
int ret, i;
|
||||
|
||||
ctx->h264_initialized = 0;
|
||||
|
||||
/* init pix_fmts of codec */
|
||||
if (!ff_h264_vda_decoder.pix_fmts) {
|
||||
if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber10_7)
|
||||
ff_h264_vda_decoder.pix_fmts = vda_pixfmts_prior_10_7;
|
||||
else
|
||||
ff_h264_vda_decoder.pix_fmts = vda_pixfmts;
|
||||
}
|
||||
|
||||
/* init vda */
|
||||
memset(vda_ctx, 0, sizeof(struct vda_context));
|
||||
vda_ctx->width = avctx->width;
|
||||
vda_ctx->height = avctx->height;
|
||||
vda_ctx->format = 'avc1';
|
||||
vda_ctx->use_sync_decoding = 1;
|
||||
vda_ctx->use_ref_buffer = 1;
|
||||
ctx->pix_fmt = avctx->get_format(avctx, avctx->codec->pix_fmts);
|
||||
switch (ctx->pix_fmt) {
|
||||
case AV_PIX_FMT_UYVY422:
|
||||
vda_ctx->cv_pix_fmt_type = '2vuy';
|
||||
break;
|
||||
case AV_PIX_FMT_YUYV422:
|
||||
vda_ctx->cv_pix_fmt_type = 'yuvs';
|
||||
break;
|
||||
case AV_PIX_FMT_NV12:
|
||||
vda_ctx->cv_pix_fmt_type = '420v';
|
||||
break;
|
||||
case AV_PIX_FMT_YUV420P:
|
||||
vda_ctx->cv_pix_fmt_type = 'y420';
|
||||
break;
|
||||
default:
|
||||
av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format: %d\n", avctx->pix_fmt);
|
||||
goto failed;
|
||||
}
|
||||
status = ff_vda_create_decoder(vda_ctx,
|
||||
avctx->extradata, avctx->extradata_size);
|
||||
if (status != kVDADecoderNoErr) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"Failed to init VDA decoder: %d.\n", status);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
/* init H.264 decoder */
|
||||
set_context(avctx);
|
||||
ret = ff_h264_decoder.init(avctx);
|
||||
restore_context(avctx);
|
||||
if (ret < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Failed to open H.264 decoder.\n");
|
||||
goto failed;
|
||||
}
|
||||
ctx->h264_initialized = 1;
|
||||
|
||||
for (i = 0; i < MAX_SPS_COUNT; i++) {
|
||||
const SPS *sps = ctx->h264ctx.ps.sps_list[i] ? (const SPS*)ctx->h264ctx.ps.sps_list[i]->data : NULL;
|
||||
if (sps && (sps->bit_depth_luma != 8 ||
|
||||
sps->chroma_format_idc == 2 ||
|
||||
sps->chroma_format_idc == 3)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Format is not supported.\n");
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
vdadec_close(avctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void vdadec_flush(AVCodecContext *avctx)
|
||||
{
|
||||
set_context(avctx);
|
||||
ff_h264_decoder.flush(avctx);
|
||||
restore_context(avctx);
|
||||
}
|
||||
|
||||
AVCodec ff_h264_vda_decoder = {
|
||||
.name = "h264_vda",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_H264,
|
||||
.priv_data_size = sizeof(VDADecoderContext),
|
||||
.init = vdadec_init,
|
||||
.close = vdadec_close,
|
||||
.decode = vdadec_decode,
|
||||
.capabilities = AV_CODEC_CAP_DELAY,
|
||||
.flush = vdadec_flush,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("H.264 (VDA acceleration)"),
|
||||
};
|
@ -21,13 +21,9 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#if CONFIG_VIDEOTOOLBOX
|
||||
# include "videotoolbox.h"
|
||||
# include "libavutil/hwcontext_videotoolbox.h"
|
||||
#else
|
||||
# include "vda.h"
|
||||
#endif
|
||||
#include "vda_vt_internal.h"
|
||||
#include "videotoolbox.h"
|
||||
#include "libavutil/hwcontext_videotoolbox.h"
|
||||
#include "vt_internal.h"
|
||||
#include "libavutil/avutil.h"
|
||||
#include "libavutil/hwcontext.h"
|
||||
#include "bytestream.h"
|
||||
|
@ -16,17 +16,8 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_VDA_VT_INTERNAL_H
|
||||
#define AVCODEC_VDA_VT_INTERNAL_H
|
||||
|
||||
void ff_vda_output_callback(void *vda_hw_ctx,
|
||||
CFDictionaryRef user_info,
|
||||
OSStatus status,
|
||||
uint32_t infoFlags,
|
||||
CVImageBufferRef image_buffer);
|
||||
|
||||
int ff_vda_default_init(AVCodecContext *avctx);
|
||||
void ff_vda_default_free(AVCodecContext *avctx);
|
||||
#ifndef AVCODEC_VT_INTERNAL_H
|
||||
#define AVCODEC_VT_INTERNAL_H
|
||||
|
||||
typedef struct VTContext {
|
||||
// The current bitstream buffer.
|
||||
@ -60,4 +51,5 @@ int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx,
|
||||
uint32_t size);
|
||||
CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx);
|
||||
CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx);
|
||||
#endif /* AVCODEC_VDA_VT_INTERNAL_H */
|
||||
|
||||
#endif /* AVCODEC_VT_INTERNAL_H */
|
@ -1670,12 +1670,6 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
|
||||
.log2_chroma_h = 1,
|
||||
.flags = AV_PIX_FMT_FLAG_HWACCEL,
|
||||
},
|
||||
[AV_PIX_FMT_VDA_VLD] = {
|
||||
.name = "vda_vld",
|
||||
.log2_chroma_w = 1,
|
||||
.log2_chroma_h = 1,
|
||||
.flags = AV_PIX_FMT_FLAG_HWACCEL,
|
||||
},
|
||||
[AV_PIX_FMT_YA8] = {
|
||||
.name = "ya8",
|
||||
.nb_components = 2,
|
||||
@ -2029,10 +2023,6 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
|
||||
},
|
||||
.flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE,
|
||||
},
|
||||
[AV_PIX_FMT_VDA] = {
|
||||
.name = "vda",
|
||||
.flags = AV_PIX_FMT_FLAG_HWACCEL,
|
||||
},
|
||||
[AV_PIX_FMT_QSV] = {
|
||||
.name = "qsv",
|
||||
.flags = AV_PIX_FMT_FLAG_HWACCEL,
|
||||
|
@ -176,7 +176,6 @@ enum AVPixelFormat {
|
||||
AV_PIX_FMT_YUV444P10LE,///< planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
|
||||
AV_PIX_FMT_YUV422P9BE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), big-endian
|
||||
AV_PIX_FMT_YUV422P9LE, ///< planar YUV 4:2:2, 18bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
|
||||
AV_PIX_FMT_VDA_VLD, ///< hardware decoding through VDA
|
||||
AV_PIX_FMT_GBRP, ///< planar GBR 4:4:4 24bpp
|
||||
AV_PIX_FMT_GBR24P = AV_PIX_FMT_GBRP, // alias for #AV_PIX_FMT_GBRP
|
||||
AV_PIX_FMT_GBRP9BE, ///< planar GBR 4:4:4 27bpp, big-endian
|
||||
@ -221,8 +220,6 @@ enum AVPixelFormat {
|
||||
|
||||
AV_PIX_FMT_YVYU422, ///< packed YUV 4:2:2, 16bpp, Y0 Cr Y1 Cb
|
||||
|
||||
AV_PIX_FMT_VDA, ///< HW acceleration through VDA, data[3] contains a CVPixelBufferRef
|
||||
|
||||
AV_PIX_FMT_YA16BE, ///< 16 bits gray, 16 bits alpha (big-endian)
|
||||
AV_PIX_FMT_YA16LE, ///< 16 bits gray, 16 bits alpha (little-endian)
|
||||
|
||||
|
@ -41,9 +41,6 @@ unsigned avutil_version(void)
|
||||
if (checks_done)
|
||||
return LIBAVUTIL_VERSION_INT;
|
||||
|
||||
#if FF_API_VDPAU
|
||||
av_assert0(AV_PIX_FMT_VDA_VLD == 81); //check if the pix fmt enum has not had anything inserted or removed by mistake
|
||||
#endif
|
||||
av_assert0(AV_SAMPLE_FMT_DBLP == 9);
|
||||
av_assert0(AVMEDIA_TYPE_ATTACHMENT == 4);
|
||||
av_assert0(AV_PICTURE_TYPE_BI == 7);
|
||||
|
Loading…
Reference in New Issue
Block a user