Deprecated (aka removed) in OSX 10.11, and we have a replacement for it (VideoToolbox).tags/n4.0
@@ -5,6 +5,7 @@ version <next>: | |||||
- Bitstream filters for editing metadata in H.264, HEVC and MPEG-2 streams | - 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 | - Dropped support for OpenJPEG versions 2.0 and below. Using OpenJPEG now | ||||
requires 2.1 (or later) and pkg-config. | requires 2.1 (or later) and pkg-config. | ||||
- VDA dropped (use VideoToolbox instead) | |||||
version 3.4: | version 3.4: | ||||
@@ -244,7 +244,6 @@ Codecs: | |||||
txd.c Ivo van Poorten | txd.c Ivo van Poorten | ||||
vc2* Rostislav Pehlivanov | vc2* Rostislav Pehlivanov | ||||
vcr1.c Michael Niedermayer | vcr1.c Michael Niedermayer | ||||
vda_h264_dec.c Xidorn Quan | |||||
videotoolboxenc.c Rick Kern | videotoolboxenc.c Rick Kern | ||||
vima.c Paul B Mahol | vima.c Paul B Mahol | ||||
vorbisdec.c Denes Balatoni, David Conrad | vorbisdec.c Denes Balatoni, David Conrad | ||||
@@ -318,7 +318,6 @@ External library support: | |||||
--enable-omx-rpi enable OpenMAX IL code for Raspberry Pi [no] | --enable-omx-rpi enable OpenMAX IL code for Raspberry Pi [no] | ||||
--enable-rkmpp enable Rockchip Media Process Platform code [no] | --enable-rkmpp enable Rockchip Media Process Platform code [no] | ||||
--disable-vaapi disable Video Acceleration API (mainly Unix/Intel) code [autodetect] | --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-vdpau disable Nvidia Video Decode and Presentation API for Unix code [autodetect] | ||||
--disable-videotoolbox disable VideoToolbox code [autodetect] | --disable-videotoolbox disable VideoToolbox code [autodetect] | ||||
@@ -1650,7 +1649,6 @@ HWACCEL_AUTODETECT_LIBRARY_LIST=" | |||||
dxva2 | dxva2 | ||||
nvenc | nvenc | ||||
vaapi | vaapi | ||||
vda | |||||
vdpau | vdpau | ||||
videotoolbox | videotoolbox | ||||
v4l2_m2m | v4l2_m2m | ||||
@@ -2660,10 +2658,6 @@ cuda_deps_any="libdl LoadLibrary" | |||||
cuvid_deps="cuda" | cuvid_deps="cuda" | ||||
d3d11va_deps="d3d11_h dxva_h ID3D11VideoDecoder ID3D11VideoContext" | d3d11va_deps="d3d11_h dxva_h ID3D11VideoDecoder ID3D11VideoContext" | ||||
dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32" | 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_deps="videotoolbox pthreads" | ||||
videotoolbox_hwaccel_extralibs="-framework QuartzCore" | videotoolbox_hwaccel_extralibs="-framework QuartzCore" | ||||
xvmc_deps="X11_extensions_XvMClib_h" | xvmc_deps="X11_extensions_XvMClib_h" | ||||
@@ -2685,10 +2679,6 @@ h264_mmal_hwaccel_deps="mmal" | |||||
h264_qsv_hwaccel_deps="libmfx" | h264_qsv_hwaccel_deps="libmfx" | ||||
h264_vaapi_hwaccel_deps="vaapi" | h264_vaapi_hwaccel_deps="vaapi" | ||||
h264_vaapi_hwaccel_select="h264_decoder" | 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_deps="vdpau" | ||||
h264_vdpau_hwaccel_select="h264_decoder" | h264_vdpau_hwaccel_select="h264_decoder" | ||||
h264_videotoolbox_hwaccel_deps="videotoolbox" | h264_videotoolbox_hwaccel_deps="videotoolbox" | ||||
@@ -2822,8 +2812,6 @@ h264_rkmpp_decoder_deps="rkmpp" | |||||
h264_rkmpp_decoder_select="h264_mp4toannexb_bsf" | h264_rkmpp_decoder_select="h264_mp4toannexb_bsf" | ||||
h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264" | h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264" | ||||
h264_vaapi_encoder_select="cbs_h264 vaapi_encode" | 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_deps="vdpau" | ||||
h264_vdpau_decoder_select="h264_decoder" | h264_vdpau_decoder_select="h264_decoder" | ||||
h264_v4l2m2m_decoder_deps="v4l2_m2m h264_v4l2_m2m" | h264_v4l2m2m_decoder_deps="v4l2_m2m h264_v4l2_m2m" | ||||
@@ -3011,7 +2999,6 @@ libzvbi_teletext_decoder_deps="libzvbi" | |||||
videotoolbox_suggest="coreservices" | videotoolbox_suggest="coreservices" | ||||
videotoolbox_deps="corefoundation coremedia corevideo" | videotoolbox_deps="corefoundation coremedia corevideo" | ||||
videotoolbox_encoder_deps="videotoolbox VTCompressionSessionPrepareToEncodeFrames" | videotoolbox_encoder_deps="videotoolbox VTCompressionSessionPrepareToEncodeFrames" | ||||
videotoolbox_encoder_suggest="vda_framework" | |||||
# demuxers / muxers | # demuxers / muxers | ||||
ac3_demuxer_select="ac3_parser" | ac3_demuxer_select="ac3_parser" | ||||
@@ -5847,7 +5834,6 @@ check_header sys/un.h | |||||
check_header termios.h | check_header termios.h | ||||
check_header unistd.h | check_header unistd.h | ||||
check_header valgrind/valgrind.h | check_header valgrind/valgrind.h | ||||
check_header VideoDecodeAcceleration/VDADecoder.h | |||||
check_func_headers VideoToolbox/VTCompressionSession.h VTCompressionSessionPrepareToEncodeFrames -framework VideoToolbox | check_func_headers VideoToolbox/VTCompressionSession.h VTCompressionSessionPrepareToEncodeFrames -framework VideoToolbox | ||||
check_header windows.h | check_header windows.h | ||||
check_header X11/extensions/XvMClib.h | check_header X11/extensions/XvMClib.h | ||||
@@ -786,9 +786,6 @@ Do not use any hardware acceleration (the default). | |||||
@item auto | @item auto | ||||
Automatically select the hardware acceleration method. | Automatically select the hardware acceleration method. | ||||
@item vda | |||||
Use Apple VDA hardware acceleration. | |||||
@item vdpau | @item vdpau | ||||
Use VDPAU (Video Decode and Presentation API for Unix) hardware acceleration. | Use VDPAU (Video Decode and Presentation API for Unix) hardware acceleration. | ||||
@@ -63,7 +63,6 @@ enum HWAccelID { | |||||
HWACCEL_AUTO, | HWACCEL_AUTO, | ||||
HWACCEL_VDPAU, | HWACCEL_VDPAU, | ||||
HWACCEL_DXVA2, | HWACCEL_DXVA2, | ||||
HWACCEL_VDA, | |||||
HWACCEL_VIDEOTOOLBOX, | HWACCEL_VIDEOTOOLBOX, | ||||
HWACCEL_QSV, | HWACCEL_QSV, | ||||
HWACCEL_VAAPI, | 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 ffmpeg_parse_options(int argc, char **argv); | ||||
int vda_init(AVCodecContext *s); | |||||
int videotoolbox_init(AVCodecContext *s); | int videotoolbox_init(AVCodecContext *s); | ||||
int qsv_init(AVCodecContext *s); | int qsv_init(AVCodecContext *s); | ||||
int cuvid_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, | { "dxva2", hwaccel_decode_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD, | ||||
AV_HWDEVICE_TYPE_DXVA2 }, | AV_HWDEVICE_TYPE_DXVA2 }, | ||||
#endif | #endif | ||||
#if CONFIG_VDA | |||||
{ "vda", videotoolbox_init, HWACCEL_VDA, AV_PIX_FMT_VDA, | |||||
AV_HWDEVICE_TYPE_NONE }, | |||||
#endif | |||||
#if CONFIG_VIDEOTOOLBOX | #if CONFIG_VIDEOTOOLBOX | ||||
{ "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX, | { "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX, | ||||
AV_HWDEVICE_TYPE_NONE }, | AV_HWDEVICE_TYPE_NONE }, | ||||
@@ -3631,7 +3627,7 @@ const OptionDef options[] = { | |||||
{ "hwaccel_output_format", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | | { "hwaccel_output_format", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | | ||||
OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_output_formats) }, | OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_output_formats) }, | ||||
"select output format used with HW accelerated decoding", "format" }, | "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}, "" }, | { "videotoolbox_pixfmt", HAS_ARG | OPT_STRING | OPT_EXPERT, { &videotoolbox_pixfmt}, "" }, | ||||
#endif | #endif | ||||
{ "hwaccels", OPT_EXIT, { .func_arg = show_hwaccels }, | { "hwaccels", OPT_EXIT, { .func_arg = show_hwaccels }, | ||||
@@ -23,12 +23,7 @@ | |||||
#endif | #endif | ||||
#include "libavcodec/avcodec.h" | #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 "libavutil/imgutils.h" | ||||
#include "ffmpeg.h" | #include "ffmpeg.h" | ||||
@@ -114,15 +109,7 @@ static void videotoolbox_uninit(AVCodecContext *s) | |||||
av_frame_free(&vt->tmp_frame); | 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); | av_freep(&ist->hwaccel_ctx); | ||||
} | } | ||||
@@ -147,8 +134,7 @@ int videotoolbox_init(AVCodecContext *s) | |||||
goto fail; | goto fail; | ||||
} | } | ||||
if (ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX) { | |||||
#if CONFIG_VIDEOTOOLBOX | |||||
// TODO: reindent | |||||
if (!videotoolbox_pixfmt) { | if (!videotoolbox_pixfmt) { | ||||
ret = av_videotoolbox_default_init(s); | ret = av_videotoolbox_default_init(s); | ||||
} else { | } else { | ||||
@@ -166,31 +152,8 @@ int videotoolbox_init(AVCodecContext *s) | |||||
ret = av_videotoolbox_default_init2(s, vtctx); | ret = av_videotoolbox_default_init2(s, vtctx); | ||||
CFRelease(pixfmt_str); | 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) { | 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; | goto fail; | ||||
} | } | ||||
@@ -12,7 +12,6 @@ HEADERS = avcodec.h \ | |||||
mediacodec.h \ | mediacodec.h \ | ||||
qsv.h \ | qsv.h \ | ||||
vaapi.h \ | vaapi.h \ | ||||
vda.h \ | |||||
vdpau.h \ | vdpau.h \ | ||||
version.h \ | version.h \ | ||||
videotoolbox.h \ | videotoolbox.h \ | ||||
@@ -338,7 +337,6 @@ OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o | |||||
OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o | OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o | ||||
OBJS-$(CONFIG_NVENC_ENCODER) += nvenc_h264.o | OBJS-$(CONFIG_NVENC_ENCODER) += nvenc_h264.o | ||||
OBJS-$(CONFIG_NVENC_H264_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_OMX_ENCODER) += omx.o | ||||
OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec_h2645.o | OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec_h2645.o | ||||
OBJS-$(CONFIG_H264_QSV_ENCODER) += qsvenc_h264.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_D3D11VA) += dxva2.o | ||||
OBJS-$(CONFIG_DXVA2) += dxva2.o | OBJS-$(CONFIG_DXVA2) += dxva2.o | ||||
OBJS-$(CONFIG_VAAPI) += vaapi_decode.o | OBJS-$(CONFIG_VAAPI) += vaapi_decode.o | ||||
OBJS-$(CONFIG_VDA) += vda.o videotoolbox.o | |||||
OBJS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.o | OBJS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.o | ||||
OBJS-$(CONFIG_VDPAU) += vdpau.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_DXVA2_HWACCEL) += dxva2_h264.o | ||||
OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec_h2645.o | OBJS-$(CONFIG_H264_QSV_HWACCEL) += qsvdec_h2645.o | ||||
OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.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_VDPAU_HWACCEL) += vdpau_h264.o | ||||
OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o | OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o | ||||
OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL) += dxva2_hevc.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_QSVENC) += qsvenc.h | ||||
SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h | SKIPHEADERS-$(CONFIG_XVMC) += xvmc.h | ||||
SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_decode.h vaapi_encode.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_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 | SKIPHEADERS-$(CONFIG_V4L2_M2M) += v4l2_buffers.h v4l2_context.h v4l2_m2m.h | ||||
TESTPROGS = avpacket \ | TESTPROGS = avpacket \ | ||||
@@ -72,8 +72,6 @@ static void register_all(void) | |||||
REGISTER_HWACCEL(H264_MMAL, h264_mmal); | REGISTER_HWACCEL(H264_MMAL, h264_mmal); | ||||
REGISTER_HWACCEL(H264_QSV, h264_qsv); | REGISTER_HWACCEL(H264_QSV, h264_qsv); | ||||
REGISTER_HWACCEL(H264_VAAPI, h264_vaapi); | 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_VDPAU, h264_vdpau); | ||||
REGISTER_HWACCEL(H264_VIDEOTOOLBOX, h264_videotoolbox); | REGISTER_HWACCEL(H264_VIDEOTOOLBOX, h264_videotoolbox); | ||||
REGISTER_HWACCEL(HEVC_CUVID, hevc_cuvid); | REGISTER_HWACCEL(HEVC_CUVID, hevc_cuvid); | ||||
@@ -217,7 +215,6 @@ static void register_all(void) | |||||
REGISTER_DECODER(H264_MMAL, h264_mmal); | REGISTER_DECODER(H264_MMAL, h264_mmal); | ||||
REGISTER_DECODER(H264_QSV, h264_qsv); | REGISTER_DECODER(H264_QSV, h264_qsv); | ||||
REGISTER_DECODER(H264_RKMPP, h264_rkmpp); | REGISTER_DECODER(H264_RKMPP, h264_rkmpp); | ||||
REGISTER_DECODER(H264_VDA, h264_vda); | |||||
#if FF_API_VDPAU | #if FF_API_VDPAU | ||||
REGISTER_DECODER(H264_VDPAU, h264_vdpau); | REGISTER_DECODER(H264_VDPAU, h264_vdpau); | ||||
#endif | #endif | ||||
@@ -755,7 +755,6 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) | |||||
#define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \ | #define HWACCEL_MAX (CONFIG_H264_DXVA2_HWACCEL + \ | ||||
(CONFIG_H264_D3D11VA_HWACCEL * 2) + \ | (CONFIG_H264_D3D11VA_HWACCEL * 2) + \ | ||||
CONFIG_H264_VAAPI_HWACCEL + \ | CONFIG_H264_VAAPI_HWACCEL + \ | ||||
(CONFIG_H264_VDA_HWACCEL * 2) + \ | |||||
CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \ | CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \ | ||||
CONFIG_H264_VDPAU_HWACCEL) | CONFIG_H264_VDPAU_HWACCEL) | ||||
enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts; | 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 | #if CONFIG_H264_VAAPI_HWACCEL | ||||
*fmt++ = AV_PIX_FMT_VAAPI; | *fmt++ = AV_PIX_FMT_VAAPI; | ||||
#endif | #endif | ||||
#if CONFIG_H264_VDA_HWACCEL | |||||
*fmt++ = AV_PIX_FMT_VDA_VLD; | |||||
*fmt++ = AV_PIX_FMT_VDA; | |||||
#endif | |||||
#if CONFIG_H264_VIDEOTOOLBOX_HWACCEL | #if CONFIG_H264_VIDEOTOOLBOX_HWACCEL | ||||
*fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; | *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; | ||||
#endif | #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 |
@@ -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" | #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/avutil.h" | ||||
#include "libavutil/hwcontext.h" | #include "libavutil/hwcontext.h" | ||||
#include "bytestream.h" | #include "bytestream.h" | ||||
@@ -16,17 +16,8 @@ | |||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | * 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 { | typedef struct VTContext { | ||||
// The current bitstream buffer. | // The current bitstream buffer. | ||||
@@ -60,4 +51,5 @@ int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx, | |||||
uint32_t size); | uint32_t size); | ||||
CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx); | CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx); | ||||
CFDataRef ff_videotoolbox_hvcc_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, | .log2_chroma_h = 1, | ||||
.flags = AV_PIX_FMT_FLAG_HWACCEL, | .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] = { | [AV_PIX_FMT_YA8] = { | ||||
.name = "ya8", | .name = "ya8", | ||||
.nb_components = 2, | .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, | .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] = { | [AV_PIX_FMT_QSV] = { | ||||
.name = "qsv", | .name = "qsv", | ||||
.flags = AV_PIX_FMT_FLAG_HWACCEL, | .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_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_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_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_GBRP, ///< planar GBR 4:4:4 24bpp | ||||
AV_PIX_FMT_GBR24P = AV_PIX_FMT_GBRP, // alias for #AV_PIX_FMT_GBRP | 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 | 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_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_YA16BE, ///< 16 bits gray, 16 bits alpha (big-endian) | ||||
AV_PIX_FMT_YA16LE, ///< 16 bits gray, 16 bits alpha (little-endian) | AV_PIX_FMT_YA16LE, ///< 16 bits gray, 16 bits alpha (little-endian) | ||||
@@ -41,9 +41,6 @@ unsigned avutil_version(void) | |||||
if (checks_done) | if (checks_done) | ||||
return LIBAVUTIL_VERSION_INT; | 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(AV_SAMPLE_FMT_DBLP == 9); | ||||
av_assert0(AVMEDIA_TYPE_ATTACHMENT == 4); | av_assert0(AVMEDIA_TYPE_ATTACHMENT == 4); | ||||
av_assert0(AV_PICTURE_TYPE_BI == 7); | av_assert0(AV_PICTURE_TYPE_BI == 7); | ||||