avcodec/cuvid: add cuvid decoder

This commit is contained in:
Timo Rothenpieler 2016-06-04 19:06:52 +02:00
parent 24f5136196
commit 88e8aef9e9
7 changed files with 751 additions and 1 deletions

View File

@ -40,6 +40,8 @@ version <next>:
- MagicYUV decoder - MagicYUV decoder
- OpenExr improvements (tile data and B44/B44A support) - OpenExr improvements (tile data and B44/B44A support)
- BitJazz SheerVideo decoder - BitJazz SheerVideo decoder
- CUDA CUVID H264/HEVC decoder
version 3.0: version 3.0:
- Common Encryption (CENC) MP4 encoding and decoding support - Common Encryption (CENC) MP4 encoding and decoding support

View File

@ -163,6 +163,7 @@ Codecs:
cpia.c Stephan Hilb cpia.c Stephan Hilb
crystalhd.c Philip Langdale crystalhd.c Philip Langdale
cscd.c Reimar Doeffinger cscd.c Reimar Doeffinger
cuvid.c Timo Rothenpieler
dca.c Kostya Shishkov, Benjamin Larsson dca.c Kostya Shishkov, Benjamin Larsson
dirac* Rostislav Pehlivanov dirac* Rostislav Pehlivanov
dnxhd* Baptiste Coudurier dnxhd* Baptiste Coudurier

34
configure vendored
View File

@ -158,6 +158,7 @@ Hardware accelerators:
Hardware-accelerated decoding/encoding: Hardware-accelerated decoding/encoding:
--enable-cuda enable dynamically linked CUDA [no] --enable-cuda enable dynamically linked CUDA [no]
--enable-cuvid enable CUVID support [autodetect]
--enable-libmfx enable HW acceleration through libmfx --enable-libmfx enable HW acceleration through libmfx
--enable-mmal enable decoding via MMAL [no] --enable-mmal enable decoding via MMAL [no]
--enable-nvenc enable NVIDIA NVENC support [no] --enable-nvenc enable NVIDIA NVENC support [no]
@ -1567,6 +1568,7 @@ FEATURE_LIST="
HW_CODECS_LIST=" HW_CODECS_LIST="
cuda cuda
cuvid
libmfx libmfx
mmal mmal
nvenc nvenc
@ -2522,6 +2524,7 @@ audiotoolbox_extralibs="-framework CoreFoundation -framework AudioToolbox -frame
# hardware accelerators # hardware accelerators
crystalhd_deps="libcrystalhd_libcrystalhd_if_h" crystalhd_deps="libcrystalhd_libcrystalhd_if_h"
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" dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode"
vaapi_deps="va_va_h" vaapi_deps="va_va_h"
@ -2539,6 +2542,7 @@ h263_vaapi_hwaccel_select="h263_decoder"
h263_videotoolbox_hwaccel_deps="videotoolbox" h263_videotoolbox_hwaccel_deps="videotoolbox"
h263_videotoolbox_hwaccel_select="h263_decoder" h263_videotoolbox_hwaccel_select="h263_decoder"
h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser" h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser"
h264_cuvid_hwaccel_deps="cuda cuvid CUVIDH264PICPARAMS"
h264_d3d11va_hwaccel_deps="d3d11va" h264_d3d11va_hwaccel_deps="d3d11va"
h264_d3d11va_hwaccel_select="h264_decoder" h264_d3d11va_hwaccel_select="h264_decoder"
h264_dxva2_hwaccel_deps="dxva2" h264_dxva2_hwaccel_deps="dxva2"
@ -2564,6 +2568,7 @@ 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"
h264_videotoolbox_hwaccel_select="h264_decoder" h264_videotoolbox_hwaccel_select="h264_decoder"
hevc_cuvid_hwaccel_deps="cuda cuvid CUVIDHEVCPICPARAMS"
hevc_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_HEVC" hevc_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_HEVC"
hevc_d3d11va_hwaccel_select="hevc_decoder" hevc_d3d11va_hwaccel_select="hevc_decoder"
hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC" hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC"
@ -2618,6 +2623,7 @@ mpeg4_videotoolbox_hwaccel_deps="videotoolbox"
mpeg4_videotoolbox_hwaccel_select="mpeg4_decoder" mpeg4_videotoolbox_hwaccel_select="mpeg4_decoder"
msmpeg4_crystalhd_decoder_select="crystalhd" msmpeg4_crystalhd_decoder_select="crystalhd"
vc1_crystalhd_decoder_select="crystalhd" vc1_crystalhd_decoder_select="crystalhd"
vc1_cuvid_hwaccel_deps="cuda cuvid CUVIDVC1PICPARAMS"
vc1_d3d11va_hwaccel_deps="d3d11va" vc1_d3d11va_hwaccel_deps="d3d11va"
vc1_d3d11va_hwaccel_select="vc1_decoder" vc1_d3d11va_hwaccel_select="vc1_decoder"
vc1_dxva2_hwaccel_deps="dxva2" vc1_dxva2_hwaccel_deps="dxva2"
@ -2633,6 +2639,8 @@ vc1_vdpau_decoder_deps="vdpau"
vc1_vdpau_decoder_select="vc1_decoder" vc1_vdpau_decoder_select="vc1_decoder"
vc1_vdpau_hwaccel_deps="vdpau" vc1_vdpau_hwaccel_deps="vdpau"
vc1_vdpau_hwaccel_select="vc1_decoder" vc1_vdpau_hwaccel_select="vc1_decoder"
vp8_cuvid_hwaccel_deps="cuda cuvid CUVIDVP9PICPARAMS"
vp9_cuvid_hwaccel_deps="cuda cuvid CUVIDVP9PICPARAMS"
vp9_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_VP9" vp9_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_VP9"
vp9_d3d11va_hwaccel_select="vp9_decoder" vp9_d3d11va_hwaccel_select="vp9_decoder"
vp9_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_VP9" vp9_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_VP9"
@ -2657,6 +2665,8 @@ hwupload_cuda_filter_deps="cuda"
scale_npp_filter_deps="cuda libnpp" scale_npp_filter_deps="cuda libnpp"
nvenc_encoder_deps="nvenc" nvenc_encoder_deps="nvenc"
h264_cuvid_decoder_deps="cuda cuvid CUVIDH264PICPARAMS"
h264_cuvid_decoder_select="h264_mp4toannexb_bsf h264_cuvid_hwaccel"
h264_qsv_decoder_deps="libmfx" h264_qsv_decoder_deps="libmfx"
h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec h264_qsv_hwaccel" h264_qsv_decoder_select="h264_mp4toannexb_bsf h264_parser qsvdec h264_qsv_hwaccel"
h264_qsv_encoder_deps="libmfx" h264_qsv_encoder_deps="libmfx"
@ -2664,6 +2674,8 @@ h264_qsv_encoder_select="qsvenc"
h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264" h264_vaapi_encoder_deps="VAEncPictureParameterBufferH264"
h264_vaapi_encoder_select="vaapi_encode golomb" h264_vaapi_encoder_select="vaapi_encode golomb"
hevc_cuvid_decoder_deps="cuda cuvid CUVIDHEVCPICPARAMS"
hevc_cuvid_decoder_select="hevc_mp4toannexb_bsf hevc_cuvid_hwaccel"
hevc_qsv_decoder_deps="libmfx" hevc_qsv_decoder_deps="libmfx"
hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser qsvdec hevc_qsv_hwaccel" hevc_qsv_decoder_select="hevc_mp4toannexb_bsf hevc_parser qsvdec hevc_qsv_hwaccel"
hevc_qsv_encoder_deps="libmfx" hevc_qsv_encoder_deps="libmfx"
@ -2677,6 +2689,13 @@ mpeg2_qsv_encoder_select="qsvenc"
nvenc_h264_encoder_deps="nvenc" nvenc_h264_encoder_deps="nvenc"
nvenc_hevc_encoder_deps="nvenc" nvenc_hevc_encoder_deps="nvenc"
vc1_cuvid_decoder_deps="cuda cuvid CUVIDVC1PICPARAMS"
vc1_cuvid_decoder_select="vc1_cuvid_hwaccel"
vp8_cuvid_decoder_deps="cuda cuvid CUVIDVP9PICPARAMS"
vp8_cuvid_decoder_select="vp8_cuvid_hwaccel"
vp9_cuvid_decoder_deps="cuda cuvid CUVIDVP9PICPARAMS"
vp9_cuvid_decoder_select="vp9_cuvid_hwaccel"
# parsers # parsers
h264_parser_select="h264_decoder" h264_parser_select="h264_decoder"
hevc_parser_select="golomb" hevc_parser_select="golomb"
@ -5002,6 +5021,7 @@ die_license_disabled gpl libxvid
die_license_disabled gpl x11grab die_license_disabled gpl x11grab
die_license_disabled nonfree cuda die_license_disabled nonfree cuda
die_license_disabled nonfree cuvid
die_license_disabled nonfree libfaac die_license_disabled nonfree libfaac
die_license_disabled nonfree libnpp die_license_disabled nonfree libnpp
enabled gpl && die_license_disabled_gpl nonfree libfdk_aac enabled gpl && die_license_disabled_gpl nonfree libfdk_aac
@ -5509,6 +5529,11 @@ check_type "va/va.h va/va_enc_jpeg.h" "VAEncPictureParameterBufferJPEG"
check_type "vdpau/vdpau.h" "VdpPictureInfoHEVC" check_type "vdpau/vdpau.h" "VdpPictureInfoHEVC"
check_type "cuviddec.h" "CUVIDH264PICPARAMS"
check_type "cuviddec.h" "CUVIDHEVCPICPARAMS"
check_type "cuviddec.h" "CUVIDVC1PICPARAMS"
check_type "cuviddec.h" "CUVIDVP9PICPARAMS"
check_cpp_condition windows.h "!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)" && enable winrt || disable winrt check_cpp_condition windows.h "!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)" && enable winrt || disable winrt
if ! disabled w32threads && ! enabled pthreads; then if ! disabled w32threads && ! enabled pthreads; then
@ -5572,6 +5597,11 @@ for func in $COMPLEX_FUNCS; do
eval check_complexfunc $func \${${func}_args:-1} eval check_complexfunc $func \${${func}_args:-1}
done done
# Enable CUVID by default if CUDA is enabled
if enabled cuda && ! disabled cuvid; then
enable cuvid
fi
# these are off by default, so fail if requested and not available # these are off by default, so fail if requested and not available
enabled avfoundation_indev && { check_header_objcc AVFoundation/AVFoundation.h || disable avfoundation_indev; } enabled avfoundation_indev && { check_header_objcc AVFoundation/AVFoundation.h || disable avfoundation_indev; }
enabled avfoundation_indev && { check_lib2 CoreGraphics/CoreGraphics.h CGGetActiveDisplayList -framework CoreGraphics || enabled avfoundation_indev && { check_lib2 CoreGraphics/CoreGraphics.h CGGetActiveDisplayList -framework CoreGraphics ||
@ -5581,6 +5611,10 @@ enabled avisynth && { { check_lib2 "windows.h" LoadLibrary; } ||
die "ERROR: LoadLibrary/dlopen not found for avisynth"; } die "ERROR: LoadLibrary/dlopen not found for avisynth"; }
enabled cuda && { check_lib cuda.h cuInit -lcuda || enabled cuda && { check_lib cuda.h cuInit -lcuda ||
die "ERROR: CUDA not found"; } die "ERROR: CUDA not found"; }
enabled cuvid && { check_lib cuviddec.h cuvidCreateDecoder -lnvcuvid ||
die "ERROR: CUVID not found"; } &&
{ enabled cuda ||
die "ERROR: CUVID requires CUDA"; }
enabled chromaprint && require chromaprint chromaprint.h chromaprint_get_version -lchromaprint enabled chromaprint && require chromaprint chromaprint.h chromaprint_get_version -lchromaprint
enabled coreimage_filter && { check_header_objcc QuartzCore/CoreImage.h || disable coreimage_filter; } enabled coreimage_filter && { check_header_objcc QuartzCore/CoreImage.h || disable coreimage_filter; }
enabled coreimagesrc_filter && { check_header_objcc QuartzCore/CoreImage.h || disable coreimagesrc_filter; } enabled coreimagesrc_filter && { check_header_objcc QuartzCore/CoreImage.h || disable coreimagesrc_filter; }

View File

@ -768,12 +768,14 @@ OBJS-$(CONFIG_QSV) += qsv.o
OBJS-$(CONFIG_QSVDEC) += qsvdec.o OBJS-$(CONFIG_QSVDEC) += qsvdec.o
OBJS-$(CONFIG_QSVENC) += qsvenc.o OBJS-$(CONFIG_QSVENC) += qsvenc.o
OBJS-$(CONFIG_H264_CUVID_DECODER) += cuvid.o
OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o
OBJS-$(CONFIG_H264_VDA_DECODER) += vda_h264_dec.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
OBJS-$(CONFIG_H264_VAAPI_ENCODER) += vaapi_encode_h264.o vaapi_encode_h26x.o OBJS-$(CONFIG_H264_VAAPI_ENCODER) += vaapi_encode_h264.o vaapi_encode_h26x.o
OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuvid.o
OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec_h2645.o OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec_h2645.o
OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o h2645_parse.o OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o h2645_parse.o
OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o vaapi_encode_h26x.o OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o vaapi_encode_h26x.o
@ -784,6 +786,9 @@ OBJS-$(CONFIG_MPEG4_OMX_ENCODER) += omx.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_NVENC_HEVC_ENCODER) += nvenc_hevc.o OBJS-$(CONFIG_NVENC_HEVC_ENCODER) += nvenc_hevc.o
OBJS-$(CONFIG_VC1_CUVID_DECODER) += cuvid.o
OBJS-$(CONFIG_VP8_CUVID_DECODER) += cuvid.o
OBJS-$(CONFIG_VP9_CUVID_DECODER) += cuvid.o
# libavformat dependencies # libavformat dependencies
OBJS-$(CONFIG_ISO_MEDIA) += mpeg4audio.o mpegaudiodata.o OBJS-$(CONFIG_ISO_MEDIA) += mpeg4audio.o mpegaudiodata.o

View File

@ -69,6 +69,7 @@ void avcodec_register_all(void)
/* hardware accelerators */ /* hardware accelerators */
REGISTER_HWACCEL(H263_VAAPI, h263_vaapi); REGISTER_HWACCEL(H263_VAAPI, h263_vaapi);
REGISTER_HWACCEL(H263_VIDEOTOOLBOX, h263_videotoolbox); REGISTER_HWACCEL(H263_VIDEOTOOLBOX, h263_videotoolbox);
REGISTER_HWACCEL(H264_CUVID, h264_cuvid);
REGISTER_HWACCEL(H264_D3D11VA, h264_d3d11va); REGISTER_HWACCEL(H264_D3D11VA, h264_d3d11va);
REGISTER_HWACCEL(H264_DXVA2, h264_dxva2); REGISTER_HWACCEL(H264_DXVA2, h264_dxva2);
REGISTER_HWACCEL(H264_MMAL, h264_mmal); REGISTER_HWACCEL(H264_MMAL, h264_mmal);
@ -78,6 +79,7 @@ void avcodec_register_all(void)
REGISTER_HWACCEL(H264_VDA_OLD, h264_vda_old); 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_D3D11VA, hevc_d3d11va); REGISTER_HWACCEL(HEVC_D3D11VA, hevc_d3d11va);
REGISTER_HWACCEL(HEVC_DXVA2, hevc_dxva2); REGISTER_HWACCEL(HEVC_DXVA2, hevc_dxva2);
REGISTER_HWACCEL(HEVC_QSV, hevc_qsv); REGISTER_HWACCEL(HEVC_QSV, hevc_qsv);
@ -98,12 +100,15 @@ void avcodec_register_all(void)
REGISTER_HWACCEL(MPEG4_VAAPI, mpeg4_vaapi); REGISTER_HWACCEL(MPEG4_VAAPI, mpeg4_vaapi);
REGISTER_HWACCEL(MPEG4_VDPAU, mpeg4_vdpau); REGISTER_HWACCEL(MPEG4_VDPAU, mpeg4_vdpau);
REGISTER_HWACCEL(MPEG4_VIDEOTOOLBOX, mpeg4_videotoolbox); REGISTER_HWACCEL(MPEG4_VIDEOTOOLBOX, mpeg4_videotoolbox);
REGISTER_HWACCEL(VC1_CUVID, vc1_cuvid);
REGISTER_HWACCEL(VC1_D3D11VA, vc1_d3d11va); REGISTER_HWACCEL(VC1_D3D11VA, vc1_d3d11va);
REGISTER_HWACCEL(VC1_DXVA2, vc1_dxva2); REGISTER_HWACCEL(VC1_DXVA2, vc1_dxva2);
REGISTER_HWACCEL(VC1_VAAPI, vc1_vaapi); REGISTER_HWACCEL(VC1_VAAPI, vc1_vaapi);
REGISTER_HWACCEL(VC1_VDPAU, vc1_vdpau); REGISTER_HWACCEL(VC1_VDPAU, vc1_vdpau);
REGISTER_HWACCEL(VC1_MMAL, vc1_mmal); REGISTER_HWACCEL(VC1_MMAL, vc1_mmal);
REGISTER_HWACCEL(VC1_QSV, vc1_qsv); REGISTER_HWACCEL(VC1_QSV, vc1_qsv);
REGISTER_HWACCEL(VP8_CUVID, vp8_cuvid);
REGISTER_HWACCEL(VP9_CUVID, vp9_cuvid);
REGISTER_HWACCEL(VP9_D3D11VA, vp9_d3d11va); REGISTER_HWACCEL(VP9_D3D11VA, vp9_d3d11va);
REGISTER_HWACCEL(VP9_DXVA2, vp9_dxva2); REGISTER_HWACCEL(VP9_DXVA2, vp9_dxva2);
REGISTER_HWACCEL(VP9_VAAPI, vp9_vaapi); REGISTER_HWACCEL(VP9_VAAPI, vp9_vaapi);
@ -618,6 +623,7 @@ void avcodec_register_all(void)
/* external libraries, that shouldn't be used by default if one of the /* external libraries, that shouldn't be used by default if one of the
* above is available */ * above is available */
REGISTER_ENCODER(LIBOPENH264, libopenh264); REGISTER_ENCODER(LIBOPENH264, libopenh264);
REGISTER_DECODER(H264_CUVID, h264_cuvid);
REGISTER_ENCODER(H264_QSV, h264_qsv); REGISTER_ENCODER(H264_QSV, h264_qsv);
REGISTER_ENCODER(H264_VAAPI, h264_vaapi); REGISTER_ENCODER(H264_VAAPI, h264_vaapi);
REGISTER_ENCODER(H264_VIDEOTOOLBOX, h264_videotoolbox); REGISTER_ENCODER(H264_VIDEOTOOLBOX, h264_videotoolbox);
@ -625,11 +631,15 @@ void avcodec_register_all(void)
REGISTER_ENCODER(H264_OMX, h264_omx); REGISTER_ENCODER(H264_OMX, h264_omx);
REGISTER_ENCODER(NVENC_H264, nvenc_h264); REGISTER_ENCODER(NVENC_H264, nvenc_h264);
REGISTER_ENCODER(NVENC_HEVC, nvenc_hevc); REGISTER_ENCODER(NVENC_HEVC, nvenc_hevc);
REGISTER_DECODER(HEVC_CUVID, hevc_cuvid);
REGISTER_ENCODER(HEVC_QSV, hevc_qsv); REGISTER_ENCODER(HEVC_QSV, hevc_qsv);
REGISTER_ENCODER(HEVC_VAAPI, hevc_vaapi); REGISTER_ENCODER(HEVC_VAAPI, hevc_vaapi);
REGISTER_ENCODER(LIBKVAZAAR, libkvazaar); REGISTER_ENCODER(LIBKVAZAAR, libkvazaar);
REGISTER_ENCODER(MJPEG_VAAPI, mjpeg_vaapi); REGISTER_ENCODER(MJPEG_VAAPI, mjpeg_vaapi);
REGISTER_ENCODER(MPEG2_QSV, mpeg2_qsv); REGISTER_ENCODER(MPEG2_QSV, mpeg2_qsv);
REGISTER_DECODER(VC1_CUVID, vc1_cuvid);
REGISTER_DECODER(VP8_CUVID, vp8_cuvid);
REGISTER_DECODER(VP9_CUVID, vp9_cuvid);
/* parsers */ /* parsers */
REGISTER_PARSER(AAC, aac); REGISTER_PARSER(AAC, aac);

698
libavcodec/cuvid.c Normal file
View File

@ -0,0 +1,698 @@
/*
* Nvidia CUVID decoder
* Copyright (c) 2016 Timo Rothenpieler <timo@rothenpieler.org>
*
* 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 "libavutil/buffer.h"
#include "libavutil/mathematics.h"
#include "libavutil/hwcontext.h"
#include "libavutil/hwcontext_cuda.h"
#include "libavutil/fifo.h"
#include "libavutil/log.h"
#include "avcodec.h"
#include "internal.h"
#include <nvcuvid.h>
#define MAX_FRAME_COUNT 20
typedef struct CuvidContext
{
CUvideodecoder cudecoder;
CUvideoparser cuparser;
AVBufferRef *hwdevice;
AVBufferRef *hwframe;
AVBSFContext *bsf;
AVFifoBuffer *frame_queue;
int internal_error;
cudaVideoCodec codec_type;
cudaVideoChromaFormat chroma_format;
} CuvidContext;
static int check_cu(AVCodecContext *avctx, CUresult err, const char *func)
{
const char *err_name;
const char *err_string;
av_log(avctx, AV_LOG_TRACE, "Calling %s\n", func);
if (err == CUDA_SUCCESS)
return 0;
cuGetErrorName(err, &err_name);
cuGetErrorString(err, &err_string);
av_log(avctx, AV_LOG_ERROR, "%s failed", func);
if (err_name && err_string)
av_log(avctx, AV_LOG_ERROR, " -> %s: %s", err_name, err_string);
av_log(avctx, AV_LOG_ERROR, "\n");
return AVERROR_EXTERNAL;
}
#define CHECK_CU(x) check_cu(avctx, (x), #x)
static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* format)
{
AVCodecContext *avctx = opaque;
CuvidContext *ctx = avctx->priv_data;
AVHWFramesContext *hwframe_ctx = (AVHWFramesContext*)ctx->hwframe->data;
CUVIDDECODECREATEINFO cuinfo;
av_log(avctx, AV_LOG_TRACE, "pfnSequenceCallback\n");
ctx->internal_error = 0;
avctx->width = format->display_area.right;
avctx->height = format->display_area.bottom;
ff_set_sar(avctx, av_div_q(
(AVRational){ format->display_aspect_ratio.x, format->display_aspect_ratio.y },
(AVRational){ avctx->width, avctx->height }));
if (!format->progressive_sequence)
avctx->flags |= AV_CODEC_FLAG_INTERLACED_DCT;
else
avctx->flags &= ~AV_CODEC_FLAG_INTERLACED_DCT;
if (format->video_signal_description.video_full_range_flag)
avctx->color_range = AVCOL_RANGE_JPEG;
else
avctx->color_range = AVCOL_RANGE_MPEG;
avctx->color_primaries = format->video_signal_description.color_primaries;
avctx->color_trc = format->video_signal_description.transfer_characteristics;
avctx->colorspace = format->video_signal_description.matrix_coefficients;
if (format->bitrate)
avctx->bit_rate = format->bitrate;
if (format->frame_rate.numerator && format->frame_rate.denominator) {
avctx->framerate.num = format->frame_rate.numerator;
avctx->framerate.den = format->frame_rate.denominator;
}
if (ctx->cudecoder
&& avctx->coded_width == format->coded_width
&& avctx->coded_height == format->coded_height
&& ctx->chroma_format == format->chroma_format
&& ctx->codec_type == format->codec)
return 1;
if (ctx->cudecoder) {
av_log(avctx, AV_LOG_ERROR, "re-initializing decoder is not supported\n");
ctx->internal_error = AVERROR(EINVAL);
return 0;
}
if (hwframe_ctx->pool) {
av_log(avctx, AV_LOG_ERROR, "AVHWFramesContext is already initialized\n");
ctx->internal_error = AVERROR(EINVAL);
return 0;
}
avctx->coded_width = format->coded_width;
avctx->coded_height = format->coded_height;
ctx->chroma_format = format->chroma_format;
memset(&cuinfo, 0, sizeof(cuinfo));
cuinfo.CodecType = ctx->codec_type = format->codec;
cuinfo.ChromaFormat = format->chroma_format;
cuinfo.OutputFormat = cudaVideoSurfaceFormat_NV12;
cuinfo.ulWidth = avctx->coded_width;
cuinfo.ulHeight = avctx->coded_height;
cuinfo.ulTargetWidth = cuinfo.ulWidth;
cuinfo.ulTargetHeight = cuinfo.ulHeight;
cuinfo.target_rect.left = 0;
cuinfo.target_rect.top = 0;
cuinfo.target_rect.right = cuinfo.ulWidth;
cuinfo.target_rect.bottom = cuinfo.ulHeight;
cuinfo.ulNumDecodeSurfaces = MAX_FRAME_COUNT;
cuinfo.ulNumOutputSurfaces = 1;
cuinfo.ulCreationFlags = cudaVideoCreate_PreferCUVID;
cuinfo.DeinterlaceMode = cudaVideoDeinterlaceMode_Weave;
ctx->internal_error = CHECK_CU(cuvidCreateDecoder(&ctx->cudecoder, &cuinfo));
if (ctx->internal_error < 0)
return 0;
hwframe_ctx->format = AV_PIX_FMT_CUDA;
hwframe_ctx->sw_format = AV_PIX_FMT_NV12;
hwframe_ctx->width = FFALIGN(avctx->coded_width, 32);
hwframe_ctx->height = FFALIGN(avctx->coded_height, 32);
if ((ctx->internal_error = av_hwframe_ctx_init(ctx->hwframe)) < 0) {
av_log(avctx, AV_LOG_ERROR, "av_hwframe_ctx_init failed\n");
return 0;
}
return 1;
}
static int CUDAAPI cuvid_handle_picture_decode(void *opaque, CUVIDPICPARAMS* picparams)
{
AVCodecContext *avctx = opaque;
CuvidContext *ctx = avctx->priv_data;
av_log(avctx, AV_LOG_TRACE, "pfnDecodePicture\n");
ctx->internal_error = CHECK_CU(cuvidDecodePicture(ctx->cudecoder, picparams));
if (ctx->internal_error < 0)
return 0;
return 1;
}
static int CUDAAPI cuvid_handle_picture_display(void *opaque, CUVIDPARSERDISPINFO* dispinfo)
{
AVCodecContext *avctx = opaque;
CuvidContext *ctx = avctx->priv_data;
av_log(avctx, AV_LOG_TRACE, "pfnDisplayPicture\n");
ctx->internal_error = 0;
av_fifo_generic_write(ctx->frame_queue, dispinfo, sizeof(CUVIDPARSERDISPINFO), NULL);
return 1;
}
static int cuvid_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
{
CuvidContext *ctx = avctx->priv_data;
AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)ctx->hwdevice->data;
AVCUDADeviceContext *device_hwctx = device_ctx->hwctx;
CUcontext dummy, cuda_ctx = device_hwctx->cuda_ctx;
AVFrame *frame = data;
CUVIDSOURCEDATAPACKET cupkt;
AVPacket filter_packet = { 0 };
AVPacket filtered_packet = { 0 };
CUdeviceptr mapped_frame = 0;
int ret = 0, eret = 0;
if (ctx->bsf && avpkt->size) {
if ((ret = av_packet_ref(&filter_packet, avpkt)) < 0) {
av_log(avctx, AV_LOG_ERROR, "av_packet_ref failed\n");
return ret;
}
if ((ret = av_bsf_send_packet(ctx->bsf, &filter_packet)) < 0) {
av_log(avctx, AV_LOG_ERROR, "av_bsf_send_packet failed\n");
av_packet_unref(&filter_packet);
return ret;
}
if ((ret = av_bsf_receive_packet(ctx->bsf, &filtered_packet)) < 0) {
av_log(avctx, AV_LOG_ERROR, "av_bsf_receive_packet failed\n");
return ret;
}
avpkt = &filtered_packet;
}
ret = CHECK_CU(cuCtxPushCurrent(cuda_ctx));
if (ret < 0) {
av_packet_unref(&filtered_packet);
return ret;
}
memset(&cupkt, 0, sizeof(cupkt));
if (avpkt->size) {
cupkt.payload_size = avpkt->size;
cupkt.payload = avpkt->data;
if (avpkt->pts != AV_NOPTS_VALUE) {
cupkt.flags = CUVID_PKT_TIMESTAMP;
cupkt.timestamp = av_rescale_q(avpkt->pts, avctx->time_base, (AVRational){1, 10000000});
}
} else {
cupkt.flags = CUVID_PKT_ENDOFSTREAM;
}
ret = CHECK_CU(cuvidParseVideoData(ctx->cuparser, &cupkt));
av_packet_unref(&filtered_packet);
if (ret < 0) {
if (ctx->internal_error)
ret = ctx->internal_error;
goto error;
}
if (av_fifo_size(ctx->frame_queue)) {
CUVIDPARSERDISPINFO dispinfo;
CUVIDPROCPARAMS params;
unsigned int pitch = 0;
int offset = 0;
int i;
av_fifo_generic_read(ctx->frame_queue, &dispinfo, sizeof(CUVIDPARSERDISPINFO), NULL);
memset(&params, 0, sizeof(params));
params.progressive_frame = dispinfo.progressive_frame;
params.second_field = 0;
params.top_field_first = dispinfo.top_field_first;
ret = CHECK_CU(cuvidMapVideoFrame(ctx->cudecoder, dispinfo.picture_index, &mapped_frame, &pitch, &params));
if (ret < 0)
goto error;
if (avctx->pix_fmt == AV_PIX_FMT_CUDA) {
ret = av_hwframe_get_buffer(ctx->hwframe, frame, 0);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "av_hwframe_get_buffer failed\n");
goto error;
}
ret = ff_decode_frame_props(avctx, frame);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "ff_decode_frame_props failed\n");
goto error;
}
for (i = 0; i < 2; i++) {
CUDA_MEMCPY2D cpy = {
.srcMemoryType = CU_MEMORYTYPE_DEVICE,
.dstMemoryType = CU_MEMORYTYPE_DEVICE,
.srcDevice = mapped_frame,
.dstDevice = (CUdeviceptr)frame->data[i],
.srcPitch = pitch,
.dstPitch = frame->linesize[i],
.srcY = offset,
.WidthInBytes = FFMIN(pitch, frame->linesize[i]),
.Height = avctx->coded_height >> (i ? 1 : 0),
};
ret = CHECK_CU(cuMemcpy2D(&cpy));
if (ret < 0)
goto error;
offset += avctx->coded_height;
}
} else if (avctx->pix_fmt == AV_PIX_FMT_NV12) {
AVFrame *tmp_frame = av_frame_alloc();
if (!tmp_frame) {
av_log(avctx, AV_LOG_ERROR, "av_frame_alloc failed\n");
ret = AVERROR(ENOMEM);
goto error;
}
tmp_frame->format = AV_PIX_FMT_CUDA;
tmp_frame->hw_frames_ctx = av_buffer_ref(ctx->hwframe);
tmp_frame->data[0] = (uint8_t*)mapped_frame;
tmp_frame->linesize[0] = pitch;
tmp_frame->data[1] = (uint8_t*)(mapped_frame + avctx->coded_height * pitch);
tmp_frame->linesize[1] = pitch;
tmp_frame->width = avctx->width;
tmp_frame->height = avctx->height;
ret = ff_get_buffer(avctx, frame, 0);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "ff_get_buffer failed\n");
av_frame_free(&tmp_frame);
goto error;
}
ret = av_hwframe_transfer_data(frame, tmp_frame, 0);
if (ret) {
av_log(avctx, AV_LOG_ERROR, "av_hwframe_transfer_data failed\n");
av_frame_free(&tmp_frame);
goto error;
}
av_frame_free(&tmp_frame);
} else {
ret = AVERROR_BUG;
goto error;
}
frame->width = avctx->width;
frame->height = avctx->height;
frame->pts = av_rescale_q(dispinfo.timestamp, (AVRational){1, 10000000}, avctx->time_base);
/* CUVIDs opaque reordering breaks the internal pkt logic.
* So set pkt_pts and clear all the other pkt_ fields.
*/
frame->pkt_pts = frame->pts;
av_frame_set_pkt_pos(frame, -1);
av_frame_set_pkt_duration(frame, 0);
av_frame_set_pkt_size(frame, -1);
frame->interlaced_frame = !dispinfo.progressive_frame;
if (!dispinfo.progressive_frame)
frame->top_field_first = dispinfo.top_field_first;
*got_frame = 1;
} else {
*got_frame = 0;
}
error:
if (mapped_frame)
eret = CHECK_CU(cuvidUnmapVideoFrame(ctx->cudecoder, mapped_frame));
eret = CHECK_CU(cuCtxPopCurrent(&dummy));
if (eret < 0)
return eret;
else
return ret;
}
static av_cold int cuvid_decode_end(AVCodecContext *avctx)
{
CuvidContext *ctx = avctx->priv_data;
av_fifo_freep(&ctx->frame_queue);
if (ctx->bsf)
av_bsf_free(&ctx->bsf);
if (ctx->cuparser)
cuvidDestroyVideoParser(ctx->cuparser);
if (ctx->cudecoder)
cuvidDestroyDecoder(ctx->cudecoder);
av_buffer_unref(&ctx->hwframe);
av_buffer_unref(&ctx->hwdevice);
return 0;
}
static void cuvid_ctx_free(AVHWDeviceContext *ctx)
{
AVCUDADeviceContext *hwctx = ctx->hwctx;
cuCtxDestroy(hwctx->cuda_ctx);
}
static int cuvid_test_dummy_decoder(AVCodecContext *avctx, CUVIDPARSERPARAMS *cuparseinfo)
{
CUVIDDECODECREATEINFO cuinfo;
CUvideodecoder cudec = 0;
int ret = 0;
memset(&cuinfo, 0, sizeof(cuinfo));
cuinfo.CodecType = cuparseinfo->CodecType;
cuinfo.ChromaFormat = cudaVideoChromaFormat_420;
cuinfo.OutputFormat = cudaVideoSurfaceFormat_NV12;
cuinfo.ulWidth = 1280;
cuinfo.ulHeight = 720;
cuinfo.ulTargetWidth = cuinfo.ulWidth;
cuinfo.ulTargetHeight = cuinfo.ulHeight;
cuinfo.target_rect.left = 0;
cuinfo.target_rect.top = 0;
cuinfo.target_rect.right = cuinfo.ulWidth;
cuinfo.target_rect.bottom = cuinfo.ulHeight;
cuinfo.ulNumDecodeSurfaces = MAX_FRAME_COUNT;
cuinfo.ulNumOutputSurfaces = 1;
cuinfo.ulCreationFlags = cudaVideoCreate_PreferCUVID;
cuinfo.DeinterlaceMode = cudaVideoDeinterlaceMode_Weave;
ret = CHECK_CU(cuvidCreateDecoder(&cudec, &cuinfo));
if (ret < 0)
return ret;
ret = CHECK_CU(cuvidDestroyDecoder(cudec));
if (ret < 0)
return ret;
return 0;
}
static av_cold int cuvid_decode_init(AVCodecContext *avctx)
{
CuvidContext *ctx = avctx->priv_data;
AVCUDADeviceContext *device_hwctx;
AVHWDeviceContext *device_ctx;
AVHWFramesContext *hwframe_ctx;
CUVIDPARSERPARAMS cuparseinfo;
CUVIDEOFORMATEX cuparse_ext;
CUVIDSOURCEDATAPACKET seq_pkt;
CUdevice device;
CUcontext cuda_ctx = NULL;
CUcontext dummy;
const AVBitStreamFilter *bsf;
int ret = 0;
enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_CUDA,
AV_PIX_FMT_NV12,
AV_PIX_FMT_NONE };
ret = ff_get_format(avctx, pix_fmts);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "ff_get_format failed: %d\n", ret);
return ret;
}
ctx->frame_queue = av_fifo_alloc(MAX_FRAME_COUNT * sizeof(CUVIDPARSERDISPINFO));
if (!ctx->frame_queue) {
ret = AVERROR(ENOMEM);
goto error;
}
avctx->pix_fmt = ret;
if (avctx->hw_frames_ctx) {
ctx->hwframe = av_buffer_ref(avctx->hw_frames_ctx);
if (!ctx->hwframe) {
ret = AVERROR(ENOMEM);
goto error;
}
hwframe_ctx = (AVHWFramesContext*)ctx->hwframe->data;
ctx->hwdevice = av_buffer_ref(hwframe_ctx->device_ref);
if (!ctx->hwdevice) {
ret = AVERROR(ENOMEM);
goto error;
}
device_ctx = hwframe_ctx->device_ctx;
device_hwctx = device_ctx->hwctx;
cuda_ctx = device_hwctx->cuda_ctx;
} else {
ctx->hwdevice = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_CUDA);
if (!ctx->hwdevice) {
av_log(avctx, AV_LOG_ERROR, "Error allocating hwdevice\n");
ret = AVERROR(ENOMEM);
goto error;
}
ret = CHECK_CU(cuInit(0));
if (ret < 0)
goto error;
ret = CHECK_CU(cuDeviceGet(&device, 0));
if (ret < 0)
goto error;
ret = CHECK_CU(cuCtxCreate(&cuda_ctx, CU_CTX_SCHED_BLOCKING_SYNC, device));
if (ret < 0)
goto error;
device_ctx = (AVHWDeviceContext*)ctx->hwdevice->data;
device_ctx->free = cuvid_ctx_free;
device_hwctx = device_ctx->hwctx;
device_hwctx->cuda_ctx = cuda_ctx;
ret = CHECK_CU(cuCtxPopCurrent(&dummy));
if (ret < 0)
goto error;
ret = av_hwdevice_ctx_init(ctx->hwdevice);
if (ret < 0) {
av_log(avctx, AV_LOG_ERROR, "av_hwdevice_ctx_init failed\n");
goto error;
}
ctx->hwframe = av_hwframe_ctx_alloc(ctx->hwdevice);
if (!ctx->hwframe) {
av_log(avctx, AV_LOG_ERROR, "av_hwframe_ctx_alloc failed\n");
ret = AVERROR(ENOMEM);
goto error;
}
}
memset(&cuparseinfo, 0, sizeof(cuparseinfo));
memset(&cuparse_ext, 0, sizeof(cuparse_ext));
memset(&seq_pkt, 0, sizeof(seq_pkt));
cuparseinfo.pExtVideoInfo = &cuparse_ext;
switch (avctx->codec->id) {
#if CONFIG_H264_CUVID_DECODER
case AV_CODEC_ID_H264:
cuparseinfo.CodecType = cudaVideoCodec_H264;
break;
#endif
#if CONFIG_HEVC_CUVID_DECODER
case AV_CODEC_ID_HEVC:
cuparseinfo.CodecType = cudaVideoCodec_HEVC;
break;
#endif
#if CONFIG_VP8_CUVID_DECODER
case AV_CODEC_ID_VP8:
cuparseinfo.CodecType = cudaVideoCodec_VP8;
break;
#endif
#if CONFIG_VP9_CUVID_DECODER
case AV_CODEC_ID_VP9:
cuparseinfo.CodecType = cudaVideoCodec_VP9;
break;
#endif
#if CONFIG_VC1_CUVID_DECODER
case AV_CODEC_ID_VC1:
cuparseinfo.CodecType = cudaVideoCodec_VC1;
break;
#endif
default:
av_log(avctx, AV_LOG_ERROR, "Invalid CUVID codec!\n");
return AVERROR_BUG;
}
if (avctx->codec->id == AV_CODEC_ID_H264 || avctx->codec->id == AV_CODEC_ID_HEVC) {
if (avctx->codec->id == AV_CODEC_ID_H264)
bsf = av_bsf_get_by_name("h264_mp4toannexb");
else
bsf = av_bsf_get_by_name("hevc_mp4toannexb");
if (!bsf) {
ret = AVERROR_BSF_NOT_FOUND;
goto error;
}
if (ret = av_bsf_alloc(bsf, &ctx->bsf)) {
goto error;
}
if (((ret = avcodec_parameters_from_context(ctx->bsf->par_in, avctx)) < 0) || ((ret = av_bsf_init(ctx->bsf)) < 0)) {
av_bsf_free(&ctx->bsf);
goto error;
}
cuparse_ext.format.seqhdr_data_length = ctx->bsf->par_out->extradata_size;
memcpy(cuparse_ext.raw_seqhdr_data,
ctx->bsf->par_out->extradata,
FFMIN(sizeof(cuparse_ext.raw_seqhdr_data), ctx->bsf->par_out->extradata_size));
} else if (avctx->extradata_size > 0) {
cuparse_ext.format.seqhdr_data_length = avctx->extradata_size;
memcpy(cuparse_ext.raw_seqhdr_data,
avctx->extradata,
FFMIN(sizeof(cuparse_ext.raw_seqhdr_data), avctx->extradata_size));
}
cuparseinfo.ulMaxNumDecodeSurfaces = MAX_FRAME_COUNT;
cuparseinfo.ulMaxDisplayDelay = 4;
cuparseinfo.pUserData = avctx;
cuparseinfo.pfnSequenceCallback = cuvid_handle_video_sequence;
cuparseinfo.pfnDecodePicture = cuvid_handle_picture_decode;
cuparseinfo.pfnDisplayPicture = cuvid_handle_picture_display;
ret = CHECK_CU(cuCtxPushCurrent(cuda_ctx));
if (ret < 0)
goto error;
ret = cuvid_test_dummy_decoder(avctx, &cuparseinfo);
if (ret < 0)
goto error;
ret = CHECK_CU(cuvidCreateVideoParser(&ctx->cuparser, &cuparseinfo));
if (ret < 0)
goto error;
seq_pkt.payload = cuparse_ext.raw_seqhdr_data;
seq_pkt.payload_size = cuparse_ext.format.seqhdr_data_length;
if (seq_pkt.payload && seq_pkt.payload_size) {
ret = CHECK_CU(cuvidParseVideoData(ctx->cuparser, &seq_pkt));
if (ret < 0)
goto error;
}
ret = CHECK_CU(cuCtxPopCurrent(&dummy));
if (ret < 0)
goto error;
return 0;
error:
cuvid_decode_end(avctx);
return ret;
}
#define DEFINE_CUVID_CODEC(x, X) \
AVHWAccel ff_##x##_cuvid_hwaccel = { \
.name = #x "_cuvid", \
.type = AVMEDIA_TYPE_VIDEO, \
.id = AV_CODEC_ID_##X, \
.pix_fmt = AV_PIX_FMT_CUDA, \
}; \
AVCodec ff_##x##_cuvid_decoder = { \
.name = #x "_cuvid", \
.long_name = NULL_IF_CONFIG_SMALL("Nvidia CUVID " #X " decoder"), \
.type = AVMEDIA_TYPE_VIDEO, \
.id = AV_CODEC_ID_##X, \
.priv_data_size = sizeof(CuvidContext), \
.init = cuvid_decode_init, \
.close = cuvid_decode_end, \
.decode = cuvid_decode_frame, \
.capabilities = AV_CODEC_CAP_DELAY, \
.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA, \
AV_PIX_FMT_NV12, \
AV_PIX_FMT_NONE }, \
};
#if CONFIG_HEVC_CUVID_DECODER
DEFINE_CUVID_CODEC(hevc, HEVC)
#endif
#if CONFIG_H264_CUVID_DECODER
DEFINE_CUVID_CODEC(h264, H264)
#endif
#if CONFIG_VP8_CUVID_DECODER
DEFINE_CUVID_CODEC(vp8, VP8)
#endif
#if CONFIG_VP9_CUVID_DECODER
DEFINE_CUVID_CODEC(vp9, VP9)
#endif
#if CONFIG_VC1_CUVID_DECODER
DEFINE_CUVID_CODEC(vc1, VC1)
#endif

View File

@ -28,7 +28,7 @@
#include "libavutil/version.h" #include "libavutil/version.h"
#define LIBAVCODEC_VERSION_MAJOR 57 #define LIBAVCODEC_VERSION_MAJOR 57
#define LIBAVCODEC_VERSION_MINOR 45 #define LIBAVCODEC_VERSION_MINOR 46
#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \