mirror of
https://github.com/jellyfin/jellyfin-ffmpeg.git
synced 2026-09-03 05:09:58 +03:00
New upstream version 3.5~git20180113
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
/*_tablegen
|
||||
/*_tables.c
|
||||
/*_tables.h
|
||||
/bsf_list.c
|
||||
+51
-29
@@ -1,7 +1,9 @@
|
||||
NAME = avcodec
|
||||
DESC = FFmpeg codec library
|
||||
|
||||
HEADERS = avcodec.h \
|
||||
HEADERS = ac3_parser.h \
|
||||
adts_parser.h \
|
||||
avcodec.h \
|
||||
avdct.h \
|
||||
avfft.h \
|
||||
d3d11va.h \
|
||||
@@ -12,15 +14,15 @@ HEADERS = avcodec.h \
|
||||
mediacodec.h \
|
||||
qsv.h \
|
||||
vaapi.h \
|
||||
vda.h \
|
||||
vdpau.h \
|
||||
version.h \
|
||||
videotoolbox.h \
|
||||
vorbis_parser.h \
|
||||
xvmc.h \
|
||||
|
||||
OBJS = allcodecs.o \
|
||||
audioconvert.o \
|
||||
OBJS = ac3_parser.o \
|
||||
adts_parser.o \
|
||||
allcodecs.o \
|
||||
avdct.o \
|
||||
avpacket.o \
|
||||
avpicture.o \
|
||||
@@ -45,8 +47,6 @@ OBJS = allcodecs.o \
|
||||
profiles.o \
|
||||
qsv_api.o \
|
||||
raw.o \
|
||||
resample.o \
|
||||
resample2.o \
|
||||
utils.o \
|
||||
vorbis_parser.o \
|
||||
xiph.o \
|
||||
@@ -54,11 +54,17 @@ OBJS = allcodecs.o \
|
||||
# subsystems
|
||||
OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o
|
||||
OBJS-$(CONFIG_AC3DSP) += ac3dsp.o ac3.o ac3tab.o
|
||||
OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio.o
|
||||
OBJS-$(CONFIG_AMF) += amfenc.o
|
||||
OBJS-$(CONFIG_AUDIO_FRAME_QUEUE) += audio_frame_queue.o
|
||||
OBJS-$(CONFIG_AUDIODSP) += audiodsp.o
|
||||
OBJS-$(CONFIG_BLOCKDSP) += blockdsp.o
|
||||
OBJS-$(CONFIG_BSWAPDSP) += bswapdsp.o
|
||||
OBJS-$(CONFIG_CABAC) += cabac.o
|
||||
OBJS-$(CONFIG_CBS) += cbs.o
|
||||
OBJS-$(CONFIG_CBS_H264) += cbs_h2645.o h2645_parse.o
|
||||
OBJS-$(CONFIG_CBS_H265) += cbs_h2645.o h2645_parse.o
|
||||
OBJS-$(CONFIG_CBS_MPEG2) += cbs_mpeg2.o
|
||||
OBJS-$(CONFIG_CRYSTALHD) += crystalhd.o
|
||||
OBJS-$(CONFIG_DCT) += dct.o dct32_fixed.o dct32_float.o
|
||||
OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o
|
||||
@@ -91,7 +97,6 @@ OBJS-$(CONFIG_INTRAX8) += intrax8.o intrax8dsp.o msmpeg4data.o
|
||||
OBJS-$(CONFIG_IVIDSP) += ivi_dsp.o
|
||||
OBJS-$(CONFIG_JNI) += ffjni.o jni.o
|
||||
OBJS-$(CONFIG_JPEGTABLES) += jpegtables.o
|
||||
OBJS-$(CONFIG_LIBXVID) += libxvid_rc.o
|
||||
OBJS-$(CONFIG_LLAUDDSP) += lossless_audiodsp.o
|
||||
OBJS-$(CONFIG_LLVIDDSP) += lossless_videodsp.o
|
||||
OBJS-$(CONFIG_LLVIDENCDSP) += lossless_videoencdsp.o
|
||||
@@ -146,10 +151,10 @@ OBJS-$(CONFIG_ZERO12V_DECODER) += 012v.o
|
||||
OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o
|
||||
OBJS-$(CONFIG_A64MULTI5_ENCODER) += a64multienc.o elbg.o
|
||||
OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o aacsbr.o aacps_float.o \
|
||||
aacadtsdec.o mpeg4audio.o kbdwin.o \
|
||||
mpeg4audio.o kbdwin.o \
|
||||
sbrdsp.o aacpsdsp_float.o cbrt_data.o
|
||||
OBJS-$(CONFIG_AAC_FIXED_DECODER) += aacdec_fixed.o aactab.o aacsbr_fixed.o aacps_fixed.o \
|
||||
aacadtsdec.o mpeg4audio.o kbdwin.o \
|
||||
mpeg4audio.o kbdwin.o \
|
||||
sbrdsp_fixed.o aacpsdsp_fixed.o cbrt_data_fixed.o
|
||||
OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \
|
||||
aacpsy.o aactab.o \
|
||||
@@ -183,6 +188,8 @@ OBJS-$(CONFIG_AMV_ENCODER) += mjpegenc.o mjpegenc_common.o \
|
||||
OBJS-$(CONFIG_ANM_DECODER) += anm.o
|
||||
OBJS-$(CONFIG_ANSI_DECODER) += ansi.o cga_data.o
|
||||
OBJS-$(CONFIG_APE_DECODER) += apedec.o
|
||||
OBJS-$(CONFIG_APTX_DECODER) += aptx.o
|
||||
OBJS-$(CONFIG_APTX_ENCODER) += aptx.o
|
||||
OBJS-$(CONFIG_APNG_DECODER) += png.o pngdec.o pngdsp.o
|
||||
OBJS-$(CONFIG_APNG_ENCODER) += png.o pngenc.o
|
||||
OBJS-$(CONFIG_SSA_DECODER) += assdec.o ass.o
|
||||
@@ -331,18 +338,18 @@ OBJS-$(CONFIG_H264_DECODER) += h264dec.o h264_cabac.o h264_cavlc.o \
|
||||
h264_mb.o h264_picture.o \
|
||||
h264_refs.o h264_sei.o \
|
||||
h264_slice.o h264data.o
|
||||
OBJS-$(CONFIG_H264_CUVID_DECODER) += cuvid.o
|
||||
OBJS-$(CONFIG_H264_AMF_ENCODER) += amfenc_h264.o
|
||||
OBJS-$(CONFIG_H264_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_H264_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
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
|
||||
OBJS-$(CONFIG_H264_RKMPP_DECODER) += rkmppdec.o
|
||||
OBJS-$(CONFIG_H264_VAAPI_ENCODER) += vaapi_encode_h264.o vaapi_encode_h26x.o
|
||||
OBJS-$(CONFIG_H264_VAAPI_ENCODER) += vaapi_encode_h264.o
|
||||
OBJS-$(CONFIG_H264_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o
|
||||
OBJS-$(CONFIG_H264_V4L2M2M_DECODER) += v4l2_m2m_dec.o
|
||||
OBJS-$(CONFIG_H264_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
|
||||
@@ -351,7 +358,8 @@ OBJS-$(CONFIG_HAP_ENCODER) += hapenc.o hap.o
|
||||
OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o \
|
||||
hevc_cabac.o hevc_refs.o hevcpred.o \
|
||||
hevcdsp.o hevc_filter.o hevc_data.o
|
||||
OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuvid.o
|
||||
OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o
|
||||
OBJS-$(CONFIG_NVENC_HEVC_ENCODER) += nvenc_hevc.o
|
||||
@@ -359,7 +367,7 @@ OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec_h2645.o
|
||||
OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o \
|
||||
hevc_data.o
|
||||
OBJS-$(CONFIG_HEVC_RKMPP_DECODER) += rkmppdec.o
|
||||
OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o vaapi_encode_h26x.o
|
||||
OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o
|
||||
OBJS-$(CONFIG_HEVC_V4L2M2M_DECODER) += v4l2_m2m_dec.o
|
||||
OBJS-$(CONFIG_HEVC_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
|
||||
OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o
|
||||
@@ -396,6 +404,7 @@ OBJS-$(CONFIG_M101_DECODER) += m101.o
|
||||
OBJS-$(CONFIG_MACE3_DECODER) += mace.o
|
||||
OBJS-$(CONFIG_MACE6_DECODER) += mace.o
|
||||
OBJS-$(CONFIG_MAGICYUV_DECODER) += magicyuv.o
|
||||
OBJS-$(CONFIG_MAGICYUV_ENCODER) += magicyuvenc.o
|
||||
OBJS-$(CONFIG_MDEC_DECODER) += mdec.o mpeg12.o mpeg12data.o
|
||||
OBJS-$(CONFIG_METASOUND_DECODER) += metasound.o metasound_data.o \
|
||||
twinvq.o
|
||||
@@ -405,6 +414,7 @@ OBJS-$(CONFIG_MJPEG_DECODER) += mjpegdec.o
|
||||
OBJS-$(CONFIG_MJPEG_ENCODER) += mjpegenc.o mjpegenc_common.o \
|
||||
mjpegenc_huffman.o
|
||||
OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o
|
||||
OBJS-$(CONFIG_MJPEG_QSV_ENCODER) += qsvenc_jpeg.o
|
||||
OBJS-$(CONFIG_MJPEG_VAAPI_ENCODER) += vaapi_encode_mjpeg.o
|
||||
OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o
|
||||
OBJS-$(CONFIG_MLP_ENCODER) += mlpenc.o mlp.o
|
||||
@@ -616,7 +626,7 @@ OBJS-$(CONFIG_VC1_DECODER) += vc1dec.o vc1_block.o vc1_loopfilter.o
|
||||
vc1_mc.o vc1_pred.o vc1.o vc1data.o \
|
||||
msmpeg4dec.o msmpeg4.o msmpeg4data.o \
|
||||
wmv2dsp.o wmv2data.o
|
||||
OBJS-$(CONFIG_VC1_CUVID_DECODER) += cuvid.o
|
||||
OBJS-$(CONFIG_VC1_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_VC1_MMAL_DECODER) += mmaldec.o
|
||||
OBJS-$(CONFIG_VC1_QSV_DECODER) += qsvdec_other.o
|
||||
OBJS-$(CONFIG_VC1_V4L2M2M_DECODER) += v4l2_m2m_dec.o
|
||||
@@ -635,7 +645,7 @@ OBJS-$(CONFIG_VP6_DECODER) += vp6.o vp56.o vp56data.o \
|
||||
vp6dsp.o vp56rac.o
|
||||
OBJS-$(CONFIG_VP7_DECODER) += vp8.o vp56rac.o
|
||||
OBJS-$(CONFIG_VP8_DECODER) += vp8.o vp56rac.o
|
||||
OBJS-$(CONFIG_VP8_CUVID_DECODER) += cuvid.o
|
||||
OBJS-$(CONFIG_VP8_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_VP8_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_VP8_QSV_DECODER) += qsvdec_other.o
|
||||
OBJS-$(CONFIG_VP8_RKMPP_DECODER) += rkmppdec.o
|
||||
@@ -645,7 +655,7 @@ OBJS-$(CONFIG_VP8_V4L2M2M_ENCODER) += v4l2_m2m_enc.o
|
||||
OBJS-$(CONFIG_VP9_DECODER) += vp9.o vp9data.o vp9dsp.o vp9lpf.o vp9recon.o \
|
||||
vp9block.o vp9prob.o vp9mvs.o vp56rac.o \
|
||||
vp9dsp_8bpp.o vp9dsp_10bpp.o vp9dsp_12bpp.o
|
||||
OBJS-$(CONFIG_VP9_CUVID_DECODER) += cuvid.o
|
||||
OBJS-$(CONFIG_VP9_CUVID_DECODER) += cuviddec.o
|
||||
OBJS-$(CONFIG_VP9_MEDIACODEC_DECODER) += mediacodecdec.o
|
||||
OBJS-$(CONFIG_VP9_RKMPP_DECODER) += rkmppdec.o
|
||||
OBJS-$(CONFIG_VP9_VAAPI_ENCODER) += vaapi_encode_vp9.o
|
||||
@@ -822,8 +832,8 @@ OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcmenc.o adpcm_data.o
|
||||
# hardware accelerators
|
||||
OBJS-$(CONFIG_D3D11VA) += dxva2.o
|
||||
OBJS-$(CONFIG_DXVA2) += dxva2.o
|
||||
OBJS-$(CONFIG_NVDEC) += nvdec.o
|
||||
OBJS-$(CONFIG_VAAPI) += vaapi_decode.o
|
||||
OBJS-$(CONFIG_VDA) += vda.o videotoolbox.o
|
||||
OBJS-$(CONFIG_VIDEOTOOLBOX) += videotoolbox.o
|
||||
OBJS-$(CONFIG_VDPAU) += vdpau.o
|
||||
|
||||
@@ -831,36 +841,44 @@ OBJS-$(CONFIG_H263_VAAPI_HWACCEL) += vaapi_mpeg4.o
|
||||
OBJS-$(CONFIG_H263_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
|
||||
OBJS-$(CONFIG_H264_D3D11VA_HWACCEL) += dxva2_h264.o
|
||||
OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o
|
||||
OBJS-$(CONFIG_H264_NVDEC_HWACCEL) += nvdec_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
|
||||
OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_NVDEC_HWACCEL) += nvdec_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_QSV_HWACCEL) += qsvdec_h2645.o
|
||||
OBJS-$(CONFIG_HEVC_VAAPI_HWACCEL) += vaapi_hevc.o
|
||||
OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL) += vdpau_hevc.o
|
||||
OBJS-$(CONFIG_MPEG1_NVDEC_HWACCEL) += nvdec_mpeg12.o
|
||||
OBJS-$(CONFIG_MPEG1_VDPAU_HWACCEL) += vdpau_mpeg12.o
|
||||
OBJS-$(CONFIG_MPEG1_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
|
||||
OBJS-$(CONFIG_MPEG1_XVMC_HWACCEL) += mpegvideo_xvmc.o
|
||||
OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL) += dxva2_mpeg2.o
|
||||
OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o
|
||||
OBJS-$(CONFIG_MPEG2_NVDEC_HWACCEL) += nvdec_mpeg12.o
|
||||
OBJS-$(CONFIG_MPEG2_QSV_HWACCEL) += qsvdec_other.o
|
||||
OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o
|
||||
OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL) += vdpau_mpeg12.o
|
||||
OBJS-$(CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
|
||||
OBJS-$(CONFIG_MPEG2_XVMC_HWACCEL) += mpegvideo_xvmc.o
|
||||
OBJS-$(CONFIG_MPEG4_NVDEC_HWACCEL) += nvdec_mpeg4.o
|
||||
OBJS-$(CONFIG_MPEG4_VAAPI_HWACCEL) += vaapi_mpeg4.o
|
||||
OBJS-$(CONFIG_MPEG4_VDPAU_HWACCEL) += vdpau_mpeg4.o
|
||||
OBJS-$(CONFIG_MPEG4_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
|
||||
OBJS-$(CONFIG_VC1_D3D11VA_HWACCEL) += dxva2_vc1.o
|
||||
OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o
|
||||
OBJS-$(CONFIG_VC1_NVDEC_HWACCEL) += nvdec_vc1.o
|
||||
OBJS-$(CONFIG_VC1_QSV_HWACCEL) += qsvdec_other.o
|
||||
OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o
|
||||
OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o
|
||||
OBJS-$(CONFIG_VP8_NVDEC_HWACCEL) += nvdec_vp8.o
|
||||
OBJS-$(CONFIG_VP8_VAAPI_HWACCEL) += vaapi_vp8.o
|
||||
OBJS-$(CONFIG_VP9_D3D11VA_HWACCEL) += dxva2_vp9.o
|
||||
OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o
|
||||
OBJS-$(CONFIG_VP9_NVDEC_HWACCEL) += nvdec_vp9.o
|
||||
OBJS-$(CONFIG_VP9_VAAPI_HWACCEL) += vaapi_vp9.o
|
||||
OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec_other.o
|
||||
|
||||
@@ -880,7 +898,6 @@ OBJS-$(CONFIG_MXF_MUXER) += dnxhddata.o
|
||||
OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o
|
||||
OBJS-$(CONFIG_NUT_DEMUXER) += mpegaudiodata.o mpeg4audio.o
|
||||
OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o
|
||||
OBJS-$(CONFIG_SPDIF_DEMUXER) += aacadtsdec.o mpeg4audio.o
|
||||
OBJS-$(CONFIG_SPDIF_MUXER) += dca.o
|
||||
OBJS-$(CONFIG_TAK_DEMUXER) += tak.o
|
||||
OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o
|
||||
@@ -951,15 +968,14 @@ OBJS-$(CONFIG_LIBX262_ENCODER) += libx264.o
|
||||
OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o
|
||||
OBJS-$(CONFIG_LIBX265_ENCODER) += libx265.o
|
||||
OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o
|
||||
OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o
|
||||
OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o libxvid_rc.o
|
||||
OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o ass.o
|
||||
|
||||
# parsers
|
||||
OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o
|
||||
OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o \
|
||||
aacadtsdec.o mpeg4audio.o
|
||||
OBJS-$(CONFIG_AC3_PARSER) += ac3_parser.o ac3tab.o \
|
||||
aac_ac3_parser.o
|
||||
mpeg4audio.o
|
||||
OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o
|
||||
OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o
|
||||
OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o
|
||||
OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o
|
||||
@@ -989,7 +1005,8 @@ OBJS-$(CONFIG_PNG_PARSER) += png_parser.o
|
||||
OBJS-$(CONFIG_MPEGAUDIO_PARSER) += mpegaudio_parser.o
|
||||
OBJS-$(CONFIG_MPEGVIDEO_PARSER) += mpegvideo_parser.o \
|
||||
mpeg12.o mpeg12data.o
|
||||
OBJS-$(CONFIG_OPUS_PARSER) += opus_parser.o opus.o vorbis_data.o
|
||||
OBJS-$(CONFIG_OPUS_PARSER) += opus_parser.o opus.o opustab.o \
|
||||
opus_rc.o vorbis_data.o
|
||||
OBJS-$(CONFIG_PNG_PARSER) += png_parser.o
|
||||
OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o
|
||||
OBJS-$(CONFIG_RV30_PARSER) += rv34_parser.o
|
||||
@@ -1004,14 +1021,16 @@ OBJS-$(CONFIG_VP9_PARSER) += vp9_parser.o
|
||||
OBJS-$(CONFIG_XMA_PARSER) += xma_parser.o
|
||||
|
||||
# bitstream filters
|
||||
OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o aacadtsdec.o \
|
||||
mpeg4audio.o
|
||||
OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o mpeg4audio.o
|
||||
OBJS-$(CONFIG_CHOMP_BSF) += chomp_bsf.o
|
||||
OBJS-$(CONFIG_DUMP_EXTRADATA_BSF) += dump_extradata_bsf.o
|
||||
OBJS-$(CONFIG_DCA_CORE_BSF) += dca_core_bsf.o
|
||||
OBJS-$(CONFIG_EXTRACT_EXTRADATA_BSF) += extract_extradata_bsf.o \
|
||||
h2645_parse.o
|
||||
OBJS-$(CONFIG_H264_METADATA_BSF) += h264_metadata_bsf.o
|
||||
OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += h264_mp4toannexb_bsf.o
|
||||
OBJS-$(CONFIG_H264_REDUNDANT_PPS_BSF) += h264_redundant_pps_bsf.o
|
||||
OBJS-$(CONFIG_HEVC_METADATA_BSF) += h265_metadata_bsf.o
|
||||
OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += hevc_mp4toannexb_bsf.o
|
||||
OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += imx_dump_header_bsf.o
|
||||
OBJS-$(CONFIG_MJPEG2JPEG_BSF) += mjpeg2jpeg_bsf.o
|
||||
@@ -1020,10 +1039,12 @@ OBJS-$(CONFIG_MPEG4_UNPACK_BFRAMES_BSF) += mpeg4_unpack_bframes_bsf.o
|
||||
OBJS-$(CONFIG_MOV2TEXTSUB_BSF) += movsub_bsf.o
|
||||
OBJS-$(CONFIG_MP3_HEADER_DECOMPRESS_BSF) += mp3_header_decompress_bsf.o \
|
||||
mpegaudiodata.o
|
||||
OBJS-$(CONFIG_MPEG2_METADATA_BSF) += mpeg2_metadata_bsf.o
|
||||
OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o
|
||||
OBJS-$(CONFIG_NULL_BSF) += null_bsf.o
|
||||
OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o
|
||||
OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o
|
||||
OBJS-$(CONFIG_TRACE_HEADERS_BSF) += trace_headers_bsf.o
|
||||
OBJS-$(CONFIG_VP9_RAW_REORDER_BSF) += vp9_raw_reorder_bsf.o
|
||||
OBJS-$(CONFIG_VP9_SUPERFRAME_BSF) += vp9_superframe_bsf.o
|
||||
OBJS-$(CONFIG_VP9_SUPERFRAME_SPLIT_BSF) += vp9_superframe_split_bsf.o
|
||||
@@ -1048,6 +1069,7 @@ SKIPHEADERS += %_tablegen.h \
|
||||
aacenc_quantization_misc.h \
|
||||
$(ARCH)/vp56_arith.h \
|
||||
|
||||
SKIPHEADERS-$(CONFIG_AMF) += amfenc.h
|
||||
SKIPHEADERS-$(CONFIG_D3D11VA) += d3d11va.h dxva2_internal.h
|
||||
SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h
|
||||
SKIPHEADERS-$(CONFIG_JNI) += ffjni.h
|
||||
@@ -1060,9 +1082,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 \
|
||||
@@ -1082,6 +1103,7 @@ TESTPROGS-$(CONFIG_GOLOMB) += golomb
|
||||
TESTPROGS-$(CONFIG_IDCTDSP) += dct
|
||||
TESTPROGS-$(CONFIG_IIRFILTER) += iirfilter
|
||||
TESTPROGS-$(HAVE_MMX) += motion
|
||||
TESTPROGS-$(CONFIG_MPEGVIDEO) += mpeg12framerate
|
||||
TESTPROGS-$(CONFIG_RANGECODER) += rangecoder
|
||||
TESTPROGS-$(CONFIG_SNOW_ENCODER) += snowenc
|
||||
|
||||
|
||||
@@ -86,20 +86,8 @@ get_next:
|
||||
the frame). */
|
||||
if (avctx->codec_id != AV_CODEC_ID_AAC) {
|
||||
avctx->sample_rate = s->sample_rate;
|
||||
|
||||
/* (E-)AC-3: allow downmixing to stereo or mono */
|
||||
if (s->channels > 1 &&
|
||||
avctx->request_channel_layout == AV_CH_LAYOUT_MONO) {
|
||||
avctx->channels = 1;
|
||||
avctx->channel_layout = AV_CH_LAYOUT_MONO;
|
||||
} else if (s->channels > 2 &&
|
||||
avctx->request_channel_layout == AV_CH_LAYOUT_STEREO) {
|
||||
avctx->channels = 2;
|
||||
avctx->channel_layout = AV_CH_LAYOUT_STEREO;
|
||||
} else {
|
||||
avctx->channels = s->channels;
|
||||
avctx->channel_layout = s->channel_layout;
|
||||
}
|
||||
avctx->channels = s->channels;
|
||||
avctx->channel_layout = s->channel_layout;
|
||||
s1->duration = s->samples;
|
||||
avctx->audio_service_type = s->service_type;
|
||||
}
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "adts_header.h"
|
||||
#include "adts_parser.h"
|
||||
#include "avcodec.h"
|
||||
#include "aacadtsdec.h"
|
||||
#include "bsf.h"
|
||||
#include "put_bits.h"
|
||||
#include "get_bits.h"
|
||||
@@ -52,12 +53,12 @@ static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out)
|
||||
if (bsfc->par_in->extradata && in->size >= 2 && (AV_RB16(in->data) >> 4) != 0xfff)
|
||||
goto finish;
|
||||
|
||||
if (in->size < AAC_ADTS_HEADER_SIZE)
|
||||
if (in->size < AV_AAC_ADTS_HEADER_SIZE)
|
||||
goto packet_too_small;
|
||||
|
||||
init_get_bits(&gb, in->data, AAC_ADTS_HEADER_SIZE * 8);
|
||||
init_get_bits(&gb, in->data, AV_AAC_ADTS_HEADER_SIZE * 8);
|
||||
|
||||
if (avpriv_aac_parse_header(&gb, &hdr) < 0) {
|
||||
if (ff_adts_header_parse(&gb, &hdr) < 0) {
|
||||
av_log(bsfc, AV_LOG_ERROR, "Error parsing ADTS frame header!\n");
|
||||
ret = AVERROR_INVALIDDATA;
|
||||
goto fail;
|
||||
@@ -70,10 +71,10 @@ static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
in->size -= AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent;
|
||||
in->size -= AV_AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent;
|
||||
if (in->size <= 0)
|
||||
goto packet_too_small;
|
||||
in->data += AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent;
|
||||
in->data += AV_AAC_ADTS_HEADER_SIZE + 2 * !hdr.crc_absent;
|
||||
|
||||
if (!ctx->first_frame_done) {
|
||||
int pce_size = 0;
|
||||
@@ -91,7 +92,7 @@ static int aac_adtstoasc_filter(AVBSFContext *bsfc, AVPacket *out)
|
||||
goto fail;
|
||||
}
|
||||
init_put_bits(&pb, pce_data, MAX_PCE_SIZE);
|
||||
pce_size = avpriv_copy_pce_data(&pb, &gb)/8;
|
||||
pce_size = ff_copy_pce_data(&pb, &gb) / 8;
|
||||
flush_put_bits(&pb);
|
||||
in->size -= get_bits_count(&gb)/8;
|
||||
in->data += get_bits_count(&gb)/8;
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
|
||||
#include "parser.h"
|
||||
#include "aac_ac3_parser.h"
|
||||
#include "aacadtsdec.h"
|
||||
#include "adts_header.h"
|
||||
#include "adts_parser.h"
|
||||
#include "get_bits.h"
|
||||
#include "mpeg4audio.h"
|
||||
|
||||
@@ -38,9 +39,10 @@ static int aac_sync(uint64_t state, AACAC3ParseContext *hdr_info,
|
||||
} tmp;
|
||||
|
||||
tmp.u64 = av_be2ne64(state);
|
||||
init_get_bits(&bits, tmp.u8+8-AAC_ADTS_HEADER_SIZE, AAC_ADTS_HEADER_SIZE * 8);
|
||||
init_get_bits(&bits, tmp.u8 + 8 - AV_AAC_ADTS_HEADER_SIZE,
|
||||
AV_AAC_ADTS_HEADER_SIZE * 8);
|
||||
|
||||
if ((size = avpriv_aac_parse_header(&bits, &hdr)) < 0)
|
||||
if ((size = ff_adts_header_parse(&bits, &hdr)) < 0)
|
||||
return 0;
|
||||
*need_next_header = 0;
|
||||
*new_frame_start = 1;
|
||||
@@ -54,7 +56,7 @@ static int aac_sync(uint64_t state, AACAC3ParseContext *hdr_info,
|
||||
static av_cold int aac_parse_init(AVCodecParserContext *s1)
|
||||
{
|
||||
AACAC3ParseContext *s = s1->priv_data;
|
||||
s->header_size = AAC_ADTS_HEADER_SIZE;
|
||||
s->header_size = AV_AAC_ADTS_HEADER_SIZE;
|
||||
s->sync = aac_sync;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+1
-1
@@ -50,11 +50,11 @@
|
||||
#include "aac.h"
|
||||
#include "aactab.h"
|
||||
#include "aacdectab.h"
|
||||
#include "adts_header.h"
|
||||
#include "cbrt_data.h"
|
||||
#include "sbr.h"
|
||||
#include "aacsbr.h"
|
||||
#include "mpeg4audio.h"
|
||||
#include "aacadtsdec.h"
|
||||
#include "profiles.h"
|
||||
#include "libavutil/intfloat.h"
|
||||
|
||||
|
||||
@@ -75,11 +75,11 @@
|
||||
#include "aac.h"
|
||||
#include "aactab.h"
|
||||
#include "aacdectab.h"
|
||||
#include "adts_header.h"
|
||||
#include "cbrt_data.h"
|
||||
#include "sbr.h"
|
||||
#include "aacsbr.h"
|
||||
#include "mpeg4audio.h"
|
||||
#include "aacadtsdec.h"
|
||||
#include "profiles.h"
|
||||
#include "libavutil/intfloat.h"
|
||||
|
||||
@@ -307,9 +307,9 @@ static av_always_inline void predict(PredictorState *ps, int *coef,
|
||||
|
||||
if (shift < 31) {
|
||||
if (shift > 0) {
|
||||
*coef += (pv.mant + (1 << (shift - 1))) >> shift;
|
||||
*coef += (unsigned)((pv.mant + (1 << (shift - 1))) >> shift);
|
||||
} else
|
||||
*coef += pv.mant << -shift;
|
||||
*coef += (unsigned)pv.mant << -shift;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,7 +394,7 @@ static void apply_dependent_coupling_fixed(AACContext *ac,
|
||||
for (k = offsets[i]; k < offsets[i + 1]; k++) {
|
||||
tmp = (int)(((int64_t)src[group * 128 + k] * c + \
|
||||
(int64_t)0x1000000000) >> 37);
|
||||
dest[group * 128 + k] += tmp * (1 << shift);
|
||||
dest[group * 128 + k] += tmp * (1U << shift);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2955,7 +2955,7 @@ static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb)
|
||||
uint8_t layout_map[MAX_ELEM_ID*4][3];
|
||||
int layout_map_tags, ret;
|
||||
|
||||
size = avpriv_aac_parse_header(gb, &hdr_info);
|
||||
size = ff_adts_header_parse(gb, &hdr_info);
|
||||
if (size > 0) {
|
||||
if (!ac->warned_num_aac_frames && hdr_info.num_aac_frames != 1) {
|
||||
// This is 2 for "VLB " audio in NSV files.
|
||||
|
||||
+83
-16
@@ -50,17 +50,59 @@
|
||||
|
||||
static AVOnce aac_table_init = AV_ONCE_INIT;
|
||||
|
||||
static void put_pce(PutBitContext *pb, AVCodecContext *avctx)
|
||||
{
|
||||
int i, j;
|
||||
AACEncContext *s = avctx->priv_data;
|
||||
AACPCEInfo *pce = &s->pce;
|
||||
const int bitexact = avctx->flags & AV_CODEC_FLAG_BITEXACT;
|
||||
const char *aux_data = bitexact ? "Lavc" : LIBAVCODEC_IDENT;
|
||||
|
||||
put_bits(pb, 4, 0);
|
||||
|
||||
put_bits(pb, 2, avctx->profile);
|
||||
put_bits(pb, 4, s->samplerate_index);
|
||||
|
||||
put_bits(pb, 4, pce->num_ele[0]); /* Front */
|
||||
put_bits(pb, 4, pce->num_ele[1]); /* Side */
|
||||
put_bits(pb, 4, pce->num_ele[2]); /* Back */
|
||||
put_bits(pb, 2, pce->num_ele[3]); /* LFE */
|
||||
put_bits(pb, 3, 0); /* Assoc data */
|
||||
put_bits(pb, 4, 0); /* CCs */
|
||||
|
||||
put_bits(pb, 1, 0); /* Stereo mixdown */
|
||||
put_bits(pb, 1, 0); /* Mono mixdown */
|
||||
put_bits(pb, 1, 0); /* Something else */
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < pce->num_ele[i]; j++) {
|
||||
if (i < 3)
|
||||
put_bits(pb, 1, pce->pairing[i][j]);
|
||||
put_bits(pb, 4, pce->index[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
avpriv_align_put_bits(pb);
|
||||
put_bits(pb, 8, strlen(aux_data));
|
||||
avpriv_put_string(pb, aux_data, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make AAC audio config object.
|
||||
* @see 1.6.2.1 "Syntax - AudioSpecificConfig"
|
||||
*/
|
||||
static void put_audio_specific_config(AVCodecContext *avctx)
|
||||
static int put_audio_specific_config(AVCodecContext *avctx)
|
||||
{
|
||||
PutBitContext pb;
|
||||
AACEncContext *s = avctx->priv_data;
|
||||
int channels = s->channels - (s->channels == 8 ? 1 : 0);
|
||||
int channels = (!s->needs_pce)*(s->channels - (s->channels == 8 ? 1 : 0));
|
||||
const int max_size = 32;
|
||||
|
||||
init_put_bits(&pb, avctx->extradata, avctx->extradata_size);
|
||||
avctx->extradata = av_mallocz(max_size);
|
||||
if (!avctx->extradata)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
init_put_bits(&pb, avctx->extradata, max_size);
|
||||
put_bits(&pb, 5, s->profile+1); //profile
|
||||
put_bits(&pb, 4, s->samplerate_index); //sample rate index
|
||||
put_bits(&pb, 4, channels);
|
||||
@@ -68,12 +110,17 @@ static void put_audio_specific_config(AVCodecContext *avctx)
|
||||
put_bits(&pb, 1, 0); //frame length - 1024 samples
|
||||
put_bits(&pb, 1, 0); //does not depend on core coder
|
||||
put_bits(&pb, 1, 0); //is not extension
|
||||
if (s->needs_pce)
|
||||
put_pce(&pb, avctx);
|
||||
|
||||
//Explicitly Mark SBR absent
|
||||
put_bits(&pb, 11, 0x2b7); //sync extension
|
||||
put_bits(&pb, 5, AOT_SBR);
|
||||
put_bits(&pb, 1, 0);
|
||||
flush_put_bits(&pb);
|
||||
avctx->extradata_size = put_bits_count(&pb) >> 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ff_quantize_band_cost_cache_init(struct AACEncContext *s)
|
||||
@@ -488,7 +535,7 @@ static void copy_input_samples(AACEncContext *s, const AVFrame *frame)
|
||||
{
|
||||
int ch;
|
||||
int end = 2048 + (frame ? frame->nb_samples : 0);
|
||||
const uint8_t *channel_map = aac_chan_maps[s->channels - 1];
|
||||
const uint8_t *channel_map = s->reorder_map;
|
||||
|
||||
/* copy and remap input samples */
|
||||
for (ch = 0; ch < s->channels; ch++) {
|
||||
@@ -895,7 +942,6 @@ static av_cold int alloc_buffers(AVCodecContext *avctx, AACEncContext *s)
|
||||
int ch;
|
||||
FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->buffer.samples, s->channels, 3 * 1024 * sizeof(s->buffer.samples[0]), alloc_fail);
|
||||
FF_ALLOCZ_ARRAY_OR_GOTO(avctx, s->cpe, s->chan_map[0], sizeof(ChannelElement), alloc_fail);
|
||||
FF_ALLOCZ_OR_GOTO(avctx, avctx->extradata, 5 + AV_INPUT_BUFFER_PADDING_SIZE, alloc_fail);
|
||||
|
||||
for(ch = 0; ch < s->channels; ch++)
|
||||
s->planar_samples[ch] = s->buffer.samples + 3 * 1024 * ch;
|
||||
@@ -920,16 +966,35 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
|
||||
|
||||
/* Constants */
|
||||
s->last_frame_pb_count = 0;
|
||||
avctx->extradata_size = 5;
|
||||
avctx->frame_size = 1024;
|
||||
avctx->initial_padding = 1024;
|
||||
s->lambda = avctx->global_quality > 0 ? avctx->global_quality : 120;
|
||||
|
||||
/* Channel map and unspecified bitrate guessing */
|
||||
s->channels = avctx->channels;
|
||||
ERROR_IF(s->channels > AAC_MAX_CHANNELS || s->channels == 7,
|
||||
"Unsupported number of channels: %d\n", s->channels);
|
||||
s->chan_map = aac_chan_configs[s->channels-1];
|
||||
|
||||
s->needs_pce = 1;
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(aac_normal_chan_layouts); i++) {
|
||||
if (avctx->channel_layout == aac_normal_chan_layouts[i]) {
|
||||
s->needs_pce = s->options.pce;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->needs_pce) {
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(aac_pce_configs); i++)
|
||||
if (avctx->channel_layout == aac_pce_configs[i].layout)
|
||||
break;
|
||||
ERROR_IF(i == FF_ARRAY_ELEMS(aac_pce_configs), "Unsupported channel layout\n");
|
||||
av_log(avctx, AV_LOG_INFO, "Using a PCE to encode channel layout\n");
|
||||
s->pce = aac_pce_configs[i];
|
||||
s->reorder_map = s->pce.reorder_map;
|
||||
s->chan_map = s->pce.config_map;
|
||||
} else {
|
||||
s->reorder_map = aac_chan_maps[s->channels - 1];
|
||||
s->chan_map = aac_chan_configs[s->channels - 1];
|
||||
}
|
||||
|
||||
if (!avctx->bit_rate) {
|
||||
for (i = 1; i <= s->chan_map[0]; i++) {
|
||||
avctx->bit_rate += s->chan_map[i] == TYPE_CPE ? 128000 : /* Pair */
|
||||
@@ -1015,7 +1080,8 @@ static av_cold int aac_encode_init(AVCodecContext *avctx)
|
||||
if ((ret = alloc_buffers(avctx, s)) < 0)
|
||||
goto fail;
|
||||
|
||||
put_audio_specific_config(avctx);
|
||||
if ((ret = put_audio_specific_config(avctx)))
|
||||
goto fail;
|
||||
|
||||
sizes[0] = ff_aac_swb_size_1024[s->samplerate_index];
|
||||
sizes[1] = ff_aac_swb_size_128[s->samplerate_index];
|
||||
@@ -1052,24 +1118,25 @@ fail:
|
||||
|
||||
#define AACENC_FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
|
||||
static const AVOption aacenc_options[] = {
|
||||
{"aac_coder", "Coding algorithm", offsetof(AACEncContext, options.coder), AV_OPT_TYPE_INT, {.i64 = AAC_CODER_TWOLOOP}, 0, AAC_CODER_NB-1, AACENC_FLAGS, "coder"},
|
||||
{"aac_coder", "Coding algorithm", offsetof(AACEncContext, options.coder), AV_OPT_TYPE_INT, {.i64 = AAC_CODER_FAST}, 0, AAC_CODER_NB-1, AACENC_FLAGS, "coder"},
|
||||
{"anmr", "ANMR method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_ANMR}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"},
|
||||
{"twoloop", "Two loop searching method", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_TWOLOOP}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"},
|
||||
{"fast", "Constant quantizer", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_FAST}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"},
|
||||
{"fast", "Default fast search", 0, AV_OPT_TYPE_CONST, {.i64 = AAC_CODER_FAST}, INT_MIN, INT_MAX, AACENC_FLAGS, "coder"},
|
||||
{"aac_ms", "Force M/S stereo coding", offsetof(AACEncContext, options.mid_side), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, AACENC_FLAGS},
|
||||
{"aac_is", "Intensity stereo coding", offsetof(AACEncContext, options.intensity_stereo), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
|
||||
{"aac_pns", "Perceptual noise substitution", offsetof(AACEncContext, options.pns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
|
||||
{"aac_tns", "Temporal noise shaping", offsetof(AACEncContext, options.tns), AV_OPT_TYPE_BOOL, {.i64 = 1}, -1, 1, AACENC_FLAGS},
|
||||
{"aac_ltp", "Long term prediction", offsetof(AACEncContext, options.ltp), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
|
||||
{"aac_pred", "AAC-Main prediction", offsetof(AACEncContext, options.pred), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
|
||||
{"aac_pce", "Forces the use of PCEs", offsetof(AACEncContext, options.pce), AV_OPT_TYPE_BOOL, {.i64 = 0}, -1, 1, AACENC_FLAGS},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static const AVClass aacenc_class = {
|
||||
"AAC encoder",
|
||||
av_default_item_name,
|
||||
aacenc_options,
|
||||
LIBAVUTIL_VERSION_INT,
|
||||
.class_name = "AAC encoder",
|
||||
.item_name = av_default_item_name,
|
||||
.option = aacenc_options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
static const AVCodecDefault aac_encode_defaults[] = {
|
||||
|
||||
+285
-1
@@ -45,6 +45,7 @@ typedef struct AACEncOptions {
|
||||
int pns;
|
||||
int tns;
|
||||
int ltp;
|
||||
int pce;
|
||||
int pred;
|
||||
int mid_side;
|
||||
int intensity_stereo;
|
||||
@@ -89,6 +90,286 @@ typedef struct AACQuantizeBandCostCacheEntry {
|
||||
uint16_t generation;
|
||||
} AACQuantizeBandCostCacheEntry;
|
||||
|
||||
typedef struct AACPCEInfo {
|
||||
int64_t layout;
|
||||
int num_ele[4]; ///< front, side, back, lfe
|
||||
int pairing[3][8]; ///< front, side, back
|
||||
int index[4][8]; ///< front, side, back, lfe
|
||||
uint8_t config_map[16]; ///< configs the encoder's channel specific settings
|
||||
uint8_t reorder_map[16]; ///< maps channels from lavc to aac order
|
||||
} AACPCEInfo;
|
||||
|
||||
/**
|
||||
* List of PCE (Program Configuration Element) for the channel layouts listed
|
||||
* in channel_layout.h
|
||||
*
|
||||
* For those wishing in the future to add other layouts:
|
||||
*
|
||||
* - num_ele: number of elements in each group of front, side, back, lfe channels
|
||||
* (an element is of type SCE (single channel), CPE (channel pair) for
|
||||
* the first 3 groups; and is LFE for LFE group).
|
||||
*
|
||||
* - pairing: 0 for an SCE element or 1 for a CPE; does not apply to LFE group
|
||||
*
|
||||
* - index: there are three independent indices for SCE, CPE and LFE;
|
||||
* they are incremented irrespective of the group to which the element belongs;
|
||||
* they are not reset when going from one group to another
|
||||
*
|
||||
* Example: for 7.0 channel layout,
|
||||
* .pairing = { { 1, 0 }, { 1 }, { 1 }, }, (3 CPE and 1 SCE in front group)
|
||||
* .index = { { 0, 0 }, { 1 }, { 2 }, },
|
||||
* (index is 0 for the single SCE but goes from 0 to 2 for the CPEs)
|
||||
*
|
||||
* The index order impacts the channel ordering. But is otherwise arbitrary
|
||||
* (the sequence could have been 2, 0, 1 instead of 0, 1, 2).
|
||||
*
|
||||
* Spec allows for discontinuous indices, e.g. if one has a total of two SCE,
|
||||
* SCE.0 SCE.15 is OK per spec; BUT it won't be decoded by our AAC decoder
|
||||
* which at this time requires that indices fully cover some range starting
|
||||
* from 0 (SCE.1 SCE.0 is OK but not SCE.0 SCE.15).
|
||||
*
|
||||
* - config_map: total number of elements and their types. Beware, the way the
|
||||
* types are ordered impacts the final channel ordering.
|
||||
*
|
||||
* - reorder_map: reorders the channels.
|
||||
*
|
||||
*/
|
||||
static const AACPCEInfo aac_pce_configs[] = {
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_MONO,
|
||||
.num_ele = { 1, 0, 0, 0 },
|
||||
.pairing = { { 0 }, },
|
||||
.index = { { 0 }, },
|
||||
.config_map = { 1, TYPE_SCE, },
|
||||
.reorder_map = { 0 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_STEREO,
|
||||
.num_ele = { 1, 0, 0, 0 },
|
||||
.pairing = { { 1 }, },
|
||||
.index = { { 0 }, },
|
||||
.config_map = { 1, TYPE_CPE, },
|
||||
.reorder_map = { 0, 1 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_2POINT1,
|
||||
.num_ele = { 1, 0, 0, 1 },
|
||||
.pairing = { { 1 }, },
|
||||
.index = { { 0 },{ 0 },{ 0 },{ 0 } },
|
||||
.config_map = { 2, TYPE_CPE, TYPE_LFE },
|
||||
.reorder_map = { 0, 1, 2 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_2_1,
|
||||
.num_ele = { 1, 0, 1, 0 },
|
||||
.pairing = { { 1 },{ 0 },{ 0 } },
|
||||
.index = { { 0 },{ 0 },{ 0 }, },
|
||||
.config_map = { 2, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_SURROUND,
|
||||
.num_ele = { 2, 0, 0, 0 },
|
||||
.pairing = { { 1, 0 }, },
|
||||
.index = { { 0, 0 }, },
|
||||
.config_map = { 2, TYPE_CPE, TYPE_SCE, },
|
||||
.reorder_map = { 0, 1, 2 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_3POINT1,
|
||||
.num_ele = { 2, 0, 0, 1 },
|
||||
.pairing = { { 1, 0 }, },
|
||||
.index = { { 0, 0 }, { 0 }, { 0 }, { 0 }, },
|
||||
.config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_LFE },
|
||||
.reorder_map = { 0, 1, 2, 3 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_4POINT0,
|
||||
.num_ele = { 2, 0, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 0 }, },
|
||||
.index = { { 0, 0 }, { 0 }, { 1 } },
|
||||
.config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_4POINT1,
|
||||
.num_ele = { 2, 1, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 0 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 2 }, { 0 } },
|
||||
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_2_2,
|
||||
.num_ele = { 1, 1, 0, 0 },
|
||||
.pairing = { { 1 }, { 1 }, },
|
||||
.index = { { 0 }, { 1 }, },
|
||||
.config_map = { 2, TYPE_CPE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_QUAD,
|
||||
.num_ele = { 1, 0, 1, 0 },
|
||||
.pairing = { { 1 }, { 0 }, { 1 }, },
|
||||
.index = { { 0 }, { 0 }, { 1 } },
|
||||
.config_map = { 2, TYPE_CPE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_5POINT0,
|
||||
.num_ele = { 2, 1, 0, 0 },
|
||||
.pairing = { { 1, 0 }, { 1 }, },
|
||||
.index = { { 0, 0 }, { 1 } },
|
||||
.config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_5POINT1,
|
||||
.num_ele = { 2, 1, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 1 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1 } },
|
||||
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_5POINT0_BACK,
|
||||
.num_ele = { 2, 0, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 1 } },
|
||||
.index = { { 0, 0 }, { 0 }, { 1 } },
|
||||
.config_map = { 3, TYPE_CPE, TYPE_SCE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_5POINT1_BACK,
|
||||
.num_ele = { 2, 1, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 1 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1 } },
|
||||
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_6POINT0,
|
||||
.num_ele = { 2, 1, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 1 }, { 0 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1 } },
|
||||
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_6POINT0_FRONT,
|
||||
.num_ele = { 2, 1, 0, 0 },
|
||||
.pairing = { { 1, 1 }, { 1 } },
|
||||
.index = { { 1, 0 }, { 2 }, },
|
||||
.config_map = { 3, TYPE_CPE, TYPE_CPE, TYPE_CPE, },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_HEXAGONAL,
|
||||
.num_ele = { 2, 0, 2, 0 },
|
||||
.pairing = { { 1, 0 },{ 0 },{ 1, 0 }, },
|
||||
.index = { { 0, 0 },{ 0 },{ 1, 1 } },
|
||||
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_6POINT1,
|
||||
.num_ele = { 2, 1, 2, 0 },
|
||||
.pairing = { { 1, 0 },{ 0 },{ 1, 0 }, },
|
||||
.index = { { 0, 0 },{ 1 },{ 1, 2 } },
|
||||
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_6POINT1_BACK,
|
||||
.num_ele = { 2, 1, 2, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 1, 0 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1, 2 } },
|
||||
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_6POINT1_FRONT,
|
||||
.num_ele = { 2, 1, 2, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 1, 0 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1, 2 } },
|
||||
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_7POINT0,
|
||||
.num_ele = { 2, 1, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 1 }, { 1 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 2 }, },
|
||||
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_7POINT0_FRONT,
|
||||
.num_ele = { 2, 1, 1, 0 },
|
||||
.pairing = { { 1, 0 }, { 1 }, { 1 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 2 }, },
|
||||
.config_map = { 4, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_7POINT1,
|
||||
.num_ele = { 2, 1, 2, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 1, 1 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },
|
||||
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_7POINT1_WIDE,
|
||||
.num_ele = { 2, 1, 2, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 },{ 1, 1 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },
|
||||
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_7POINT1_WIDE_BACK,
|
||||
.num_ele = { 2, 1, 2, 0 },
|
||||
.pairing = { { 1, 0 }, { 0 }, { 1, 1 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 1, 2 }, { 0 } },
|
||||
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_SCE, TYPE_CPE, TYPE_CPE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_OCTAGONAL,
|
||||
.num_ele = { 2, 1, 2, 0 },
|
||||
.pairing = { { 1, 0 }, { 1 }, { 1, 0 }, },
|
||||
.index = { { 0, 0 }, { 1 }, { 2, 1 } },
|
||||
.config_map = { 5, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7 },
|
||||
},
|
||||
{ /* Meant for order 2/mixed ambisonics */
|
||||
.layout = AV_CH_LAYOUT_OCTAGONAL | AV_CH_TOP_CENTER,
|
||||
.num_ele = { 2, 2, 2, 0 },
|
||||
.pairing = { { 1, 0 }, { 1, 0 }, { 1, 0 }, },
|
||||
.index = { { 0, 0 }, { 1, 1 }, { 2, 2 } },
|
||||
.config_map = { 6, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8 },
|
||||
},
|
||||
{ /* Meant for order 2/mixed ambisonics */
|
||||
.layout = AV_CH_LAYOUT_6POINT0_FRONT | AV_CH_BACK_CENTER |
|
||||
AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT | AV_CH_TOP_CENTER,
|
||||
.num_ele = { 2, 2, 2, 0 },
|
||||
.pairing = { { 1, 1 }, { 1, 0 }, { 1, 0 }, },
|
||||
.index = { { 0, 1 }, { 2, 0 }, { 3, 1 } },
|
||||
.config_map = { 6, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
|
||||
},
|
||||
{
|
||||
.layout = AV_CH_LAYOUT_HEXADECAGONAL,
|
||||
.num_ele = { 4, 2, 4, 0 },
|
||||
.pairing = { { 1, 0, 1, 0 }, { 1, 1 }, { 1, 0, 1, 0 }, },
|
||||
.index = { { 0, 0, 1, 1 }, { 2, 3 }, { 4, 2, 5, 3 } },
|
||||
.config_map = { 10, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_CPE, TYPE_CPE, TYPE_SCE, TYPE_CPE, TYPE_SCE },
|
||||
.reorder_map = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* AAC encoder context
|
||||
*/
|
||||
@@ -99,12 +380,15 @@ typedef struct AACEncContext {
|
||||
FFTContext mdct1024; ///< long (1024 samples) frame transform context
|
||||
FFTContext mdct128; ///< short (128 samples) frame transform context
|
||||
AVFloatDSPContext *fdsp;
|
||||
float *planar_samples[8]; ///< saved preprocessed input
|
||||
AACPCEInfo pce; ///< PCE data, if needed
|
||||
float *planar_samples[16]; ///< saved preprocessed input
|
||||
|
||||
int profile; ///< copied from avctx
|
||||
int needs_pce; ///< flag for non-standard layout
|
||||
LPCContext lpc; ///< used by TNS
|
||||
int samplerate_index; ///< MPEG-4 samplerate index
|
||||
int channels; ///< channel count
|
||||
const uint8_t *reorder_map; ///< lavc to aac reorder map
|
||||
const uint8_t *chan_map; ///< channel configuration map
|
||||
|
||||
ChannelElement *cpe; ///< channel elements
|
||||
|
||||
+12
-1
@@ -36,13 +36,24 @@
|
||||
/** Total number of codebooks, including special ones **/
|
||||
#define CB_TOT_ALL 15
|
||||
|
||||
#define AAC_MAX_CHANNELS 8
|
||||
#define AAC_MAX_CHANNELS 16
|
||||
|
||||
extern const uint8_t *ff_aac_swb_size_1024[];
|
||||
extern const int ff_aac_swb_size_1024_len;
|
||||
extern const uint8_t *ff_aac_swb_size_128[];
|
||||
extern const int ff_aac_swb_size_128_len;
|
||||
|
||||
/* Supported layouts without using a PCE */
|
||||
static const int64_t aac_normal_chan_layouts[7] = {
|
||||
AV_CH_LAYOUT_MONO,
|
||||
AV_CH_LAYOUT_STEREO,
|
||||
AV_CH_LAYOUT_SURROUND,
|
||||
AV_CH_LAYOUT_4POINT0,
|
||||
AV_CH_LAYOUT_5POINT0_BACK,
|
||||
AV_CH_LAYOUT_5POINT1_BACK,
|
||||
AV_CH_LAYOUT_7POINT1,
|
||||
};
|
||||
|
||||
/** default channel configurations */
|
||||
static const uint8_t aac_chan_configs[AAC_MAX_CHANNELS][6] = {
|
||||
{1, TYPE_SCE}, // 1 channel - single channel element
|
||||
|
||||
@@ -130,12 +130,12 @@ static void ps_decorrelate_c(INTFLOAT (*out)[2], INTFLOAT (*delay)[2],
|
||||
INTFLOAT apd_im = in_im;
|
||||
in_re = AAC_MSUB30(link_delay_re, fractional_delay_re,
|
||||
link_delay_im, fractional_delay_im);
|
||||
in_re -= a_re;
|
||||
in_re -= (UINTFLOAT)a_re;
|
||||
in_im = AAC_MADD30(link_delay_re, fractional_delay_im,
|
||||
link_delay_im, fractional_delay_re);
|
||||
in_im -= a_im;
|
||||
ap_delay[m][n+5][0] = apd_re + AAC_MUL31(ag[m], in_re);
|
||||
ap_delay[m][n+5][1] = apd_im + AAC_MUL31(ag[m], in_im);
|
||||
in_im -= (UINTFLOAT)a_im;
|
||||
ap_delay[m][n+5][0] = apd_re + (UINTFLOAT)AAC_MUL31(ag[m], in_re);
|
||||
ap_delay[m][n+5][1] = apd_im + (UINTFLOAT)AAC_MUL31(ag[m], in_im);
|
||||
}
|
||||
out[n][0] = AAC_MUL16(transient_gain[n], in_re);
|
||||
out[n][1] = AAC_MUL16(transient_gain[n], in_im);
|
||||
|
||||
@@ -433,6 +433,7 @@ static void sbr_gain_calc(AACContext *ac, SpectralBandReplication *sbr,
|
||||
av_add_sf(FLOAT_1, sbr->e_curr[e][m]),
|
||||
av_add_sf(FLOAT_1, sbr->q_mapped[e][m]))));
|
||||
}
|
||||
sbr->gain[e][m] = av_add_sf(sbr->gain[e][m], FLOAT_MIN);
|
||||
}
|
||||
for (m = sbr->f_tablelim[k] - sbr->kx[1]; m < sbr->f_tablelim[k + 1] - sbr->kx[1]; m++) {
|
||||
sum[0] = av_add_sf(sum[0], sbr->e_origmapped[e][m]);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#define WFRAC_BITS 16 // fractional bits for window
|
||||
#define OUT_SHIFT (WFRAC_BITS + FRAC_BITS - 15)
|
||||
|
||||
const tbl_rev128.s, align=4
|
||||
const tbl_rev128_s, align=4
|
||||
.byte 12, 13, 14, 15
|
||||
.byte 8, 9, 10, 11
|
||||
.byte 4, 5, 6, 7
|
||||
@@ -39,7 +39,7 @@ function ff_mpadsp_apply_window_\type\()_neon, export=1
|
||||
ld1 {v4.4s,v5.4s,v6.4s,v7.4s}, [x7], #64
|
||||
st1 {v0.4s,v1.4s,v2.4s,v3.4s}, [x8], #64
|
||||
st1 {v4.4s,v5.4s,v6.4s,v7.4s}, [x8], #64
|
||||
movrel x15, tbl_rev128.s
|
||||
movrel x15, tbl_rev128_s
|
||||
ld1 {v27.4s}, [x15]
|
||||
.ifc \type, fixed
|
||||
lsl x4, x4, #1
|
||||
|
||||
+62
-10
@@ -20,15 +20,19 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "parser.h"
|
||||
#include "ac3_parser.h"
|
||||
#include "ac3_parser_internal.h"
|
||||
#include "aac_ac3_parser.h"
|
||||
#include "get_bits.h"
|
||||
|
||||
|
||||
#define AC3_HEADER_SIZE 7
|
||||
|
||||
#if CONFIG_AC3_PARSER
|
||||
|
||||
static const uint8_t eac3_blocks[4] = {
|
||||
1, 2, 3, 6
|
||||
@@ -47,16 +51,9 @@ static const uint8_t center_levels[4] = { 4, 5, 6, 5 };
|
||||
static const uint8_t surround_levels[4] = { 4, 6, 7, 6 };
|
||||
|
||||
|
||||
int avpriv_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo **phdr)
|
||||
int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr)
|
||||
{
|
||||
int frame_size_code;
|
||||
AC3HeaderInfo *hdr;
|
||||
|
||||
if (!*phdr)
|
||||
*phdr = av_mallocz(sizeof(AC3HeaderInfo));
|
||||
if (!*phdr)
|
||||
return AVERROR(ENOMEM);
|
||||
hdr = *phdr;
|
||||
|
||||
memset(hdr, 0, sizeof(*hdr));
|
||||
|
||||
@@ -151,6 +148,46 @@ int avpriv_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo **phdr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: Better way to pass AC3HeaderInfo fields to mov muxer.
|
||||
int avpriv_ac3_parse_header(AC3HeaderInfo **phdr, const uint8_t *buf,
|
||||
size_t size)
|
||||
{
|
||||
GetBitContext gb;
|
||||
AC3HeaderInfo *hdr;
|
||||
int err;
|
||||
|
||||
if (!*phdr)
|
||||
*phdr = av_mallocz(sizeof(AC3HeaderInfo));
|
||||
if (!*phdr)
|
||||
return AVERROR(ENOMEM);
|
||||
hdr = *phdr;
|
||||
|
||||
init_get_bits8(&gb, buf, size);
|
||||
err = ff_ac3_parse_header(&gb, hdr);
|
||||
if (err < 0)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
return get_bits_count(&gb);
|
||||
}
|
||||
|
||||
int av_ac3_parse_header(const uint8_t *buf, size_t size,
|
||||
uint8_t *bitstream_id, uint16_t *frame_size)
|
||||
{
|
||||
GetBitContext gb;
|
||||
AC3HeaderInfo hdr;
|
||||
int err;
|
||||
|
||||
init_get_bits8(&gb, buf, size);
|
||||
err = ff_ac3_parse_header(&gb, &hdr);
|
||||
if (err < 0)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
*bitstream_id = hdr.bitstream_id;
|
||||
*frame_size = hdr.frame_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ac3_sync(uint64_t state, AACAC3ParseContext *hdr_info,
|
||||
int *need_next_header, int *new_frame_start)
|
||||
{
|
||||
@@ -159,11 +196,11 @@ static int ac3_sync(uint64_t state, AACAC3ParseContext *hdr_info,
|
||||
uint64_t u64;
|
||||
uint8_t u8[8 + AV_INPUT_BUFFER_PADDING_SIZE];
|
||||
} tmp = { av_be2ne64(state) };
|
||||
AC3HeaderInfo hdr, *phdr = &hdr;
|
||||
AC3HeaderInfo hdr;
|
||||
GetBitContext gbc;
|
||||
|
||||
init_get_bits(&gbc, tmp.u8+8-AC3_HEADER_SIZE, 54);
|
||||
err = avpriv_ac3_parse_header(&gbc, &phdr);
|
||||
err = ff_ac3_parse_header(&gbc, &hdr);
|
||||
|
||||
if(err < 0)
|
||||
return 0;
|
||||
@@ -202,3 +239,18 @@ AVCodecParser ff_ac3_parser = {
|
||||
.parser_parse = ff_aac_ac3_parse,
|
||||
.parser_close = ff_parse_close,
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
int avpriv_ac3_parse_header(AC3HeaderInfo **phdr, const uint8_t *buf,
|
||||
size_t size)
|
||||
{
|
||||
return AVERROR(ENOSYS);
|
||||
}
|
||||
|
||||
int av_ac3_parse_header(const uint8_t *buf, size_t size,
|
||||
uint8_t *bitstream_id, uint16_t *frame_size)
|
||||
{
|
||||
return AVERROR(ENOSYS);
|
||||
}
|
||||
#endif
|
||||
|
||||
+6
-12
@@ -23,20 +23,14 @@
|
||||
#ifndef AVCODEC_AC3_PARSER_H
|
||||
#define AVCODEC_AC3_PARSER_H
|
||||
|
||||
#include "ac3.h"
|
||||
#include "get_bits.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Parse AC-3 frame header.
|
||||
* Parse the header up to the lfeon element, which is the first 52 or 54 bits
|
||||
* depending on the audio coding mode.
|
||||
* @param[in] gbc BitContext containing the first 54 bits of the frame.
|
||||
* @param[out] hdr Pointer to Pointer to struct where header info is written.
|
||||
* will be allocated if NULL
|
||||
* @return Returns 0 on success, -1 if there is a sync word mismatch,
|
||||
* -2 if the bsid (version) element is invalid, -3 if the fscod (sample rate)
|
||||
* element is invalid, or -4 if the frmsizecod (bit rate) element is invalid.
|
||||
* Extract the bitstream ID and the frame size from AC-3 data.
|
||||
*/
|
||||
int avpriv_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo **hdr);
|
||||
int av_ac3_parse_header(const uint8_t *buf, size_t size,
|
||||
uint8_t *bitstream_id, uint16_t *frame_size);
|
||||
|
||||
|
||||
#endif /* AVCODEC_AC3_PARSER_H */
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* AC-3 parser internal code
|
||||
*
|
||||
* 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_AC3_PARSER_INTERNAL_H
|
||||
#define AVCODEC_AC3_PARSER_INTERNAL_H
|
||||
|
||||
#include "ac3.h"
|
||||
#include "get_bits.h"
|
||||
|
||||
/**
|
||||
* Parse AC-3 frame header.
|
||||
* Parse the header up to the lfeon element, which is the first 52 or 54 bits
|
||||
* depending on the audio coding mode.
|
||||
* @param[in] gbc BitContext containing the first 54 bits of the frame.
|
||||
* @param[out] hdr Pointer to struct where header info is written.
|
||||
* @return Returns 0 on success, -1 if there is a sync word mismatch,
|
||||
* -2 if the bsid (version) element is invalid, -3 if the fscod (sample rate)
|
||||
* element is invalid, or -4 if the frmsizecod (bit rate) element is invalid.
|
||||
*/
|
||||
int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr);
|
||||
|
||||
int avpriv_ac3_parse_header(AC3HeaderInfo **hdr, const uint8_t *buf,
|
||||
size_t size);
|
||||
|
||||
#endif /* AVCODEC_AC3_PARSER_INTERNAL_H */
|
||||
+3
-3
@@ -36,7 +36,7 @@
|
||||
#include "bswapdsp.h"
|
||||
#include "internal.h"
|
||||
#include "aac_ac3_parser.h"
|
||||
#include "ac3_parser.h"
|
||||
#include "ac3_parser_internal.h"
|
||||
#include "ac3dec.h"
|
||||
#include "ac3dec_data.h"
|
||||
#include "kbdwin.h"
|
||||
@@ -297,10 +297,10 @@ static int ac3_parse_header(AC3DecodeContext *s)
|
||||
*/
|
||||
static int parse_frame_header(AC3DecodeContext *s)
|
||||
{
|
||||
AC3HeaderInfo hdr, *phdr=&hdr;
|
||||
AC3HeaderInfo hdr;
|
||||
int err;
|
||||
|
||||
err = avpriv_ac3_parse_header(&s->gbc, &phdr);
|
||||
err = ff_ac3_parse_header(&s->gbc, &hdr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
+2
-1
@@ -26,10 +26,11 @@
|
||||
|
||||
#include "libavutil/internal.h"
|
||||
#include "ac3.h"
|
||||
#include "internal.h"
|
||||
|
||||
extern const uint16_t ff_ac3_frame_size_tab[38][3];
|
||||
extern const uint8_t ff_ac3_channels_tab[8];
|
||||
extern av_export const uint16_t avpriv_ac3_channel_layout_tab[8];
|
||||
extern av_export_avcodec const uint16_t avpriv_ac3_channel_layout_tab[8];
|
||||
extern const uint8_t ff_ac3_enc_channel_map[8][2][6];
|
||||
extern const uint8_t ff_ac3_dec_channel_map[8][2][6];
|
||||
extern const uint16_t ff_ac3_sample_rate_tab[3];
|
||||
|
||||
@@ -1115,6 +1115,7 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
|
||||
int16_t *out1 = samples_p[1];
|
||||
int samples_per_block = 28 * (3 - avctx->channels) * 4;
|
||||
int sample_offset = 0;
|
||||
int bytes_remaining;
|
||||
while (bytestream2_get_bytes_left(&gb) >= 128) {
|
||||
if ((ret = xa_decode(avctx, out0, out1, buf + bytestream2_tell(&gb),
|
||||
&c->status[0], &c->status[1],
|
||||
@@ -1123,6 +1124,12 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data,
|
||||
bytestream2_skipu(&gb, 128);
|
||||
sample_offset += samples_per_block;
|
||||
}
|
||||
/* Less than a full block of data left, e.g. when reading from
|
||||
* 2324 byte per sector XA; the remainder is padding */
|
||||
bytes_remaining = bytestream2_get_bytes_left(&gb);
|
||||
if (bytes_remaining > 0) {
|
||||
bytestream2_skip(&gb, bytes_remaining);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AV_CODEC_ID_ADPCM_IMA_EA_EACS:
|
||||
|
||||
@@ -22,11 +22,12 @@
|
||||
*/
|
||||
|
||||
#include "aac_ac3_parser.h"
|
||||
#include "aacadtsdec.h"
|
||||
#include "adts_header.h"
|
||||
#include "adts_parser.h"
|
||||
#include "get_bits.h"
|
||||
#include "mpeg4audio.h"
|
||||
|
||||
int avpriv_aac_parse_header(GetBitContext *gbc, AACADTSHeaderInfo *hdr)
|
||||
int ff_adts_header_parse(GetBitContext *gbc, AACADTSHeaderInfo *hdr)
|
||||
{
|
||||
int size, rdb, ch, sr;
|
||||
int aot, crc_abs;
|
||||
@@ -51,7 +52,7 @@ int avpriv_aac_parse_header(GetBitContext *gbc, AACADTSHeaderInfo *hdr)
|
||||
skip_bits1(gbc); /* copyright_identification_bit */
|
||||
skip_bits1(gbc); /* copyright_identification_start */
|
||||
size = get_bits(gbc, 13); /* aac_frame_length */
|
||||
if (size < AAC_ADTS_HEADER_SIZE)
|
||||
if (size < AV_AAC_ADTS_HEADER_SIZE)
|
||||
return AAC_AC3_PARSE_ERROR_FRAME_SIZE;
|
||||
|
||||
skip_bits(gbc, 11); /* adts_buffer_fullness */
|
||||
@@ -20,14 +20,11 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef AVCODEC_AACADTSDEC_H
|
||||
#define AVCODEC_AACADTSDEC_H
|
||||
#ifndef AVCODEC_ADTS_HEADER_H
|
||||
#define AVCODEC_ADTS_HEADER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "get_bits.h"
|
||||
|
||||
#define AAC_ADTS_HEADER_SIZE 7
|
||||
|
||||
typedef struct AACADTSHeaderInfo {
|
||||
uint32_t sample_rate;
|
||||
uint32_t samples;
|
||||
@@ -40,7 +37,6 @@ typedef struct AACADTSHeaderInfo {
|
||||
} AACADTSHeaderInfo;
|
||||
|
||||
/**
|
||||
* Parse AAC frame header.
|
||||
* Parse the ADTS frame header to the end of the variable header, which is
|
||||
* the first 54 bits.
|
||||
* @param[in] gbc BitContext containing the first 54 bits of the frame.
|
||||
@@ -49,6 +45,6 @@ typedef struct AACADTSHeaderInfo {
|
||||
* -2 if the version element is invalid, -3 if the sample rate
|
||||
* element is invalid, or -4 if the bit rate element is invalid.
|
||||
*/
|
||||
int avpriv_aac_parse_header(GetBitContext *gbc, AACADTSHeaderInfo *hdr);
|
||||
int ff_adts_header_parse(GetBitContext *gbc, AACADTSHeaderInfo *hdr);
|
||||
|
||||
#endif /* AVCODEC_AACADTSDEC_H */
|
||||
#endif /* AVCODEC_ADTS_HEADER_H */
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "adts_header.h"
|
||||
#include "adts_parser.h"
|
||||
|
||||
int av_adts_header_parse(const uint8_t *buf, uint32_t *samples, uint8_t *frames)
|
||||
{
|
||||
#if CONFIG_ADTS_HEADER
|
||||
GetBitContext gb;
|
||||
AACADTSHeaderInfo hdr;
|
||||
int err = init_get_bits8(&gb, buf, AV_AAC_ADTS_HEADER_SIZE);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = ff_adts_header_parse(&gb, &hdr);
|
||||
if (err < 0)
|
||||
return err;
|
||||
*samples = hdr.samples;
|
||||
*frames = hdr.num_aac_frames;
|
||||
return 0;
|
||||
#else
|
||||
return AVERROR(ENOSYS);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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_ADTS_PARSER_H
|
||||
#define AVCODEC_ADTS_PARSER_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define AV_AAC_ADTS_HEADER_SIZE 7
|
||||
|
||||
/**
|
||||
* Extract the number of samples and frames from AAC data.
|
||||
* @param[in] buf pointer to AAC data buffer
|
||||
* @param[out] samples Pointer to where number of samples is written
|
||||
* @param[out] frames Pointer to where number of frames is written
|
||||
* @return Returns 0 on success, error code on failure.
|
||||
*/
|
||||
int av_adts_header_parse(const uint8_t *buf, uint32_t *samples,
|
||||
uint8_t *frames);
|
||||
|
||||
#endif /* AVCODEC_ADTS_PARSER_H */
|
||||
+1
-1
@@ -524,7 +524,7 @@ static int alac_set_info(ALACContext *alac)
|
||||
|
||||
alac->max_samples_per_frame = bytestream2_get_be32u(&gb);
|
||||
if (!alac->max_samples_per_frame ||
|
||||
alac->max_samples_per_frame > INT_MAX / sizeof(int32_t)) {
|
||||
alac->max_samples_per_frame > 4096 * 4096) {
|
||||
av_log(alac->avctx, AV_LOG_ERROR,
|
||||
"max samples per frame invalid: %"PRIu32"\n",
|
||||
alac->max_samples_per_frame);
|
||||
|
||||
+6
-97
@@ -29,13 +29,6 @@
|
||||
#include "avcodec.h"
|
||||
#include "version.h"
|
||||
|
||||
#define REGISTER_HWACCEL(X, x) \
|
||||
{ \
|
||||
extern AVHWAccel ff_##x##_hwaccel; \
|
||||
if (CONFIG_##X##_HWACCEL) \
|
||||
av_register_hwaccel(&ff_##x##_hwaccel); \
|
||||
}
|
||||
|
||||
#define REGISTER_ENCODER(X, x) \
|
||||
{ \
|
||||
extern AVCodec ff_##x##_encoder; \
|
||||
@@ -61,75 +54,6 @@
|
||||
|
||||
static void register_all(void)
|
||||
{
|
||||
/* hardware accelerators */
|
||||
REGISTER_HWACCEL(H263_VAAPI, h263_vaapi);
|
||||
REGISTER_HWACCEL(H263_VIDEOTOOLBOX, h263_videotoolbox);
|
||||
REGISTER_HWACCEL(H264_CUVID, h264_cuvid);
|
||||
REGISTER_HWACCEL(H264_D3D11VA, h264_d3d11va);
|
||||
REGISTER_HWACCEL(H264_D3D11VA2, h264_d3d11va2);
|
||||
REGISTER_HWACCEL(H264_DXVA2, h264_dxva2);
|
||||
REGISTER_HWACCEL(H264_MEDIACODEC, h264_mediacodec);
|
||||
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);
|
||||
REGISTER_HWACCEL(HEVC_D3D11VA, hevc_d3d11va);
|
||||
REGISTER_HWACCEL(HEVC_D3D11VA2, hevc_d3d11va2);
|
||||
REGISTER_HWACCEL(HEVC_DXVA2, hevc_dxva2);
|
||||
REGISTER_HWACCEL(HEVC_MEDIACODEC, hevc_mediacodec);
|
||||
REGISTER_HWACCEL(HEVC_QSV, hevc_qsv);
|
||||
REGISTER_HWACCEL(HEVC_VAAPI, hevc_vaapi);
|
||||
REGISTER_HWACCEL(HEVC_VDPAU, hevc_vdpau);
|
||||
REGISTER_HWACCEL(HEVC_VIDEOTOOLBOX, hevc_videotoolbox);
|
||||
REGISTER_HWACCEL(MJPEG_CUVID, mjpeg_cuvid);
|
||||
REGISTER_HWACCEL(MPEG1_CUVID, mpeg1_cuvid);
|
||||
REGISTER_HWACCEL(MPEG1_XVMC, mpeg1_xvmc);
|
||||
REGISTER_HWACCEL(MPEG1_VDPAU, mpeg1_vdpau);
|
||||
REGISTER_HWACCEL(MPEG1_VIDEOTOOLBOX, mpeg1_videotoolbox);
|
||||
REGISTER_HWACCEL(MPEG2_CUVID, mpeg2_cuvid);
|
||||
REGISTER_HWACCEL(MPEG2_XVMC, mpeg2_xvmc);
|
||||
REGISTER_HWACCEL(MPEG2_D3D11VA, mpeg2_d3d11va);
|
||||
REGISTER_HWACCEL(MPEG2_D3D11VA2, mpeg2_d3d11va2);
|
||||
REGISTER_HWACCEL(MPEG2_DXVA2, mpeg2_dxva2);
|
||||
REGISTER_HWACCEL(MPEG2_MMAL, mpeg2_mmal);
|
||||
REGISTER_HWACCEL(MPEG2_QSV, mpeg2_qsv);
|
||||
REGISTER_HWACCEL(MPEG2_VAAPI, mpeg2_vaapi);
|
||||
REGISTER_HWACCEL(MPEG2_VDPAU, mpeg2_vdpau);
|
||||
REGISTER_HWACCEL(MPEG2_VIDEOTOOLBOX, mpeg2_videotoolbox);
|
||||
REGISTER_HWACCEL(MPEG2_MEDIACODEC, mpeg2_mediacodec);
|
||||
REGISTER_HWACCEL(MPEG4_CUVID, mpeg4_cuvid);
|
||||
REGISTER_HWACCEL(MPEG4_MEDIACODEC, mpeg4_mediacodec);
|
||||
REGISTER_HWACCEL(MPEG4_MMAL, mpeg4_mmal);
|
||||
REGISTER_HWACCEL(MPEG4_VAAPI, mpeg4_vaapi);
|
||||
REGISTER_HWACCEL(MPEG4_VDPAU, mpeg4_vdpau);
|
||||
REGISTER_HWACCEL(MPEG4_VIDEOTOOLBOX, mpeg4_videotoolbox);
|
||||
REGISTER_HWACCEL(VC1_CUVID, vc1_cuvid);
|
||||
REGISTER_HWACCEL(VC1_D3D11VA, vc1_d3d11va);
|
||||
REGISTER_HWACCEL(VC1_D3D11VA2, vc1_d3d11va2);
|
||||
REGISTER_HWACCEL(VC1_DXVA2, vc1_dxva2);
|
||||
REGISTER_HWACCEL(VC1_VAAPI, vc1_vaapi);
|
||||
REGISTER_HWACCEL(VC1_VDPAU, vc1_vdpau);
|
||||
REGISTER_HWACCEL(VC1_MMAL, vc1_mmal);
|
||||
REGISTER_HWACCEL(VC1_QSV, vc1_qsv);
|
||||
REGISTER_HWACCEL(VP8_CUVID, vp8_cuvid);
|
||||
REGISTER_HWACCEL(VP8_MEDIACODEC, vp8_mediacodec);
|
||||
REGISTER_HWACCEL(VP8_QSV, vp8_qsv);
|
||||
REGISTER_HWACCEL(VP9_CUVID, vp9_cuvid);
|
||||
REGISTER_HWACCEL(VP9_D3D11VA, vp9_d3d11va);
|
||||
REGISTER_HWACCEL(VP9_D3D11VA2, vp9_d3d11va2);
|
||||
REGISTER_HWACCEL(VP9_DXVA2, vp9_dxva2);
|
||||
REGISTER_HWACCEL(VP9_MEDIACODEC, vp9_mediacodec);
|
||||
REGISTER_HWACCEL(VP9_VAAPI, vp9_vaapi);
|
||||
REGISTER_HWACCEL(WMV3_D3D11VA, wmv3_d3d11va);
|
||||
REGISTER_HWACCEL(WMV3_D3D11VA2, wmv3_d3d11va2);
|
||||
REGISTER_HWACCEL(WMV3_DXVA2, wmv3_dxva2);
|
||||
REGISTER_HWACCEL(WMV3_VAAPI, wmv3_vaapi);
|
||||
REGISTER_HWACCEL(WMV3_VDPAU, wmv3_vdpau);
|
||||
|
||||
/* video codecs */
|
||||
REGISTER_ENCODER(A64MULTI, a64multi);
|
||||
REGISTER_ENCODER(A64MULTI5, a64multi5);
|
||||
@@ -217,10 +141,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
|
||||
REGISTER_ENCDEC (HAP, hap);
|
||||
REGISTER_DECODER(HEVC, hevc);
|
||||
REGISTER_DECODER(HEVC_QSV, hevc_qsv);
|
||||
@@ -246,30 +166,20 @@ static void register_all(void)
|
||||
REGISTER_ENCODER(LJPEG, ljpeg);
|
||||
REGISTER_DECODER(LOCO, loco);
|
||||
REGISTER_DECODER(M101, m101);
|
||||
REGISTER_DECODER(MAGICYUV, magicyuv);
|
||||
REGISTER_ENCDEC (MAGICYUV, magicyuv);
|
||||
REGISTER_DECODER(MDEC, mdec);
|
||||
REGISTER_DECODER(MIMIC, mimic);
|
||||
REGISTER_ENCDEC (MJPEG, mjpeg);
|
||||
REGISTER_DECODER(MJPEGB, mjpegb);
|
||||
REGISTER_DECODER(MMVIDEO, mmvideo);
|
||||
REGISTER_DECODER(MOTIONPIXELS, motionpixels);
|
||||
#if FF_API_XVMC
|
||||
REGISTER_DECODER(MPEG_XVMC, mpeg_xvmc);
|
||||
#endif /* FF_API_XVMC */
|
||||
REGISTER_ENCDEC (MPEG1VIDEO, mpeg1video);
|
||||
REGISTER_ENCDEC (MPEG2VIDEO, mpeg2video);
|
||||
REGISTER_ENCDEC (MPEG4, mpeg4);
|
||||
REGISTER_DECODER(MPEG4_CRYSTALHD, mpeg4_crystalhd);
|
||||
REGISTER_DECODER(MPEG4_V4L2M2M, mpeg4_v4l2m2m);
|
||||
REGISTER_DECODER(MPEG4_MMAL, mpeg4_mmal);
|
||||
#if FF_API_VDPAU
|
||||
REGISTER_DECODER(MPEG4_VDPAU, mpeg4_vdpau);
|
||||
#endif
|
||||
REGISTER_DECODER(MPEGVIDEO, mpegvideo);
|
||||
#if FF_API_VDPAU
|
||||
REGISTER_DECODER(MPEG_VDPAU, mpeg_vdpau);
|
||||
REGISTER_DECODER(MPEG1_VDPAU, mpeg1_vdpau);
|
||||
#endif
|
||||
REGISTER_DECODER(MPEG1_V4L2M2M, mpeg1_v4l2m2m);
|
||||
REGISTER_DECODER(MPEG2_MMAL, mpeg2_mmal);
|
||||
REGISTER_DECODER(MPEG2_CRYSTALHD, mpeg2_crystalhd);
|
||||
@@ -365,9 +275,6 @@ static void register_all(void)
|
||||
REGISTER_DECODER(VBLE, vble);
|
||||
REGISTER_DECODER(VC1, vc1);
|
||||
REGISTER_DECODER(VC1_CRYSTALHD, vc1_crystalhd);
|
||||
#if FF_API_VDPAU
|
||||
REGISTER_DECODER(VC1_VDPAU, vc1_vdpau);
|
||||
#endif
|
||||
REGISTER_DECODER(VC1IMAGE, vc1image);
|
||||
REGISTER_DECODER(VC1_MMAL, vc1_mmal);
|
||||
REGISTER_DECODER(VC1_QSV, vc1_qsv);
|
||||
@@ -396,9 +303,6 @@ static void register_all(void)
|
||||
REGISTER_ENCDEC (WMV2, wmv2);
|
||||
REGISTER_DECODER(WMV3, wmv3);
|
||||
REGISTER_DECODER(WMV3_CRYSTALHD, wmv3_crystalhd);
|
||||
#if FF_API_VDPAU
|
||||
REGISTER_DECODER(WMV3_VDPAU, wmv3_vdpau);
|
||||
#endif
|
||||
REGISTER_DECODER(WMV3IMAGE, wmv3image);
|
||||
REGISTER_DECODER(WNV1, wnv1);
|
||||
REGISTER_DECODER(XAN_WC3, xan_wc3);
|
||||
@@ -428,6 +332,7 @@ static void register_all(void)
|
||||
REGISTER_DECODER(AMRNB, amrnb);
|
||||
REGISTER_DECODER(AMRWB, amrwb);
|
||||
REGISTER_DECODER(APE, ape);
|
||||
REGISTER_ENCDEC (APTX, aptx);
|
||||
REGISTER_DECODER(ATRAC1, atrac1);
|
||||
REGISTER_DECODER(ATRAC3, atrac3);
|
||||
REGISTER_DECODER(ATRAC3AL, atrac3al);
|
||||
@@ -671,6 +576,7 @@ static void register_all(void)
|
||||
* above is available */
|
||||
REGISTER_ENCODER(H263_V4L2M2M, h263_v4l2m2m);
|
||||
REGISTER_ENCDEC (LIBOPENH264, libopenh264);
|
||||
REGISTER_ENCODER(H264_AMF, h264_amf);
|
||||
REGISTER_DECODER(H264_CUVID, h264_cuvid);
|
||||
REGISTER_ENCODER(H264_NVENC, h264_nvenc);
|
||||
REGISTER_ENCODER(H264_OMX, h264_omx);
|
||||
@@ -683,14 +589,17 @@ static void register_all(void)
|
||||
REGISTER_ENCODER(NVENC_H264, nvenc_h264);
|
||||
REGISTER_ENCODER(NVENC_HEVC, nvenc_hevc);
|
||||
#endif
|
||||
REGISTER_ENCODER(HEVC_AMF, hevc_amf);
|
||||
REGISTER_DECODER(HEVC_CUVID, hevc_cuvid);
|
||||
REGISTER_DECODER(HEVC_MEDIACODEC, hevc_mediacodec);
|
||||
REGISTER_ENCODER(HEVC_NVENC, hevc_nvenc);
|
||||
REGISTER_ENCODER(HEVC_QSV, hevc_qsv);
|
||||
REGISTER_ENCODER(HEVC_V4L2M2M, hevc_v4l2m2m);
|
||||
REGISTER_ENCODER(HEVC_VAAPI, hevc_vaapi);
|
||||
REGISTER_ENCODER(HEVC_VIDEOTOOLBOX, hevc_videotoolbox);
|
||||
REGISTER_ENCODER(LIBKVAZAAR, libkvazaar);
|
||||
REGISTER_DECODER(MJPEG_CUVID, mjpeg_cuvid);
|
||||
REGISTER_ENCODER(MJPEG_QSV, mjpeg_qsv);
|
||||
REGISTER_ENCODER(MJPEG_VAAPI, mjpeg_vaapi);
|
||||
REGISTER_DECODER(MPEG1_CUVID, mpeg1_cuvid);
|
||||
REGISTER_DECODER(MPEG2_CUVID, mpeg2_cuvid);
|
||||
|
||||
@@ -146,39 +146,6 @@ struct unaligned_long { uint64_t l; } __attribute__((packed));
|
||||
#define unpkbw(a) ({ uint64_t __r; __asm__ (".arch ev6; unpkbw %r1,%0" : "=r" (__r) : "rJ" (a)); __r; })
|
||||
#endif
|
||||
|
||||
#elif defined(__DECC) /* Digital/Compaq/hp "ccc" compiler */
|
||||
|
||||
#include <c_asm.h>
|
||||
#define ldq(p) (*(const uint64_t *) (p))
|
||||
#define ldl(p) (*(const int32_t *) (p))
|
||||
#define stq(l, p) do { *(uint64_t *) (p) = (l); } while (0)
|
||||
#define stl(l, p) do { *(int32_t *) (p) = (l); } while (0)
|
||||
#define ldq_u(a) asm ("ldq_u %v0,0(%a0)", a)
|
||||
#define uldq(a) (*(const __unaligned uint64_t *) (a))
|
||||
#define cmpbge(a, b) asm ("cmpbge %a0,%a1,%v0", a, b)
|
||||
#define extql(a, b) asm ("extql %a0,%a1,%v0", a, b)
|
||||
#define extwl(a, b) asm ("extwl %a0,%a1,%v0", a, b)
|
||||
#define extqh(a, b) asm ("extqh %a0,%a1,%v0", a, b)
|
||||
#define zap(a, b) asm ("zap %a0,%a1,%v0", a, b)
|
||||
#define zapnot(a, b) asm ("zapnot %a0,%a1,%v0", a, b)
|
||||
#define amask(a) asm ("amask %a0,%v0", a)
|
||||
#define implver() asm ("implver %v0")
|
||||
#define rpcc() asm ("rpcc %v0")
|
||||
#define minub8(a, b) asm ("minub8 %a0,%a1,%v0", a, b)
|
||||
#define minsb8(a, b) asm ("minsb8 %a0,%a1,%v0", a, b)
|
||||
#define minuw4(a, b) asm ("minuw4 %a0,%a1,%v0", a, b)
|
||||
#define minsw4(a, b) asm ("minsw4 %a0,%a1,%v0", a, b)
|
||||
#define maxub8(a, b) asm ("maxub8 %a0,%a1,%v0", a, b)
|
||||
#define maxsb8(a, b) asm ("maxsb8 %a0,%a1,%v0", a, b)
|
||||
#define maxuw4(a, b) asm ("maxuw4 %a0,%a1,%v0", a, b)
|
||||
#define maxsw4(a, b) asm ("maxsw4 %a0,%a1,%v0", a, b)
|
||||
#define perr(a, b) asm ("perr %a0,%a1,%v0", a, b)
|
||||
#define pklb(a) asm ("pklb %a0,%v0", a)
|
||||
#define pkwb(a) asm ("pkwb %a0,%v0", a)
|
||||
#define unpkbl(a) asm ("unpkbl %a0,%v0", a)
|
||||
#define unpkbw(a) asm ("unpkbw %a0,%v0", a)
|
||||
#define wh64(a) asm ("wh64 %a0", a)
|
||||
|
||||
#else
|
||||
#error "Unknown compiler!"
|
||||
#endif
|
||||
|
||||
@@ -118,8 +118,7 @@ av_cold void ff_idctdsp_init_alpha(IDCTDSPContext *c, AVCodecContext *avctx,
|
||||
add_pixels_clamped_axp_p = c->add_pixels_clamped;
|
||||
|
||||
if (!high_bit_depth && !avctx->lowres &&
|
||||
(avctx->idct_algo == FF_IDCT_AUTO ||
|
||||
avctx->idct_algo == FF_IDCT_SIMPLEALPHA)) {
|
||||
(avctx->idct_algo == FF_IDCT_AUTO)) {
|
||||
c->idct_put = ff_simple_idct_put_axp;
|
||||
c->idct_add = ff_simple_idct_add_axp;
|
||||
c->idct = ff_simple_idct_axp;
|
||||
|
||||
+1
-6
@@ -704,11 +704,6 @@ static int read_var_block_data(ALSDecContext *ctx, ALSBlockData *bd)
|
||||
} else {
|
||||
*bd->opt_order = sconf->max_order;
|
||||
}
|
||||
if (*bd->opt_order > bd->block_length) {
|
||||
*bd->opt_order = bd->block_length;
|
||||
av_log(avctx, AV_LOG_ERROR, "Predictor order too large.\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
opt_order = *bd->opt_order;
|
||||
|
||||
if (opt_order) {
|
||||
@@ -925,7 +920,7 @@ static int decode_var_block_data(ALSDecContext *ctx, ALSBlockData *bd)
|
||||
|
||||
// reconstruct all samples from residuals
|
||||
if (bd->ra_block) {
|
||||
for (smp = 0; smp < opt_order; smp++) {
|
||||
for (smp = 0; smp < FFMIN(opt_order, block_length); smp++) {
|
||||
y = 1 << 19;
|
||||
|
||||
for (sb = 0; sb < smp; sb++)
|
||||
|
||||
@@ -0,0 +1,606 @@
|
||||
/*
|
||||
* 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/avassert.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
#include "libavutil/hwcontext.h"
|
||||
#if CONFIG_D3D11VA
|
||||
#include "libavutil/hwcontext_d3d11va.h"
|
||||
#endif
|
||||
#include "libavutil/mem.h"
|
||||
#include "libavutil/pixdesc.h"
|
||||
#include "libavutil/time.h"
|
||||
|
||||
#include "amfenc.h"
|
||||
#include "internal.h"
|
||||
|
||||
#if CONFIG_D3D11VA
|
||||
#include <d3d11.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "compat/w32dlfcn.h"
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#define FFMPEG_AMF_WRITER_ID L"ffmpeg_amf"
|
||||
|
||||
#define PTS_PROP L"PtsProp"
|
||||
|
||||
const enum AVPixelFormat ff_amf_pix_fmts[] = {
|
||||
AV_PIX_FMT_NV12,
|
||||
AV_PIX_FMT_YUV420P,
|
||||
#if CONFIG_D3D11VA
|
||||
AV_PIX_FMT_D3D11,
|
||||
#endif
|
||||
AV_PIX_FMT_NONE
|
||||
};
|
||||
|
||||
typedef struct FormatMap {
|
||||
enum AVPixelFormat av_format;
|
||||
enum AMF_SURFACE_FORMAT amf_format;
|
||||
} FormatMap;
|
||||
|
||||
static const FormatMap format_map[] =
|
||||
{
|
||||
{ AV_PIX_FMT_NONE, AMF_SURFACE_UNKNOWN },
|
||||
{ AV_PIX_FMT_NV12, AMF_SURFACE_NV12 },
|
||||
{ AV_PIX_FMT_BGR0, AMF_SURFACE_BGRA },
|
||||
{ AV_PIX_FMT_RGB0, AMF_SURFACE_RGBA },
|
||||
{ AV_PIX_FMT_GRAY8, AMF_SURFACE_GRAY8 },
|
||||
{ AV_PIX_FMT_YUV420P, AMF_SURFACE_YUV420P },
|
||||
{ AV_PIX_FMT_YUYV422, AMF_SURFACE_YUY2 },
|
||||
{ AV_PIX_FMT_D3D11, AMF_SURFACE_NV12 },
|
||||
};
|
||||
|
||||
|
||||
static int is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt)
|
||||
{
|
||||
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
|
||||
return desc->flags & AV_PIX_FMT_FLAG_HWACCEL;
|
||||
}
|
||||
|
||||
|
||||
static enum AMF_SURFACE_FORMAT amf_av_to_amf_format(enum AVPixelFormat fmt)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < amf_countof(format_map); i++) {
|
||||
if (format_map[i].av_format == fmt) {
|
||||
return format_map[i].amf_format;
|
||||
}
|
||||
}
|
||||
return AMF_SURFACE_UNKNOWN;
|
||||
}
|
||||
|
||||
static void AMF_CDECL_CALL AMFTraceWriter_Write(AMFTraceWriter *pThis,
|
||||
const wchar_t *scope, const wchar_t *message)
|
||||
{
|
||||
AmfTraceWriter *tracer = (AmfTraceWriter*)pThis;
|
||||
av_log(tracer->avctx, AV_LOG_DEBUG, "%ls: %ls", scope, message); // \n is provided from AMF
|
||||
}
|
||||
|
||||
static void AMF_CDECL_CALL AMFTraceWriter_Flush(AMFTraceWriter *pThis)
|
||||
{
|
||||
}
|
||||
|
||||
static AMFTraceWriterVtbl tracer_vtbl =
|
||||
{
|
||||
.Write = AMFTraceWriter_Write,
|
||||
.Flush = AMFTraceWriter_Flush,
|
||||
};
|
||||
|
||||
static int amf_load_library(AVCodecContext *avctx)
|
||||
{
|
||||
AmfContext *ctx = avctx->priv_data;
|
||||
AMFInit_Fn init_fun = NULL;
|
||||
AMFQueryVersion_Fn version_fun = NULL;
|
||||
AMF_RESULT res = AMF_OK;
|
||||
|
||||
ctx->eof = 0;
|
||||
ctx->delayed_drain = 0;
|
||||
ctx->hw_frames_ctx = NULL;
|
||||
ctx->hw_device_ctx = NULL;
|
||||
ctx->delayed_surface = NULL;
|
||||
ctx->delayed_frame = av_frame_alloc();
|
||||
if (!ctx->delayed_frame) {
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
// hardcoded to current HW queue size - will realloc in timestamp_queue_enqueue() if too small
|
||||
ctx->timestamp_list = av_fifo_alloc((avctx->max_b_frames + 16) * sizeof(int64_t));
|
||||
if (!ctx->timestamp_list) {
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
ctx->dts_delay = 0;
|
||||
|
||||
|
||||
ctx->library = dlopen(AMF_DLL_NAMEA, RTLD_NOW | RTLD_LOCAL);
|
||||
AMF_RETURN_IF_FALSE(ctx, ctx->library != NULL,
|
||||
AVERROR_UNKNOWN, "DLL %s failed to open\n", AMF_DLL_NAMEA);
|
||||
|
||||
init_fun = (AMFInit_Fn)dlsym(ctx->library, AMF_INIT_FUNCTION_NAME);
|
||||
AMF_RETURN_IF_FALSE(ctx, init_fun != NULL, AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_INIT_FUNCTION_NAME);
|
||||
|
||||
version_fun = (AMFQueryVersion_Fn)dlsym(ctx->library, AMF_QUERY_VERSION_FUNCTION_NAME);
|
||||
AMF_RETURN_IF_FALSE(ctx, version_fun != NULL, AVERROR_UNKNOWN, "DLL %s failed to find function %s\n", AMF_DLL_NAMEA, AMF_QUERY_VERSION_FUNCTION_NAME);
|
||||
|
||||
res = version_fun(&ctx->version);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_QUERY_VERSION_FUNCTION_NAME, res);
|
||||
res = init_fun(AMF_FULL_VERSION, &ctx->factory);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "%s failed with error %d\n", AMF_INIT_FUNCTION_NAME, res);
|
||||
res = ctx->factory->pVtbl->GetTrace(ctx->factory, &ctx->trace);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "GetTrace() failed with error %d\n", res);
|
||||
res = ctx->factory->pVtbl->GetDebug(ctx->factory, &ctx->debug);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "GetDebug() failed with error %d\n", res);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amf_init_context(AVCodecContext *avctx)
|
||||
{
|
||||
AmfContext *ctx = avctx->priv_data;
|
||||
AMF_RESULT res = AMF_OK;
|
||||
|
||||
// confugure AMF logger
|
||||
// the return of these functions indicates old state and do not affect behaviour
|
||||
ctx->trace->pVtbl->EnableWriter(ctx->trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, ctx->log_to_dbg != 0 );
|
||||
if (ctx->log_to_dbg)
|
||||
ctx->trace->pVtbl->SetWriterLevel(ctx->trace, AMF_TRACE_WRITER_DEBUG_OUTPUT, AMF_TRACE_TRACE);
|
||||
ctx->trace->pVtbl->EnableWriter(ctx->trace, AMF_TRACE_WRITER_CONSOLE, 0);
|
||||
ctx->trace->pVtbl->SetGlobalLevel(ctx->trace, AMF_TRACE_TRACE);
|
||||
|
||||
// connect AMF logger to av_log
|
||||
ctx->tracer.vtbl = &tracer_vtbl;
|
||||
ctx->tracer.avctx = avctx;
|
||||
ctx->trace->pVtbl->RegisterWriter(ctx->trace, FFMPEG_AMF_WRITER_ID,(AMFTraceWriter*)&ctx->tracer, 1);
|
||||
ctx->trace->pVtbl->SetWriterLevel(ctx->trace, FFMPEG_AMF_WRITER_ID, AMF_TRACE_TRACE);
|
||||
|
||||
res = ctx->factory->pVtbl->CreateContext(ctx->factory, &ctx->context);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "CreateContext() failed with error %d\n", res);
|
||||
// try to reuse existing DX device
|
||||
#if CONFIG_D3D11VA
|
||||
if (avctx->hw_frames_ctx) {
|
||||
AVHWFramesContext *device_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
|
||||
if (device_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
|
||||
if (amf_av_to_amf_format(device_ctx->sw_format) != AMF_SURFACE_UNKNOWN) {
|
||||
if (device_ctx->device_ctx->hwctx) {
|
||||
AVD3D11VADeviceContext *device_d3d11 = (AVD3D11VADeviceContext *)device_ctx->device_ctx->hwctx;
|
||||
res = ctx->context->pVtbl->InitDX11(ctx->context, device_d3d11->device, AMF_DX11_1);
|
||||
if (res == AMF_OK) {
|
||||
ctx->hw_frames_ctx = av_buffer_ref(avctx->hw_frames_ctx);
|
||||
if (!ctx->hw_frames_ctx) {
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
} else {
|
||||
if(res == AMF_NOT_SUPPORTED)
|
||||
av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has D3D11 device which doesn't have D3D11VA interface, switching to default\n");
|
||||
else
|
||||
av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has non-AMD device, switching to default\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
av_log(avctx, AV_LOG_INFO, "avctx->hw_frames_ctx has format not uspported by AMF, switching to default\n");
|
||||
}
|
||||
}
|
||||
} else if (avctx->hw_device_ctx) {
|
||||
AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)(avctx->hw_device_ctx->data);
|
||||
if (device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
|
||||
if (device_ctx->hwctx) {
|
||||
AVD3D11VADeviceContext *device_d3d11 = (AVD3D11VADeviceContext *)device_ctx->hwctx;
|
||||
res = ctx->context->pVtbl->InitDX11(ctx->context, device_d3d11->device, AMF_DX11_1);
|
||||
if (res == AMF_OK) {
|
||||
ctx->hw_device_ctx = av_buffer_ref(avctx->hw_device_ctx);
|
||||
if (!ctx->hw_device_ctx) {
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
} else {
|
||||
if (res == AMF_NOT_SUPPORTED)
|
||||
av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has D3D11 device which doesn't have D3D11VA interface, switching to default\n");
|
||||
else
|
||||
av_log(avctx, AV_LOG_INFO, "avctx->hw_device_ctx has non-AMD device, switching to default\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!ctx->hw_frames_ctx && !ctx->hw_device_ctx) {
|
||||
res = ctx->context->pVtbl->InitDX11(ctx->context, NULL, AMF_DX11_1);
|
||||
if (res != AMF_OK) {
|
||||
res = ctx->context->pVtbl->InitDX9(ctx->context, NULL);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "InitDX9() failed with error %d\n", res);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amf_init_encoder(AVCodecContext *avctx)
|
||||
{
|
||||
AmfContext *ctx = avctx->priv_data;
|
||||
const wchar_t *codec_id = NULL;
|
||||
AMF_RESULT res = AMF_OK;
|
||||
|
||||
switch (avctx->codec->id) {
|
||||
case AV_CODEC_ID_H264:
|
||||
codec_id = AMFVideoEncoderVCE_AVC;
|
||||
break;
|
||||
case AV_CODEC_ID_HEVC:
|
||||
codec_id = AMFVideoEncoder_HEVC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
AMF_RETURN_IF_FALSE(ctx, codec_id != NULL, AVERROR(EINVAL), "Codec %d is not supported\n", avctx->codec->id);
|
||||
|
||||
ctx->format = amf_av_to_amf_format(avctx->pix_fmt);
|
||||
AMF_RETURN_IF_FALSE(ctx, ctx->format != AMF_SURFACE_UNKNOWN, AVERROR(EINVAL), "Format %d is not supported\n", avctx->pix_fmt);
|
||||
|
||||
res = ctx->factory->pVtbl->CreateComponent(ctx->factory, ctx->context, codec_id, &ctx->encoder);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_ENCODER_NOT_FOUND, "CreateComponent(%ls) failed with error %d\n", codec_id, res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int av_cold ff_amf_encode_close(AVCodecContext *avctx)
|
||||
{
|
||||
AmfContext *ctx = avctx->priv_data;
|
||||
if (ctx->delayed_surface)
|
||||
{
|
||||
ctx->delayed_surface->pVtbl->Release(ctx->delayed_surface);
|
||||
ctx->delayed_surface = NULL;
|
||||
}
|
||||
|
||||
if (ctx->encoder) {
|
||||
ctx->encoder->pVtbl->Terminate(ctx->encoder);
|
||||
ctx->encoder->pVtbl->Release(ctx->encoder);
|
||||
ctx->encoder = NULL;
|
||||
}
|
||||
|
||||
if (ctx->context) {
|
||||
ctx->context->pVtbl->Terminate(ctx->context);
|
||||
ctx->context->pVtbl->Release(ctx->context);
|
||||
ctx->context = NULL;
|
||||
}
|
||||
av_buffer_unref(&ctx->hw_device_ctx);
|
||||
av_buffer_unref(&ctx->hw_frames_ctx);
|
||||
|
||||
if (ctx->trace) {
|
||||
ctx->trace->pVtbl->UnregisterWriter(ctx->trace, FFMPEG_AMF_WRITER_ID);
|
||||
}
|
||||
if (ctx->library) {
|
||||
dlclose(ctx->library);
|
||||
ctx->library = NULL;
|
||||
}
|
||||
ctx->trace = NULL;
|
||||
ctx->debug = NULL;
|
||||
ctx->factory = NULL;
|
||||
ctx->version = 0;
|
||||
ctx->delayed_drain = 0;
|
||||
av_frame_free(&ctx->delayed_frame);
|
||||
av_fifo_freep(&ctx->timestamp_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amf_copy_surface(AVCodecContext *avctx, const AVFrame *frame,
|
||||
AMFSurface* surface)
|
||||
{
|
||||
AVFrame *sw_frame = NULL;
|
||||
AMFPlane *plane = NULL;
|
||||
uint8_t *dst_data[4];
|
||||
int dst_linesize[4];
|
||||
int ret = 0;
|
||||
int planes;
|
||||
int i;
|
||||
|
||||
if (frame->hw_frames_ctx && is_hwaccel_pix_fmt(frame->format)) {
|
||||
if (!(sw_frame = av_frame_alloc())) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Can not alloc frame\n");
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
if ((ret = av_hwframe_transfer_data(sw_frame, frame, 0)) < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Error transferring the data to system memory\n");
|
||||
goto fail;
|
||||
}
|
||||
frame = sw_frame;
|
||||
}
|
||||
planes = (int)surface->pVtbl->GetPlanesCount(surface);
|
||||
if (planes > amf_countof(dst_data)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Invalid number of planes %d in surface\n", planes);
|
||||
ret = AVERROR(EINVAL);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (i = 0; i < planes; i++) {
|
||||
plane = surface->pVtbl->GetPlaneAt(surface, i);
|
||||
dst_data[i] = plane->pVtbl->GetNative(plane);
|
||||
dst_linesize[i] = plane->pVtbl->GetHPitch(plane);
|
||||
}
|
||||
av_image_copy(dst_data, dst_linesize,
|
||||
(const uint8_t**)frame->data, frame->linesize, frame->format,
|
||||
avctx->width, avctx->height);
|
||||
|
||||
fail:
|
||||
if (sw_frame) {
|
||||
av_frame_free(&sw_frame);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int timestamp_queue_enqueue(AVCodecContext *avctx, int64_t timestamp)
|
||||
{
|
||||
AmfContext *ctx = avctx->priv_data;
|
||||
if (av_fifo_space(ctx->timestamp_list) < sizeof(timestamp)) {
|
||||
if (av_fifo_grow(ctx->timestamp_list, sizeof(timestamp)) < 0) {
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
}
|
||||
av_fifo_generic_write(ctx->timestamp_list, ×tamp, sizeof(timestamp), NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amf_copy_buffer(AVCodecContext *avctx, AVPacket *pkt, AMFBuffer *buffer)
|
||||
{
|
||||
AmfContext *ctx = avctx->priv_data;
|
||||
int ret;
|
||||
AMFVariantStruct var = {0};
|
||||
int64_t timestamp = AV_NOPTS_VALUE;
|
||||
int64_t size = buffer->pVtbl->GetSize(buffer);
|
||||
|
||||
if ((ret = ff_alloc_packet2(avctx, pkt, size, 0)) < 0) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(pkt->data, buffer->pVtbl->GetNative(buffer), size);
|
||||
|
||||
switch (avctx->codec->id) {
|
||||
case AV_CODEC_ID_H264:
|
||||
buffer->pVtbl->GetProperty(buffer, AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE, &var);
|
||||
if(var.int64Value == AMF_VIDEO_ENCODER_OUTPUT_DATA_TYPE_IDR) {
|
||||
pkt->flags = AV_PKT_FLAG_KEY;
|
||||
}
|
||||
break;
|
||||
case AV_CODEC_ID_HEVC:
|
||||
buffer->pVtbl->GetProperty(buffer, AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE, &var);
|
||||
if (var.int64Value == AMF_VIDEO_ENCODER_HEVC_OUTPUT_DATA_TYPE_IDR) {
|
||||
pkt->flags = AV_PKT_FLAG_KEY;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
buffer->pVtbl->GetProperty(buffer, PTS_PROP, &var);
|
||||
|
||||
pkt->pts = var.int64Value; // original pts
|
||||
|
||||
|
||||
AMF_RETURN_IF_FALSE(ctx, av_fifo_size(ctx->timestamp_list) > 0, AVERROR_UNKNOWN, "timestamp_list is empty\n");
|
||||
|
||||
av_fifo_generic_read(ctx->timestamp_list, ×tamp, sizeof(timestamp), NULL);
|
||||
|
||||
// calc dts shift if max_b_frames > 0
|
||||
if (avctx->max_b_frames > 0 && ctx->dts_delay == 0) {
|
||||
int64_t timestamp_last = AV_NOPTS_VALUE;
|
||||
AMF_RETURN_IF_FALSE(ctx, av_fifo_size(ctx->timestamp_list) > 0, AVERROR_UNKNOWN,
|
||||
"timestamp_list is empty while max_b_frames = %d\n", avctx->max_b_frames);
|
||||
av_fifo_generic_peek_at(
|
||||
ctx->timestamp_list,
|
||||
×tamp_last,
|
||||
(av_fifo_size(ctx->timestamp_list) / sizeof(timestamp) - 1) * sizeof(timestamp_last),
|
||||
sizeof(timestamp_last),
|
||||
NULL);
|
||||
if (timestamp < 0 || timestamp_last < AV_NOPTS_VALUE) {
|
||||
return AVERROR(ERANGE);
|
||||
}
|
||||
ctx->dts_delay = timestamp_last - timestamp;
|
||||
}
|
||||
pkt->dts = timestamp - ctx->dts_delay;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// amfenc API implmentation
|
||||
int ff_amf_encode_init(AVCodecContext *avctx)
|
||||
{
|
||||
AmfContext *ctx = avctx->priv_data;
|
||||
int ret;
|
||||
|
||||
ctx->factory = NULL;
|
||||
ctx->debug = NULL;
|
||||
ctx->trace = NULL;
|
||||
ctx->context = NULL;
|
||||
ctx->encoder = NULL;
|
||||
ctx->library = NULL;
|
||||
ctx->version = 0;
|
||||
ctx->eof = 0;
|
||||
ctx->format = 0;
|
||||
ctx->tracer.vtbl = NULL;
|
||||
ctx->tracer.avctx = NULL;
|
||||
|
||||
if ((ret = amf_load_library(avctx)) == 0) {
|
||||
if ((ret = amf_init_context(avctx)) == 0) {
|
||||
if ((ret = amf_init_encoder(avctx)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
ff_amf_encode_close(avctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame)
|
||||
{
|
||||
AMF_RESULT res = AMF_OK;
|
||||
AmfContext *ctx = avctx->priv_data;
|
||||
AMFSurface *surface = NULL;
|
||||
int ret;
|
||||
|
||||
if (!ctx->encoder)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
if (!frame) { // submit drain
|
||||
if (!ctx->eof) { // submit drain one time only
|
||||
if (ctx->delayed_surface != NULL) {
|
||||
ctx->delayed_drain = 1; // input queue is full: resubmit Drain() in ff_amf_receive_packet
|
||||
} else if(!ctx->delayed_drain) {
|
||||
res = ctx->encoder->pVtbl->Drain(ctx->encoder);
|
||||
if (res == AMF_INPUT_FULL) {
|
||||
ctx->delayed_drain = 1; // input queue is full: resubmit Drain() in ff_amf_receive_packet
|
||||
} else {
|
||||
if (res == AMF_OK) {
|
||||
ctx->eof = 1; // drain started
|
||||
}
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Drain() failed with error %d\n", res);
|
||||
}
|
||||
}
|
||||
} else{
|
||||
return AVERROR_EOF;
|
||||
}
|
||||
} else { // submit frame
|
||||
if (ctx->delayed_surface != NULL) {
|
||||
return AVERROR(EAGAIN); // should not happen when called from ffmpeg, other clients may resubmit
|
||||
}
|
||||
// prepare surface from frame
|
||||
if (frame->hw_frames_ctx && ( // HW frame detected
|
||||
// check if the same hw_frames_ctx as used in initialization
|
||||
(ctx->hw_frames_ctx && frame->hw_frames_ctx->data == ctx->hw_frames_ctx->data) ||
|
||||
// check if the same hw_device_ctx as used in initialization
|
||||
(ctx->hw_device_ctx && ((AVHWFramesContext*)frame->hw_frames_ctx->data)->device_ctx ==
|
||||
(AVHWDeviceContext*)ctx->hw_device_ctx->data)
|
||||
)) {
|
||||
#if CONFIG_D3D11VA
|
||||
static const GUID AMFTextureArrayIndexGUID = { 0x28115527, 0xe7c3, 0x4b66, { 0x99, 0xd3, 0x4f, 0x2a, 0xe6, 0xb4, 0x7f, 0xaf } };
|
||||
ID3D11Texture2D *texture = (ID3D11Texture2D*)frame->data[0]; // actual texture
|
||||
int index = (int)(size_t)frame->data[1]; // index is a slice in texture array is - set to tell AMF which slice to use
|
||||
texture->lpVtbl->SetPrivateData(texture, &AMFTextureArrayIndexGUID, sizeof(index), &index);
|
||||
|
||||
res = ctx->context->pVtbl->CreateSurfaceFromDX11Native(ctx->context, texture, &surface, NULL); // wrap to AMF surface
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "CreateSurfaceFromDX11Native() failed with error %d\n", res);
|
||||
|
||||
// input HW surfaces can be vertically aligned by 16; tell AMF the real size
|
||||
surface->pVtbl->SetCrop(surface, 0, 0, frame->width, frame->height);
|
||||
#endif
|
||||
} else {
|
||||
res = ctx->context->pVtbl->AllocSurface(ctx->context, AMF_MEMORY_HOST, ctx->format, avctx->width, avctx->height, &surface);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR(ENOMEM), "AllocSurface() failed with error %d\n", res);
|
||||
amf_copy_surface(avctx, frame, surface);
|
||||
}
|
||||
surface->pVtbl->SetPts(surface, frame->pts);
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, surface, PTS_PROP, frame->pts);
|
||||
|
||||
switch (avctx->codec->id) {
|
||||
case AV_CODEC_ID_H264:
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_INSERT_AUD, !!ctx->aud);
|
||||
break;
|
||||
case AV_CODEC_ID_HEVC:
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, surface, AMF_VIDEO_ENCODER_HEVC_INSERT_AUD, !!ctx->aud);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// submit surface
|
||||
res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)surface);
|
||||
if (res == AMF_INPUT_FULL) { // handle full queue
|
||||
//store surface for later submission
|
||||
ctx->delayed_surface = surface;
|
||||
if (surface->pVtbl->GetMemoryType(surface) == AMF_MEMORY_DX11) {
|
||||
av_frame_ref(ctx->delayed_frame, frame);
|
||||
}
|
||||
} else {
|
||||
surface->pVtbl->Release(surface);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "SubmitInput() failed with error %d\n", res);
|
||||
|
||||
if ((ret = timestamp_queue_enqueue(avctx, frame->pts)) < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt)
|
||||
{
|
||||
int ret;
|
||||
AMF_RESULT res;
|
||||
AMF_RESULT res_query;
|
||||
AmfContext *ctx = avctx->priv_data;
|
||||
AMFData *data = NULL;
|
||||
int block_and_wait;
|
||||
|
||||
if (!ctx->encoder)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
do {
|
||||
block_and_wait = 0;
|
||||
// poll data
|
||||
res_query = ctx->encoder->pVtbl->QueryOutput(ctx->encoder, &data);
|
||||
if (data) {
|
||||
// copy data to packet
|
||||
AMFBuffer* buffer;
|
||||
AMFGuid guid = IID_AMFBuffer();
|
||||
data->pVtbl->QueryInterface(data, &guid, (void**)&buffer); // query for buffer interface
|
||||
ret = amf_copy_buffer(avctx, avpkt, buffer);
|
||||
|
||||
buffer->pVtbl->Release(buffer);
|
||||
data->pVtbl->Release(data);
|
||||
|
||||
AMF_RETURN_IF_FALSE(ctx, ret >= 0, ret, "amf_copy_buffer() failed with error %d\n", ret);
|
||||
|
||||
if (ctx->delayed_surface != NULL) { // try to resubmit frame
|
||||
res = ctx->encoder->pVtbl->SubmitInput(ctx->encoder, (AMFData*)ctx->delayed_surface);
|
||||
if (res != AMF_INPUT_FULL) {
|
||||
int64_t pts = ctx->delayed_surface->pVtbl->GetPts(ctx->delayed_surface);
|
||||
ctx->delayed_surface->pVtbl->Release(ctx->delayed_surface);
|
||||
ctx->delayed_surface = NULL;
|
||||
av_frame_unref(ctx->delayed_frame);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Repeated SubmitInput() failed with error %d\n", res);
|
||||
|
||||
if ((ret = timestamp_queue_enqueue(avctx, pts)) < 0) {
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
av_log(avctx, AV_LOG_WARNING, "Data acquired but delayed frame submission got AMF_INPUT_FULL- should not happen\n");
|
||||
}
|
||||
} else if (ctx->delayed_drain) { // try to resubmit drain
|
||||
res = ctx->encoder->pVtbl->Drain(ctx->encoder);
|
||||
if (res != AMF_INPUT_FULL) {
|
||||
ctx->delayed_drain = 0;
|
||||
ctx->eof = 1; // drain started
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_UNKNOWN, "Repeated Drain() failed with error %d\n", res);
|
||||
} else {
|
||||
av_log(avctx, AV_LOG_WARNING, "Data acquired but delayed drain submission got AMF_INPUT_FULL- should not happen\n");
|
||||
}
|
||||
}
|
||||
} else if (ctx->delayed_surface != NULL || ctx->delayed_drain || (ctx->eof && res_query != AMF_EOF)) {
|
||||
block_and_wait = 1;
|
||||
av_usleep(1000); // wait and poll again
|
||||
}
|
||||
} while (block_and_wait);
|
||||
|
||||
if (res_query == AMF_EOF) {
|
||||
ret = AVERROR_EOF;
|
||||
} else if (data == NULL) {
|
||||
ret = AVERROR(EAGAIN);
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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_AMFENC_H
|
||||
#define AVCODEC_AMFENC_H
|
||||
|
||||
#include <AMF/core/Factory.h>
|
||||
|
||||
#include <AMF/components/VideoEncoderVCE.h>
|
||||
#include <AMF/components/VideoEncoderHEVC.h>
|
||||
|
||||
#include "libavutil/fifo.h"
|
||||
|
||||
#include "avcodec.h"
|
||||
|
||||
|
||||
/**
|
||||
* AMF trace writer callback class
|
||||
* Used to capture all AMF logging
|
||||
*/
|
||||
|
||||
typedef struct AmfTraceWriter {
|
||||
AMFTraceWriterVtbl *vtbl;
|
||||
AVCodecContext *avctx;
|
||||
} AmfTraceWriter;
|
||||
|
||||
/**
|
||||
* AMF encoder context
|
||||
*/
|
||||
|
||||
typedef struct AmfContext {
|
||||
AVClass *avclass;
|
||||
// access to AMF runtime
|
||||
amf_handle library; ///< handle to DLL library
|
||||
AMFFactory *factory; ///< pointer to AMF factory
|
||||
AMFDebug *debug; ///< pointer to AMF debug interface
|
||||
AMFTrace *trace; ///< pointer to AMF trace interface
|
||||
|
||||
amf_uint64 version; ///< version of AMF runtime
|
||||
AmfTraceWriter tracer; ///< AMF writer registered with AMF
|
||||
AMFContext *context; ///< AMF context
|
||||
//encoder
|
||||
AMFComponent *encoder; ///< AMF encoder object
|
||||
amf_bool eof; ///< flag indicating EOF happened
|
||||
AMF_SURFACE_FORMAT format; ///< AMF surface format
|
||||
|
||||
AVBufferRef *hw_device_ctx; ///< pointer to HW accelerator (decoder)
|
||||
AVBufferRef *hw_frames_ctx; ///< pointer to HW accelerator (frame allocator)
|
||||
|
||||
// helpers to handle async calls
|
||||
int delayed_drain;
|
||||
AMFSurface *delayed_surface;
|
||||
AVFrame *delayed_frame;
|
||||
|
||||
// shift dts back by max_b_frames in timing
|
||||
AVFifoBuffer *timestamp_list;
|
||||
int64_t dts_delay;
|
||||
|
||||
// common encoder option options
|
||||
|
||||
int log_to_dbg;
|
||||
|
||||
// Static options, have to be set before Init() call
|
||||
int usage;
|
||||
int profile;
|
||||
int level;
|
||||
int preanalysis;
|
||||
int quality;
|
||||
int b_frame_delta_qp;
|
||||
int ref_b_frame_delta_qp;
|
||||
|
||||
// Dynamic options, can be set after Init() call
|
||||
|
||||
int rate_control_mode;
|
||||
int enforce_hrd;
|
||||
int filler_data;
|
||||
int enable_vbaq;
|
||||
int skip_frame;
|
||||
int qp_i;
|
||||
int qp_p;
|
||||
int qp_b;
|
||||
int max_au_size;
|
||||
int header_spacing;
|
||||
int b_frame_ref;
|
||||
int intra_refresh_mb;
|
||||
int coding_mode;
|
||||
int me_half_pel;
|
||||
int me_quarter_pel;
|
||||
int aud;
|
||||
|
||||
// HEVC - specific options
|
||||
|
||||
int gops_per_idr;
|
||||
int header_insertion_mode;
|
||||
int min_qp_i;
|
||||
int max_qp_i;
|
||||
int min_qp_p;
|
||||
int max_qp_p;
|
||||
int tier;
|
||||
} AmfContext;
|
||||
|
||||
/**
|
||||
* Common encoder initization function
|
||||
*/
|
||||
int ff_amf_encode_init(AVCodecContext *avctx);
|
||||
/**
|
||||
* Common encoder termination function
|
||||
*/
|
||||
int ff_amf_encode_close(AVCodecContext *avctx);
|
||||
|
||||
/**
|
||||
* Ecoding one frame - common function for all AMF encoders
|
||||
*/
|
||||
|
||||
int ff_amf_send_frame(AVCodecContext *avctx, const AVFrame *frame);
|
||||
int ff_amf_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
|
||||
|
||||
/**
|
||||
* Supported formats
|
||||
*/
|
||||
extern const enum AVPixelFormat ff_amf_pix_fmts[];
|
||||
|
||||
/**
|
||||
* Error handling helper
|
||||
*/
|
||||
#define AMF_RETURN_IF_FALSE(avctx, exp, ret_value, /*message,*/ ...) \
|
||||
if (!(exp)) { \
|
||||
av_log(avctx, AV_LOG_ERROR, __VA_ARGS__); \
|
||||
return ret_value; \
|
||||
}
|
||||
|
||||
#endif //AVCODEC_AMFENC_H
|
||||
@@ -0,0 +1,395 @@
|
||||
/*
|
||||
* 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/internal.h"
|
||||
#include "libavutil/opt.h"
|
||||
#include "amfenc.h"
|
||||
#include "internal.h"
|
||||
|
||||
#define OFFSET(x) offsetof(AmfContext, x)
|
||||
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
|
||||
|
||||
static const AVOption options[] = {
|
||||
// Static
|
||||
/// Usage
|
||||
{ "usage", "Encoder Usage", OFFSET(usage), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_USAGE_TRANSCONDING }, AMF_VIDEO_ENCODER_USAGE_TRANSCONDING, AMF_VIDEO_ENCODER_USAGE_WEBCAM, VE, "usage" },
|
||||
{ "transcoding", "Generic Transcoding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_TRANSCONDING }, 0, 0, VE, "usage" },
|
||||
{ "ultralowlatency","", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_ULTRA_LOW_LATENCY }, 0, 0, VE, "usage" },
|
||||
{ "lowlatency", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_LOW_LATENCY }, 0, 0, VE, "usage" },
|
||||
{ "webcam", "Webcam", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_USAGE_WEBCAM }, 0, 0, VE, "usage" },
|
||||
|
||||
/// Profile,
|
||||
{ "profile", "Profile", OFFSET(profile),AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_PROFILE_MAIN }, AMF_VIDEO_ENCODER_PROFILE_BASELINE, AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_HIGH, VE, "profile" },
|
||||
{ "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_MAIN }, 0, 0, VE, "profile" },
|
||||
{ "high", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_HIGH }, 0, 0, VE, "profile" },
|
||||
{ "constrained_baseline", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_BASELINE }, 0, 0, VE, "profile" },
|
||||
{ "constrained_high", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_HIGH }, 0, 0, VE, "profile" },
|
||||
|
||||
/// Profile Level
|
||||
{ "level", "Profile Level", OFFSET(level), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 62, VE, "level" },
|
||||
{ "auto", "", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, VE, "level" },
|
||||
{ "1.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 10 }, 0, 0, VE, "level" },
|
||||
{ "1.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 11 }, 0, 0, VE, "level" },
|
||||
{ "1.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 12 }, 0, 0, VE, "level" },
|
||||
{ "1.3", "", 0, AV_OPT_TYPE_CONST, { .i64 = 13 }, 0, 0, VE, "level" },
|
||||
{ "2.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 20 }, 0, 0, VE, "level" },
|
||||
{ "2.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 21 }, 0, 0, VE, "level" },
|
||||
{ "2.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 22 }, 0, 0, VE, "level" },
|
||||
{ "3.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 30 }, 0, 0, VE, "level" },
|
||||
{ "3.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 31 }, 0, 0, VE, "level" },
|
||||
{ "3.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 32 }, 0, 0, VE, "level" },
|
||||
{ "4.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 40 }, 0, 0, VE, "level" },
|
||||
{ "4.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 41 }, 0, 0, VE, "level" },
|
||||
{ "4.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 42 }, 0, 0, VE, "level" },
|
||||
{ "5.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 50 }, 0, 0, VE, "level" },
|
||||
{ "5.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 51 }, 0, 0, VE, "level" },
|
||||
{ "5.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 52 }, 0, 0, VE, "level" },
|
||||
{ "6.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = 60 }, 0, 0, VE, "level" },
|
||||
{ "6.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = 61 }, 0, 0, VE, "level" },
|
||||
{ "6.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = 62 }, 0, 0, VE, "level" },
|
||||
|
||||
|
||||
/// Quality Preset
|
||||
{ "quality", "Quality Preference", OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED }, AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED, AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY, VE, "quality" },
|
||||
{ "speed", "Prefer Speed", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_SPEED }, 0, 0, VE, "quality" },
|
||||
{ "balanced", "Balanced", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_BALANCED }, 0, 0, VE, "quality" },
|
||||
{ "quality", "Prefer Quality", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_QUALITY_PRESET_QUALITY }, 0, 0, VE, "quality" },
|
||||
|
||||
// Dynamic
|
||||
/// Rate Control Method
|
||||
{ "rc", "Rate Control Method", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR, VE, "rc" },
|
||||
{ "cqp", "Constant Quantization Parameter", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP }, 0, 0, VE, "rc" },
|
||||
{ "cbr", "Constant Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR }, 0, 0, VE, "rc" },
|
||||
{ "vbr_peak", "Peak Contrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR }, 0, 0, VE, "rc" },
|
||||
{ "vbr_latency", "Latency Constrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR }, 0, 0, VE, "rc" },
|
||||
|
||||
/// Enforce HRD, Filler Data, VBAQ, Frame Skipping
|
||||
{ "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
{ "filler_data", "Filler Data Enable", OFFSET(filler_data), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
{ "vbaq", "Enable VBAQ", OFFSET(enable_vbaq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
{ "frame_skipping", "Rate Control Based Frame Skip", OFFSET(skip_frame), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
|
||||
/// QP Values
|
||||
{ "qp_i", "Quantization Parameter for I-Frame", OFFSET(qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE },
|
||||
{ "qp_p", "Quantization Parameter for P-Frame", OFFSET(qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE },
|
||||
{ "qp_b", "Quantization Parameter for B-Frame", OFFSET(qp_b), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE },
|
||||
|
||||
/// Pre-Pass, Pre-Analysis, Two-Pass
|
||||
{ "preanalysis", "Pre-Analysis Mode", OFFSET(preanalysis), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE, NULL },
|
||||
|
||||
/// Maximum Access Unit Size
|
||||
{ "max_au_size", "Maximum Access Unit Size for rate control (in bits)", OFFSET(max_au_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
|
||||
|
||||
/// Header Insertion Spacing
|
||||
{ "header_spacing", "Header Insertion Spacing", OFFSET(header_spacing), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1000, VE },
|
||||
|
||||
/// B-Frames
|
||||
// BPicturesPattern=bf
|
||||
{ "bf_delta_qp", "B-Picture Delta QP", OFFSET(b_frame_delta_qp), AV_OPT_TYPE_INT, { .i64 = 4 }, -10, 10, VE },
|
||||
{ "bf_ref", "Enable Reference to B-Frames", OFFSET(b_frame_ref), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
|
||||
{ "bf_ref_delta_qp","Reference B-Picture Delta QP", OFFSET(ref_b_frame_delta_qp), AV_OPT_TYPE_INT, { .i64 = 4 }, -10, 10, VE },
|
||||
|
||||
/// Intra-Refresh
|
||||
{ "intra_refresh_mb","Intra Refresh MBs Number Per Slot in Macroblocks", OFFSET(intra_refresh_mb), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE },
|
||||
|
||||
/// coder
|
||||
{ "coder", "Coding Type", OFFSET(coding_mode), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_UNDEFINED }, AMF_VIDEO_ENCODER_UNDEFINED, AMF_VIDEO_ENCODER_CALV, VE, "coder" },
|
||||
{ "auto", "Automatic", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_UNDEFINED }, 0, 0, VE, "coder" },
|
||||
{ "cavlc", "Context Adaptive Variable-Length Coding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_CALV }, 0, 0, VE, "coder" },
|
||||
{ "cabac", "Context Adaptive Binary Arithmetic Coding", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_CABAC }, 0, 0, VE, "coder" },
|
||||
|
||||
{ "me_half_pel", "Enable ME Half Pixel", OFFSET(me_half_pel), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
|
||||
{ "me_quarter_pel", "Enable ME Quarter Pixel", OFFSET(me_quarter_pel),AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE },
|
||||
|
||||
{ "aud", "Inserts AU Delimiter NAL unit", OFFSET(aud) ,AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
|
||||
{ "log_to_dbg", "Enable AMF logging to debug output", OFFSET(log_to_dbg) , AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE },
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static av_cold int amf_encode_init_h264(AVCodecContext *avctx)
|
||||
{
|
||||
int ret = 0;
|
||||
AMF_RESULT res = AMF_OK;
|
||||
AmfContext *ctx = avctx->priv_data;
|
||||
AMFVariantStruct var = { 0 };
|
||||
amf_int64 profile = 0;
|
||||
amf_int64 profile_level = 0;
|
||||
AMFBuffer *buffer;
|
||||
AMFGuid guid;
|
||||
AMFRate framerate;
|
||||
AMFSize framesize = AMFConstructSize(avctx->width, avctx->height);
|
||||
int deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0;
|
||||
|
||||
if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
|
||||
framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den);
|
||||
} else {
|
||||
framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num * avctx->ticks_per_frame);
|
||||
}
|
||||
|
||||
if ((ret = ff_amf_encode_init(avctx)) != 0)
|
||||
return ret;
|
||||
|
||||
// Static parameters
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_USAGE, ctx->usage);
|
||||
|
||||
AMF_ASSIGN_PROPERTY_SIZE(res, ctx->encoder, AMF_VIDEO_ENCODER_FRAMESIZE, framesize);
|
||||
|
||||
AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder, AMF_VIDEO_ENCODER_FRAMERATE, framerate);
|
||||
|
||||
switch (avctx->profile) {
|
||||
case FF_PROFILE_H264_BASELINE:
|
||||
profile = AMF_VIDEO_ENCODER_PROFILE_BASELINE;
|
||||
break;
|
||||
case FF_PROFILE_H264_MAIN:
|
||||
profile = AMF_VIDEO_ENCODER_PROFILE_MAIN;
|
||||
break;
|
||||
case FF_PROFILE_H264_HIGH:
|
||||
profile = AMF_VIDEO_ENCODER_PROFILE_HIGH;
|
||||
break;
|
||||
case FF_PROFILE_H264_CONSTRAINED_BASELINE:
|
||||
profile = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_BASELINE;
|
||||
break;
|
||||
case (FF_PROFILE_H264_HIGH | FF_PROFILE_H264_CONSTRAINED):
|
||||
profile = AMF_VIDEO_ENCODER_PROFILE_CONSTRAINED_HIGH;
|
||||
break;
|
||||
}
|
||||
if (profile == 0) {
|
||||
profile = ctx->profile;
|
||||
}
|
||||
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PROFILE, profile);
|
||||
|
||||
profile_level = avctx->level;
|
||||
if (profile_level == FF_LEVEL_UNKNOWN) {
|
||||
profile_level = ctx->level;
|
||||
}
|
||||
if (profile_level != 0) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PROFILE_LEVEL, profile_level);
|
||||
}
|
||||
|
||||
// Maximum Reference Frames
|
||||
if (avctx->refs != -1) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_NUM_REFRAMES, avctx->refs);
|
||||
}
|
||||
if (avctx->sample_aspect_ratio.den && avctx->sample_aspect_ratio.num) {
|
||||
AMFRatio ratio = AMFConstructRatio(avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den);
|
||||
AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_ASPECT_RATIO, ratio);
|
||||
}
|
||||
|
||||
/// Color Range (Partial/TV/MPEG or Full/PC/JPEG)
|
||||
if (avctx->color_range == AVCOL_RANGE_JPEG) {
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FULL_RANGE_COLOR, 1);
|
||||
}
|
||||
|
||||
// autodetect rate control method
|
||||
if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_UNKNOWN) {
|
||||
if (ctx->qp_i != -1 || ctx->qp_p != -1 || ctx->qp_b != -1) {
|
||||
ctx->rate_control_mode = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP;
|
||||
av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CQP\n");
|
||||
} else if (avctx->rc_max_rate > 0 ) {
|
||||
ctx->rate_control_mode = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR;
|
||||
av_log(ctx, AV_LOG_DEBUG, "Rate control turned to Peak VBR\n");
|
||||
} else {
|
||||
ctx->rate_control_mode = AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR;
|
||||
av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CBR\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE, AMF_VIDEO_ENCODER_PREENCODE_DISABLED);
|
||||
if (ctx->preanalysis)
|
||||
av_log(ctx, AV_LOG_WARNING, "Pre-Analysis is not supported by cqp Rate Control Method, automatically disabled\n");
|
||||
} else {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_PREANALYSIS_ENABLE, ctx->preanalysis);
|
||||
}
|
||||
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QUALITY_PRESET, ctx->quality);
|
||||
|
||||
// Dynamic parmaters
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD, ctx->rate_control_mode);
|
||||
|
||||
/// VBV Buffer
|
||||
if (avctx->rc_buffer_size != 0) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_VBV_BUFFER_SIZE, avctx->rc_buffer_size);
|
||||
if (avctx->rc_initial_buffer_occupancy != 0) {
|
||||
int amf_buffer_fullness = avctx->rc_initial_buffer_occupancy * 64 / avctx->rc_buffer_size;
|
||||
if (amf_buffer_fullness > 64)
|
||||
amf_buffer_fullness = 64;
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_INITIAL_VBV_BUFFER_FULLNESS, amf_buffer_fullness);
|
||||
}
|
||||
}
|
||||
/// Maximum Access Unit Size
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_AU_SIZE, ctx->max_au_size);
|
||||
|
||||
if (ctx->max_au_size)
|
||||
ctx->enforce_hrd = 1;
|
||||
|
||||
// QP Minimum / Maximum
|
||||
if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, 0);
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_QP, 51);
|
||||
} else {
|
||||
if (avctx->qmin != -1) {
|
||||
int qval = avctx->qmin > 51 ? 51 : avctx->qmin;
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MIN_QP, qval);
|
||||
}
|
||||
if (avctx->qmax != -1) {
|
||||
int qval = avctx->qmax > 51 ? 51 : avctx->qmax;
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_MAX_QP, qval);
|
||||
}
|
||||
}
|
||||
// QP Values
|
||||
if (ctx->qp_i != -1)
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QP_I, ctx->qp_i);
|
||||
if (ctx->qp_p != -1)
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QP_P, ctx->qp_p);
|
||||
if (ctx->qp_b != -1)
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_QP_B, ctx->qp_b);
|
||||
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_TARGET_BITRATE, avctx->bit_rate);
|
||||
|
||||
if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CBR) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PEAK_BITRATE, avctx->bit_rate);
|
||||
}
|
||||
if (avctx->rc_max_rate) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_PEAK_BITRATE, avctx->rc_max_rate);
|
||||
} else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) {
|
||||
av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n");
|
||||
}
|
||||
|
||||
// Initialize Encoder
|
||||
res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res);
|
||||
|
||||
// Enforce HRD, Filler Data, VBAQ, Frame Skipping, Deblocking Filter
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENFORCE_HRD, !!ctx->enforce_hrd);
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_FILLER_DATA_ENABLE, !!ctx->filler_data);
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_RATE_CONTROL_SKIP_FRAME_ENABLE, !!ctx->skip_frame);
|
||||
if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_RATE_CONTROL_METHOD_CONSTANT_QP) {
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENABLE_VBAQ, 0);
|
||||
if (ctx->enable_vbaq)
|
||||
av_log(ctx, AV_LOG_WARNING, "VBAQ is not supported by cqp Rate Control Method, automatically disabled\n");
|
||||
} else {
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_ENABLE_VBAQ, !!ctx->enable_vbaq);
|
||||
}
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_DE_BLOCKING_FILTER, !!deblocking_filter);
|
||||
|
||||
// B-Frames
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, avctx->max_b_frames);
|
||||
if (res != AMF_OK) {
|
||||
res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_PATTERN, &var);
|
||||
av_log(ctx, AV_LOG_WARNING, "B-frames=%d is not supported by this GPU, switched to %d\n",
|
||||
avctx->max_b_frames, (int)var.int64Value);
|
||||
avctx->max_b_frames = (int)var.int64Value;
|
||||
}
|
||||
if (avctx->max_b_frames) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_B_PIC_DELTA_QP, ctx->b_frame_delta_qp);
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_B_REFERENCE_ENABLE, !!ctx->b_frame_ref);
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_REF_B_PIC_DELTA_QP, ctx->ref_b_frame_delta_qp);
|
||||
}
|
||||
|
||||
// Keyframe Interval
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_IDR_PERIOD, avctx->gop_size);
|
||||
|
||||
// Header Insertion Spacing
|
||||
if (ctx->header_spacing >= 0)
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEADER_INSERTION_SPACING, ctx->header_spacing);
|
||||
|
||||
// Intra-Refresh, Slicing
|
||||
if (ctx->intra_refresh_mb > 0)
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_INTRA_REFRESH_NUM_MBS_PER_SLOT, ctx->intra_refresh_mb);
|
||||
if (avctx->slices > 1)
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_SLICES_PER_FRAME, avctx->slices);
|
||||
|
||||
// Coding
|
||||
if (ctx->coding_mode != 0)
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_CABAC_ENABLE, ctx->coding_mode);
|
||||
|
||||
// Motion Estimation
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_MOTION_HALF_PIXEL, !!ctx->me_half_pel);
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_MOTION_QUARTERPIXEL, !!ctx->me_quarter_pel);
|
||||
|
||||
// fill extradata
|
||||
res = AMFVariantInit(&var);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "AMFVariantInit() failed with error %d\n", res);
|
||||
|
||||
res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_EXTRADATA, &var);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) failed with error %d\n", res);
|
||||
AMF_RETURN_IF_FALSE(ctx, var.pInterface != NULL, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) returned NULL\n");
|
||||
|
||||
guid = IID_AMFBuffer();
|
||||
|
||||
res = var.pInterface->pVtbl->QueryInterface(var.pInterface, &guid, (void**)&buffer); // query for buffer interface
|
||||
if (res != AMF_OK) {
|
||||
var.pInterface->pVtbl->Release(var.pInterface);
|
||||
}
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "QueryInterface(IID_AMFBuffer) failed with error %d\n", res);
|
||||
|
||||
avctx->extradata_size = (int)buffer->pVtbl->GetSize(buffer);
|
||||
avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
if (!avctx->extradata) {
|
||||
buffer->pVtbl->Release(buffer);
|
||||
var.pInterface->pVtbl->Release(var.pInterface);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
memcpy(avctx->extradata, buffer->pVtbl->GetNative(buffer), avctx->extradata_size);
|
||||
|
||||
buffer->pVtbl->Release(buffer);
|
||||
var.pInterface->pVtbl->Release(var.pInterface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const AVCodecDefault defaults[] = {
|
||||
{ "refs", "-1" },
|
||||
{ "aspect", "0" },
|
||||
{ "sar", "0" },
|
||||
{ "qmin", "-1" },
|
||||
{ "qmax", "-1" },
|
||||
{ "b", "2M" },
|
||||
{ "g", "250" },
|
||||
{ "slices", "1" },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
static const AVClass h264_amf_class = {
|
||||
.class_name = "h264_amf",
|
||||
.item_name = av_default_item_name,
|
||||
.option = options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
//TODO declare as HW encoder when available
|
||||
AVCodec ff_h264_amf_encoder = {
|
||||
.name = "h264_amf",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("AMD AMF H.264 Encoder"),
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_H264,
|
||||
.init = amf_encode_init_h264,
|
||||
.send_frame = ff_amf_send_frame,
|
||||
.receive_packet = ff_amf_receive_packet,
|
||||
.close = ff_amf_encode_close,
|
||||
.priv_data_size = sizeof(AmfContext),
|
||||
.priv_class = &h264_amf_class,
|
||||
.defaults = defaults,
|
||||
.capabilities = AV_CODEC_CAP_DELAY,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
||||
.pix_fmts = ff_amf_pix_fmts,
|
||||
};
|
||||
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* 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/internal.h"
|
||||
#include "libavutil/opt.h"
|
||||
#include "amfenc.h"
|
||||
#include "internal.h"
|
||||
|
||||
#define OFFSET(x) offsetof(AmfContext, x)
|
||||
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
|
||||
static const AVOption options[] = {
|
||||
{ "usage", "Set the encoding usage", OFFSET(usage), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING }, AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING, AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM, VE, "usage" },
|
||||
{ "transcoding", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_TRANSCONDING }, 0, 0, VE, "usage" },
|
||||
{ "ultralowlatency","", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_ULTRA_LOW_LATENCY }, 0, 0, VE, "usage" },
|
||||
{ "lowlatency", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_LOW_LATENCY }, 0, 0, VE, "usage" },
|
||||
{ "webcam", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_USAGE_WEBCAM }, 0, 0, VE, "usage" },
|
||||
|
||||
{ "profile", "Set the profile (default main)", OFFSET(profile), AV_OPT_TYPE_INT,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN }, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN, AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN, VE, "profile" },
|
||||
{ "main", "", 0, AV_OPT_TYPE_CONST,{ .i64 = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN }, 0, 0, VE, "profile" },
|
||||
|
||||
{ "profile_tier", "Set the profile tier (default main)", OFFSET(tier), AV_OPT_TYPE_INT,{ .i64 = AMF_VIDEO_ENCODER_HEVC_TIER_MAIN }, AMF_VIDEO_ENCODER_HEVC_TIER_MAIN, AMF_VIDEO_ENCODER_HEVC_TIER_HIGH, VE, "tier" },
|
||||
{ "main", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_TIER_MAIN }, 0, 0, VE, "tier" },
|
||||
{ "high", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_TIER_HIGH }, 0, 0, VE, "tier" },
|
||||
|
||||
{ "level", "Set the encoding level (default auto)", OFFSET(level), AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, AMF_LEVEL_6_2, VE, "level" },
|
||||
{ "auto", "", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, VE, "level" },
|
||||
{ "1.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_1 }, 0, 0, VE, "level" },
|
||||
{ "2.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_2 }, 0, 0, VE, "level" },
|
||||
{ "2.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_2_1 }, 0, 0, VE, "level" },
|
||||
{ "3.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_3 }, 0, 0, VE, "level" },
|
||||
{ "3.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_3_1 }, 0, 0, VE, "level" },
|
||||
{ "4.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_4 }, 0, 0, VE, "level" },
|
||||
{ "4.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_4_1 }, 0, 0, VE, "level" },
|
||||
{ "5.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_5 }, 0, 0, VE, "level" },
|
||||
{ "5.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_5_1 }, 0, 0, VE, "level" },
|
||||
{ "5.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_5_2 }, 0, 0, VE, "level" },
|
||||
{ "6.0", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_6 }, 0, 0, VE, "level" },
|
||||
{ "6.1", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_6_1 }, 0, 0, VE, "level" },
|
||||
{ "6.2", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_LEVEL_6_2 }, 0, 0, VE, "level" },
|
||||
|
||||
{ "quality", "Set the encoding quality", OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED }, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED, VE, "quality" },
|
||||
{ "balanced", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_BALANCED }, 0, 0, VE, "quality" },
|
||||
{ "speed", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_SPEED }, 0, 0, VE, "quality" },
|
||||
{ "quality", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET_QUALITY }, 0, 0, VE, "quality" },
|
||||
|
||||
{ "rc", "Set the rate control mode", OFFSET(rate_control_mode), AV_OPT_TYPE_INT, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN }, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR, VE, "rc" },
|
||||
{ "cqp", "Constant Quantization Parameter", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP }, 0, 0, VE, "rc" },
|
||||
{ "cbr", "Constant Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR }, 0, 0, VE, "rc" },
|
||||
{ "vbr_peak", "Peak Contrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR }, 0, 0, VE, "rc" },
|
||||
{ "vbr_latency", "Latency Constrained Variable Bitrate", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR }, 0, 0, VE, "rc" },
|
||||
|
||||
{ "header_insertion_mode", "Set header insertion mode", OFFSET(header_insertion_mode), AV_OPT_TYPE_INT,{ .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE }, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED, VE, "hdrmode" },
|
||||
{ "none", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_NONE }, 0, 0, VE, "hdrmode" },
|
||||
{ "gop", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_GOP_ALIGNED }, 0, 0, VE, "hdrmode" },
|
||||
{ "idr", "", 0, AV_OPT_TYPE_CONST, { .i64 = AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE_IDR_ALIGNED }, 0, 0, VE, "hdrmode" },
|
||||
|
||||
{ "gops_per_idr", "GOPs per IDR 0-no IDR will be inserted", OFFSET(gops_per_idr), AV_OPT_TYPE_INT, { .i64 = 60 }, 0, INT_MAX, VE },
|
||||
{ "preanalysis", "Enable preanalysis", OFFSET(preanalysis), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE},
|
||||
{ "vbaq", "Enable VBAQ", OFFSET(enable_vbaq), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE},
|
||||
{ "enforce_hrd", "Enforce HRD", OFFSET(enforce_hrd), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE},
|
||||
{ "filler_data", "Filler Data Enable", OFFSET(filler_data), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE},
|
||||
{ "max_au_size", "Maximum Access Unit Size for rate control (in bits)", OFFSET(max_au_size), AV_OPT_TYPE_INT,{ .i64 = 0 }, 0, INT_MAX, VE},
|
||||
{ "min_qp_i", "min quantization parameter for I-frame", OFFSET(min_qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE },
|
||||
{ "max_qp_i", "max quantization parameter for I-frame", OFFSET(max_qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE },
|
||||
{ "min_qp_p", "min quantization parameter for P-frame", OFFSET(min_qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE },
|
||||
{ "max_qp_p", "max quantization parameter for P-frame", OFFSET(max_qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE },
|
||||
{ "qp_p", "quantization parameter for P-frame", OFFSET(qp_p), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE },
|
||||
{ "qp_i", "quantization parameter for I-frame", OFFSET(qp_i), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 51, VE },
|
||||
{ "skip_frame", "Rate Control Based Frame Skip", OFFSET(skip_frame), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE },
|
||||
{ "me_half_pel", "Enable ME Half Pixel", OFFSET(me_half_pel), AV_OPT_TYPE_BOOL,{ .i64 = 1 }, 0, 1, VE },
|
||||
{ "me_quarter_pel", "Enable ME Quarter Pixel ", OFFSET(me_quarter_pel),AV_OPT_TYPE_BOOL,{ .i64 = 1 }, 0, 1, VE },
|
||||
|
||||
{ "aud", "Inserts AU Delimiter NAL unit", OFFSET(aud) ,AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE },
|
||||
|
||||
{ "log_to_dbg", "Enable AMF logging to debug output", OFFSET(log_to_dbg), AV_OPT_TYPE_BOOL,{ .i64 = 0 }, 0, 1, VE },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static av_cold int amf_encode_init_hevc(AVCodecContext *avctx)
|
||||
{
|
||||
int ret = 0;
|
||||
AMF_RESULT res = AMF_OK;
|
||||
AmfContext *ctx = avctx->priv_data;
|
||||
AMFVariantStruct var = {0};
|
||||
amf_int64 profile = 0;
|
||||
amf_int64 profile_level = 0;
|
||||
AMFBuffer *buffer;
|
||||
AMFGuid guid;
|
||||
AMFRate framerate;
|
||||
AMFSize framesize = AMFConstructSize(avctx->width, avctx->height);
|
||||
int deblocking_filter = (avctx->flags & AV_CODEC_FLAG_LOOP_FILTER) ? 1 : 0;
|
||||
|
||||
if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
|
||||
framerate = AMFConstructRate(avctx->framerate.num, avctx->framerate.den);
|
||||
} else {
|
||||
framerate = AMFConstructRate(avctx->time_base.den, avctx->time_base.num * avctx->ticks_per_frame);
|
||||
}
|
||||
|
||||
if ((ret = ff_amf_encode_init(avctx)) < 0)
|
||||
return ret;
|
||||
|
||||
// init static parameters
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_USAGE, ctx->usage);
|
||||
|
||||
AMF_ASSIGN_PROPERTY_SIZE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FRAMESIZE, framesize);
|
||||
|
||||
AMF_ASSIGN_PROPERTY_RATE(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FRAMERATE, framerate);
|
||||
|
||||
switch (avctx->profile) {
|
||||
case FF_PROFILE_HEVC_MAIN:
|
||||
profile = AMF_VIDEO_ENCODER_HEVC_PROFILE_MAIN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (profile == 0) {
|
||||
profile = ctx->profile;
|
||||
}
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PROFILE, profile);
|
||||
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_TIER, ctx->tier);
|
||||
|
||||
profile_level = avctx->level;
|
||||
if (profile_level == 0) {
|
||||
profile_level = ctx->level;
|
||||
}
|
||||
if (profile_level != 0) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PROFILE_LEVEL, profile_level);
|
||||
}
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QUALITY_PRESET, ctx->quality);
|
||||
// Maximum Reference Frames
|
||||
if (avctx->refs != 0) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_NUM_REFRAMES, avctx->refs);
|
||||
}
|
||||
// Aspect Ratio
|
||||
if (avctx->sample_aspect_ratio.den && avctx->sample_aspect_ratio.num) {
|
||||
AMFRatio ratio = AMFConstructRatio(avctx->sample_aspect_ratio.num, avctx->sample_aspect_ratio.den);
|
||||
AMF_ASSIGN_PROPERTY_RATIO(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ASPECT_RATIO, ratio);
|
||||
}
|
||||
|
||||
// Picture control properties
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_NUM_GOPS_PER_IDR, ctx->gops_per_idr);
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_GOP_SIZE, avctx->gop_size);
|
||||
if (avctx->slices > 1) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_SLICES_PER_FRAME, avctx->slices);
|
||||
}
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_DE_BLOCKING_FILTER_DISABLE, deblocking_filter);
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_HEADER_INSERTION_MODE, ctx->header_insertion_mode);
|
||||
|
||||
// Rate control
|
||||
// autodetect rate control method
|
||||
if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_UNKNOWN) {
|
||||
if (ctx->min_qp_i != -1 || ctx->max_qp_i != -1 ||
|
||||
ctx->min_qp_p != -1 || ctx->max_qp_p != -1 ||
|
||||
ctx->qp_i !=-1 || ctx->qp_p != -1) {
|
||||
ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP;
|
||||
av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CQP\n");
|
||||
} else if (avctx->rc_max_rate > 0) {
|
||||
ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR;
|
||||
av_log(ctx, AV_LOG_DEBUG, "Rate control turned to Peak VBR\n");
|
||||
} else {
|
||||
ctx->rate_control_mode = AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR;
|
||||
av_log(ctx, AV_LOG_DEBUG, "Rate control turned to CBR\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD, ctx->rate_control_mode);
|
||||
if (avctx->rc_buffer_size) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_VBV_BUFFER_SIZE, avctx->rc_buffer_size);
|
||||
|
||||
if (avctx->rc_initial_buffer_occupancy != 0) {
|
||||
int amf_buffer_fullness = avctx->rc_initial_buffer_occupancy * 64 / avctx->rc_buffer_size;
|
||||
if (amf_buffer_fullness > 64)
|
||||
amf_buffer_fullness = 64;
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_INITIAL_VBV_BUFFER_FULLNESS, amf_buffer_fullness);
|
||||
}
|
||||
}
|
||||
// Pre-Pass, Pre-Analysis, Two-Pass
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_PREANALYSIS_ENABLE, ctx->preanalysis);
|
||||
|
||||
if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CONSTANT_QP) {
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ, false);
|
||||
if (ctx->enable_vbaq)
|
||||
av_log(ctx, AV_LOG_WARNING, "VBAQ is not supported by cqp Rate Control Method, automatically disabled\n");
|
||||
} else {
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENABLE_VBAQ, !!ctx->enable_vbaq);
|
||||
}
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MOTION_HALF_PIXEL, ctx->me_half_pel);
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MOTION_QUARTERPIXEL, ctx->me_quarter_pel);
|
||||
|
||||
// init dynamic rate control params
|
||||
if (ctx->max_au_size)
|
||||
ctx->enforce_hrd = 1;
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_ENFORCE_HRD, ctx->enforce_hrd);
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_FILLER_DATA_ENABLE, ctx->filler_data);
|
||||
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_TARGET_BITRATE, avctx->bit_rate);
|
||||
|
||||
if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_CBR) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE, avctx->bit_rate);
|
||||
}
|
||||
if (avctx->rc_max_rate) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_PEAK_BITRATE, avctx->rc_max_rate);
|
||||
} else if (ctx->rate_control_mode == AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR) {
|
||||
av_log(ctx, AV_LOG_WARNING, "rate control mode is PEAK_CONSTRAINED_VBR but rc_max_rate is not set\n");
|
||||
}
|
||||
|
||||
// init encoder
|
||||
res = ctx->encoder->pVtbl->Init(ctx->encoder, ctx->format, avctx->width, avctx->height);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "encoder->Init() failed with error %d\n", res);
|
||||
|
||||
// init dynamic picture control params
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_AU_SIZE, ctx->max_au_size);
|
||||
|
||||
if (ctx->min_qp_i != -1) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, ctx->min_qp_i);
|
||||
} else if (avctx->qmin != -1) {
|
||||
int qval = avctx->qmin > 51 ? 51 : avctx->qmin;
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_I, qval);
|
||||
}
|
||||
if (ctx->max_qp_i != -1) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, ctx->max_qp_i);
|
||||
} else if (avctx->qmax != -1) {
|
||||
int qval = avctx->qmax > 51 ? 51 : avctx->qmax;
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_I, qval);
|
||||
}
|
||||
if (ctx->min_qp_p != -1) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, ctx->min_qp_p);
|
||||
} else if (avctx->qmin != -1) {
|
||||
int qval = avctx->qmin > 51 ? 51 : avctx->qmin;
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MIN_QP_P, qval);
|
||||
}
|
||||
if (ctx->max_qp_p != -1) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, ctx->max_qp_p);
|
||||
} else if (avctx->qmax != -1) {
|
||||
int qval = avctx->qmax > 51 ? 51 : avctx->qmax;
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_MAX_QP_P, qval);
|
||||
}
|
||||
|
||||
if (ctx->qp_p != -1) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_I, ctx->qp_p);
|
||||
}
|
||||
if (ctx->qp_i != -1) {
|
||||
AMF_ASSIGN_PROPERTY_INT64(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_QP_P, ctx->qp_i);
|
||||
}
|
||||
AMF_ASSIGN_PROPERTY_BOOL(res, ctx->encoder, AMF_VIDEO_ENCODER_HEVC_RATE_CONTROL_SKIP_FRAME_ENABLE, ctx->skip_frame);
|
||||
|
||||
|
||||
// fill extradata
|
||||
res = AMFVariantInit(&var);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "AMFVariantInit() failed with error %d\n", res);
|
||||
|
||||
res = ctx->encoder->pVtbl->GetProperty(ctx->encoder, AMF_VIDEO_ENCODER_HEVC_EXTRADATA, &var);
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) failed with error %d\n", res);
|
||||
AMF_RETURN_IF_FALSE(ctx, var.pInterface != NULL, AVERROR_BUG, "GetProperty(AMF_VIDEO_ENCODER_EXTRADATA) returned NULL\n");
|
||||
|
||||
guid = IID_AMFBuffer();
|
||||
|
||||
res = var.pInterface->pVtbl->QueryInterface(var.pInterface, &guid, (void**)&buffer); // query for buffer interface
|
||||
if (res != AMF_OK) {
|
||||
var.pInterface->pVtbl->Release(var.pInterface);
|
||||
}
|
||||
AMF_RETURN_IF_FALSE(ctx, res == AMF_OK, AVERROR_BUG, "QueryInterface(IID_AMFBuffer) failed with error %d\n", res);
|
||||
|
||||
avctx->extradata_size = (int)buffer->pVtbl->GetSize(buffer);
|
||||
avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
if (!avctx->extradata) {
|
||||
buffer->pVtbl->Release(buffer);
|
||||
var.pInterface->pVtbl->Release(var.pInterface);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
memcpy(avctx->extradata, buffer->pVtbl->GetNative(buffer), avctx->extradata_size);
|
||||
|
||||
buffer->pVtbl->Release(buffer);
|
||||
var.pInterface->pVtbl->Release(var.pInterface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static const AVCodecDefault defaults[] = {
|
||||
{ "refs", "-1" },
|
||||
{ "aspect", "0" },
|
||||
{ "sar", "0" },
|
||||
{ "b", "2M" },
|
||||
{ "g", "250" },
|
||||
{ "slices", "1" },
|
||||
{ NULL },
|
||||
};
|
||||
static const AVClass hevc_amf_class = {
|
||||
.class_name = "hevc_amf",
|
||||
.item_name = av_default_item_name,
|
||||
.option = options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
//TODO declare as HW encoder when available
|
||||
AVCodec ff_hevc_amf_encoder = {
|
||||
.name = "hevc_amf",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("AMD AMF HEVC encoder"),
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_HEVC,
|
||||
.init = amf_encode_init_hevc,
|
||||
.send_frame = ff_amf_send_frame,
|
||||
.receive_packet = ff_amf_receive_packet,
|
||||
.close = ff_amf_encode_close,
|
||||
.priv_data_size = sizeof(AmfContext),
|
||||
.priv_class = &hevc_amf_class,
|
||||
.defaults = defaults,
|
||||
.capabilities = AV_CODEC_CAP_DELAY,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
|
||||
.pix_fmts = ff_amf_pix_fmts,
|
||||
};
|
||||
@@ -611,7 +611,7 @@ static float voice_factor(float *p_vector, float p_gain,
|
||||
AMRWB_SFR_SIZE) *
|
||||
f_gain * f_gain;
|
||||
|
||||
return (p_ener - f_ener) / (p_ener + f_ener);
|
||||
return (p_ener - f_ener) / (p_ener + f_ener + 0.01);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,863 @@
|
||||
/*
|
||||
* Audio Processing Technology codec for Bluetooth (aptX)
|
||||
*
|
||||
* Copyright (C) 2017 Aurelien Jacobs <aurel@gnuage.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/intreadwrite.h"
|
||||
#include "avcodec.h"
|
||||
#include "internal.h"
|
||||
#include "mathops.h"
|
||||
#include "audio_frame_queue.h"
|
||||
|
||||
|
||||
enum channels {
|
||||
LEFT,
|
||||
RIGHT,
|
||||
NB_CHANNELS
|
||||
};
|
||||
|
||||
enum subbands {
|
||||
LF, // Low Frequency (0-5.5 kHz)
|
||||
MLF, // Medium-Low Frequency (5.5-11kHz)
|
||||
MHF, // Medium-High Frequency (11-16.5kHz)
|
||||
HF, // High Frequency (16.5-22kHz)
|
||||
NB_SUBBANDS
|
||||
};
|
||||
|
||||
#define NB_FILTERS 2
|
||||
#define FILTER_TAPS 16
|
||||
|
||||
typedef struct {
|
||||
int pos;
|
||||
int32_t buffer[2*FILTER_TAPS];
|
||||
} FilterSignal;
|
||||
|
||||
typedef struct {
|
||||
FilterSignal outer_filter_signal[NB_FILTERS];
|
||||
FilterSignal inner_filter_signal[NB_FILTERS][NB_FILTERS];
|
||||
} QMFAnalysis;
|
||||
|
||||
typedef struct {
|
||||
int32_t quantized_sample;
|
||||
int32_t quantized_sample_parity_change;
|
||||
int32_t error;
|
||||
} Quantize;
|
||||
|
||||
typedef struct {
|
||||
int32_t quantization_factor;
|
||||
int32_t factor_select;
|
||||
int32_t reconstructed_difference;
|
||||
} InvertQuantize;
|
||||
|
||||
typedef struct {
|
||||
int32_t prev_sign[2];
|
||||
int32_t s_weight[2];
|
||||
int32_t d_weight[24];
|
||||
int32_t pos;
|
||||
int32_t reconstructed_differences[48];
|
||||
int32_t previous_reconstructed_sample;
|
||||
int32_t predicted_difference;
|
||||
int32_t predicted_sample;
|
||||
} Prediction;
|
||||
|
||||
typedef struct {
|
||||
int32_t codeword_history;
|
||||
int32_t dither_parity;
|
||||
int32_t dither[NB_SUBBANDS];
|
||||
|
||||
QMFAnalysis qmf;
|
||||
Quantize quantize[NB_SUBBANDS];
|
||||
InvertQuantize invert_quantize[NB_SUBBANDS];
|
||||
Prediction prediction[NB_SUBBANDS];
|
||||
} Channel;
|
||||
|
||||
typedef struct {
|
||||
int32_t sync_idx;
|
||||
Channel channels[NB_CHANNELS];
|
||||
AudioFrameQueue afq;
|
||||
} AptXContext;
|
||||
|
||||
|
||||
static const int32_t quantize_intervals_LF[65] = {
|
||||
-9948, 9948, 29860, 49808, 69822, 89926, 110144, 130502,
|
||||
151026, 171738, 192666, 213832, 235264, 256982, 279014, 301384,
|
||||
324118, 347244, 370790, 394782, 419250, 444226, 469742, 495832,
|
||||
522536, 549890, 577936, 606720, 636290, 666700, 698006, 730270,
|
||||
763562, 797958, 833538, 870398, 908640, 948376, 989740, 1032874,
|
||||
1077948, 1125150, 1174700, 1226850, 1281900, 1340196, 1402156, 1468282,
|
||||
1539182, 1615610, 1698514, 1789098, 1888944, 2000168, 2125700, 2269750,
|
||||
2438670, 2642660, 2899462, 3243240, 3746078, 4535138, 5664098, 7102424,
|
||||
8897462,
|
||||
};
|
||||
static const int32_t invert_quantize_dither_factors_LF[65] = {
|
||||
9948, 9948, 9962, 9988, 10026, 10078, 10142, 10218,
|
||||
10306, 10408, 10520, 10646, 10784, 10934, 11098, 11274,
|
||||
11462, 11664, 11880, 12112, 12358, 12618, 12898, 13194,
|
||||
13510, 13844, 14202, 14582, 14988, 15422, 15884, 16380,
|
||||
16912, 17484, 18098, 18762, 19480, 20258, 21106, 22030,
|
||||
23044, 24158, 25390, 26760, 28290, 30008, 31954, 34172,
|
||||
36728, 39700, 43202, 47382, 52462, 58762, 66770, 77280,
|
||||
91642, 112348, 144452, 199326, 303512, 485546, 643414, 794914,
|
||||
1000124,
|
||||
};
|
||||
static const int32_t quantize_dither_factors_LF[65] = {
|
||||
0, 4, 7, 10, 13, 16, 19, 22,
|
||||
26, 28, 32, 35, 38, 41, 44, 47,
|
||||
51, 54, 58, 62, 65, 70, 74, 79,
|
||||
84, 90, 95, 102, 109, 116, 124, 133,
|
||||
143, 154, 166, 180, 195, 212, 231, 254,
|
||||
279, 308, 343, 383, 430, 487, 555, 639,
|
||||
743, 876, 1045, 1270, 1575, 2002, 2628, 3591,
|
||||
5177, 8026, 13719, 26047, 45509, 39467, 37875, 51303,
|
||||
0,
|
||||
};
|
||||
static const int16_t quantize_factor_select_offset_LF[65] = {
|
||||
0, -21, -19, -17, -15, -12, -10, -8,
|
||||
-6, -4, -1, 1, 3, 6, 8, 10,
|
||||
13, 15, 18, 20, 23, 26, 29, 31,
|
||||
34, 37, 40, 43, 47, 50, 53, 57,
|
||||
60, 64, 68, 72, 76, 80, 85, 89,
|
||||
94, 99, 105, 110, 116, 123, 129, 136,
|
||||
144, 152, 161, 171, 182, 194, 207, 223,
|
||||
241, 263, 291, 328, 382, 467, 522, 522,
|
||||
522,
|
||||
};
|
||||
|
||||
|
||||
static const int32_t quantize_intervals_MLF[9] = {
|
||||
-89806, 89806, 278502, 494338, 759442, 1113112, 1652322, 2720256, 5190186,
|
||||
};
|
||||
static const int32_t invert_quantize_dither_factors_MLF[9] = {
|
||||
89806, 89806, 98890, 116946, 148158, 205512, 333698, 734236, 1735696,
|
||||
};
|
||||
static const int32_t quantize_dither_factors_MLF[9] = {
|
||||
0, 2271, 4514, 7803, 14339, 32047, 100135, 250365, 0,
|
||||
};
|
||||
static const int16_t quantize_factor_select_offset_MLF[9] = {
|
||||
0, -14, 6, 29, 58, 96, 154, 270, 521,
|
||||
};
|
||||
|
||||
|
||||
static const int32_t quantize_intervals_MHF[3] = {
|
||||
-194080, 194080, 890562,
|
||||
};
|
||||
static const int32_t invert_quantize_dither_factors_MHF[3] = {
|
||||
194080, 194080, 502402,
|
||||
};
|
||||
static const int32_t quantize_dither_factors_MHF[3] = {
|
||||
0, 77081, 0,
|
||||
};
|
||||
static const int16_t quantize_factor_select_offset_MHF[3] = {
|
||||
0, -33, 136,
|
||||
};
|
||||
|
||||
|
||||
static const int32_t quantize_intervals_HF[5] = {
|
||||
-163006, 163006, 542708, 1120554, 2669238,
|
||||
};
|
||||
static const int32_t invert_quantize_dither_factors_HF[5] = {
|
||||
163006, 163006, 216698, 361148, 1187538,
|
||||
};
|
||||
static const int32_t quantize_dither_factors_HF[5] = {
|
||||
0, 13423, 36113, 206598, 0,
|
||||
};
|
||||
static const int16_t quantize_factor_select_offset_HF[5] = {
|
||||
0, -8, 33, 95, 262,
|
||||
};
|
||||
|
||||
typedef const struct {
|
||||
const int32_t *quantize_intervals;
|
||||
const int32_t *invert_quantize_dither_factors;
|
||||
const int32_t *quantize_dither_factors;
|
||||
const int16_t *quantize_factor_select_offset;
|
||||
int tables_size;
|
||||
int32_t quantized_bits;
|
||||
int32_t prediction_order;
|
||||
} ConstTables;
|
||||
|
||||
static ConstTables tables[NB_SUBBANDS] = {
|
||||
[LF] = { quantize_intervals_LF,
|
||||
invert_quantize_dither_factors_LF,
|
||||
quantize_dither_factors_LF,
|
||||
quantize_factor_select_offset_LF,
|
||||
FF_ARRAY_ELEMS(quantize_intervals_LF),
|
||||
7, 24 },
|
||||
[MLF] = { quantize_intervals_MLF,
|
||||
invert_quantize_dither_factors_MLF,
|
||||
quantize_dither_factors_MLF,
|
||||
quantize_factor_select_offset_MLF,
|
||||
FF_ARRAY_ELEMS(quantize_intervals_MLF),
|
||||
4, 12 },
|
||||
[MHF] = { quantize_intervals_MHF,
|
||||
invert_quantize_dither_factors_MHF,
|
||||
quantize_dither_factors_MHF,
|
||||
quantize_factor_select_offset_MHF,
|
||||
FF_ARRAY_ELEMS(quantize_intervals_MHF),
|
||||
2, 6 },
|
||||
[HF] = { quantize_intervals_HF,
|
||||
invert_quantize_dither_factors_HF,
|
||||
quantize_dither_factors_HF,
|
||||
quantize_factor_select_offset_HF,
|
||||
FF_ARRAY_ELEMS(quantize_intervals_HF),
|
||||
3, 12 },
|
||||
};
|
||||
|
||||
static const int16_t quantization_factors[32] = {
|
||||
2048, 2093, 2139, 2186, 2233, 2282, 2332, 2383,
|
||||
2435, 2489, 2543, 2599, 2656, 2714, 2774, 2834,
|
||||
2896, 2960, 3025, 3091, 3158, 3228, 3298, 3371,
|
||||
3444, 3520, 3597, 3676, 3756, 3838, 3922, 4008,
|
||||
};
|
||||
|
||||
|
||||
/* Rounded right shift with optionnal clipping */
|
||||
#define RSHIFT_SIZE(size) \
|
||||
av_always_inline \
|
||||
static int##size##_t rshift##size(int##size##_t value, int shift) \
|
||||
{ \
|
||||
int##size##_t rounding = (int##size##_t)1 << (shift - 1); \
|
||||
int##size##_t mask = ((int##size##_t)1 << (shift + 1)) - 1; \
|
||||
return ((value + rounding) >> shift) - ((value & mask) == rounding); \
|
||||
} \
|
||||
av_always_inline \
|
||||
static int##size##_t rshift##size##_clip24(int##size##_t value, int shift) \
|
||||
{ \
|
||||
return av_clip_intp2(rshift##size(value, shift), 23); \
|
||||
}
|
||||
RSHIFT_SIZE(32)
|
||||
RSHIFT_SIZE(64)
|
||||
|
||||
|
||||
av_always_inline
|
||||
static void aptx_update_codeword_history(Channel *channel)
|
||||
{
|
||||
int32_t cw = ((channel->quantize[0].quantized_sample & 3) << 0) +
|
||||
((channel->quantize[1].quantized_sample & 2) << 1) +
|
||||
((channel->quantize[2].quantized_sample & 1) << 3);
|
||||
channel->codeword_history = (cw << 8) + (channel->codeword_history << 4);
|
||||
}
|
||||
|
||||
static void aptx_generate_dither(Channel *channel)
|
||||
{
|
||||
int subband;
|
||||
int64_t m;
|
||||
int32_t d;
|
||||
|
||||
aptx_update_codeword_history(channel);
|
||||
|
||||
m = (int64_t)5184443 * (channel->codeword_history >> 7);
|
||||
d = (m << 2) + (m >> 22);
|
||||
for (subband = 0; subband < NB_SUBBANDS; subband++)
|
||||
channel->dither[subband] = d << (23 - 5*subband);
|
||||
channel->dither_parity = (d >> 25) & 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convolution filter coefficients for the outer QMF of the QMF tree.
|
||||
* The 2 sets are a mirror of each other.
|
||||
*/
|
||||
static const int32_t aptx_qmf_outer_coeffs[NB_FILTERS][FILTER_TAPS] = {
|
||||
{
|
||||
730, -413, -9611, 43626, -121026, 269973, -585547, 2801966,
|
||||
697128, -160481, 27611, 8478, -10043, 3511, 688, -897,
|
||||
},
|
||||
{
|
||||
-897, 688, 3511, -10043, 8478, 27611, -160481, 697128,
|
||||
2801966, -585547, 269973, -121026, 43626, -9611, -413, 730,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Convolution filter coefficients for the inner QMF of the QMF tree.
|
||||
* The 2 sets are a mirror of each other.
|
||||
*/
|
||||
static const int32_t aptx_qmf_inner_coeffs[NB_FILTERS][FILTER_TAPS] = {
|
||||
{
|
||||
1033, -584, -13592, 61697, -171156, 381799, -828088, 3962579,
|
||||
985888, -226954, 39048, 11990, -14203, 4966, 973, -1268,
|
||||
},
|
||||
{
|
||||
-1268, 973, 4966, -14203, 11990, 39048, -226954, 985888,
|
||||
3962579, -828088, 381799, -171156, 61697, -13592, -584, 1033,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Push one sample into a circular signal buffer.
|
||||
*/
|
||||
av_always_inline
|
||||
static void aptx_qmf_filter_signal_push(FilterSignal *signal, int32_t sample)
|
||||
{
|
||||
signal->buffer[signal->pos ] = sample;
|
||||
signal->buffer[signal->pos+FILTER_TAPS] = sample;
|
||||
signal->pos = (signal->pos + 1) & (FILTER_TAPS - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the convolution of the signal with the coefficients, and reduce
|
||||
* to 24 bits by applying the specified right shifting.
|
||||
*/
|
||||
av_always_inline
|
||||
static int32_t aptx_qmf_convolution(FilterSignal *signal,
|
||||
const int32_t coeffs[FILTER_TAPS],
|
||||
int shift)
|
||||
{
|
||||
int32_t *sig = &signal->buffer[signal->pos];
|
||||
int64_t e = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FILTER_TAPS; i++)
|
||||
e += MUL64(sig[i], coeffs[i]);
|
||||
|
||||
return rshift64_clip24(e, shift);
|
||||
}
|
||||
|
||||
/*
|
||||
* Half-band QMF analysis filter realized with a polyphase FIR filter.
|
||||
* Split into 2 subbands and downsample by 2.
|
||||
* So for each pair of samples that goes in, one sample goes out,
|
||||
* split into 2 separate subbands.
|
||||
*/
|
||||
av_always_inline
|
||||
static void aptx_qmf_polyphase_analysis(FilterSignal signal[NB_FILTERS],
|
||||
const int32_t coeffs[NB_FILTERS][FILTER_TAPS],
|
||||
int shift,
|
||||
int32_t samples[NB_FILTERS],
|
||||
int32_t *low_subband_output,
|
||||
int32_t *high_subband_output)
|
||||
{
|
||||
int32_t subbands[NB_FILTERS];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NB_FILTERS; i++) {
|
||||
aptx_qmf_filter_signal_push(&signal[i], samples[NB_FILTERS-1-i]);
|
||||
subbands[i] = aptx_qmf_convolution(&signal[i], coeffs[i], shift);
|
||||
}
|
||||
|
||||
*low_subband_output = av_clip_intp2(subbands[0] + subbands[1], 23);
|
||||
*high_subband_output = av_clip_intp2(subbands[0] - subbands[1], 23);
|
||||
}
|
||||
|
||||
/*
|
||||
* Two stage QMF analysis tree.
|
||||
* Split 4 input samples into 4 subbands and downsample by 4.
|
||||
* So for each group of 4 samples that goes in, one sample goes out,
|
||||
* split into 4 separate subbands.
|
||||
*/
|
||||
static void aptx_qmf_tree_analysis(QMFAnalysis *qmf,
|
||||
int32_t samples[4],
|
||||
int32_t subband_samples[4])
|
||||
{
|
||||
int32_t intermediate_samples[4];
|
||||
int i;
|
||||
|
||||
/* Split 4 input samples into 2 intermediate subbands downsampled to 2 samples */
|
||||
for (i = 0; i < 2; i++)
|
||||
aptx_qmf_polyphase_analysis(qmf->outer_filter_signal,
|
||||
aptx_qmf_outer_coeffs, 23,
|
||||
&samples[2*i],
|
||||
&intermediate_samples[0+i],
|
||||
&intermediate_samples[2+i]);
|
||||
|
||||
/* Split 2 intermediate subband samples into 4 final subbands downsampled to 1 sample */
|
||||
for (i = 0; i < 2; i++)
|
||||
aptx_qmf_polyphase_analysis(qmf->inner_filter_signal[i],
|
||||
aptx_qmf_inner_coeffs, 23,
|
||||
&intermediate_samples[2*i],
|
||||
&subband_samples[2*i+0],
|
||||
&subband_samples[2*i+1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Half-band QMF synthesis filter realized with a polyphase FIR filter.
|
||||
* Join 2 subbands and upsample by 2.
|
||||
* So for each 2 subbands sample that goes in, a pair of samples goes out.
|
||||
*/
|
||||
av_always_inline
|
||||
static void aptx_qmf_polyphase_synthesis(FilterSignal signal[NB_FILTERS],
|
||||
const int32_t coeffs[NB_FILTERS][FILTER_TAPS],
|
||||
int shift,
|
||||
int32_t low_subband_input,
|
||||
int32_t high_subband_input,
|
||||
int32_t samples[NB_FILTERS])
|
||||
{
|
||||
int32_t subbands[NB_FILTERS];
|
||||
int i;
|
||||
|
||||
subbands[0] = low_subband_input + high_subband_input;
|
||||
subbands[1] = low_subband_input - high_subband_input;
|
||||
|
||||
for (i = 0; i < NB_FILTERS; i++) {
|
||||
aptx_qmf_filter_signal_push(&signal[i], subbands[1-i]);
|
||||
samples[i] = aptx_qmf_convolution(&signal[i], coeffs[i], shift);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Two stage QMF synthesis tree.
|
||||
* Join 4 subbands and upsample by 4.
|
||||
* So for each 4 subbands sample that goes in, a group of 4 samples goes out.
|
||||
*/
|
||||
static void aptx_qmf_tree_synthesis(QMFAnalysis *qmf,
|
||||
int32_t subband_samples[4],
|
||||
int32_t samples[4])
|
||||
{
|
||||
int32_t intermediate_samples[4];
|
||||
int i;
|
||||
|
||||
/* Join 4 subbands into 2 intermediate subbands upsampled to 2 samples. */
|
||||
for (i = 0; i < 2; i++)
|
||||
aptx_qmf_polyphase_synthesis(qmf->inner_filter_signal[i],
|
||||
aptx_qmf_inner_coeffs, 22,
|
||||
subband_samples[2*i+0],
|
||||
subband_samples[2*i+1],
|
||||
&intermediate_samples[2*i]);
|
||||
|
||||
/* Join 2 samples from intermediate subbands upsampled to 4 samples. */
|
||||
for (i = 0; i < 2; i++)
|
||||
aptx_qmf_polyphase_synthesis(qmf->outer_filter_signal,
|
||||
aptx_qmf_outer_coeffs, 21,
|
||||
intermediate_samples[0+i],
|
||||
intermediate_samples[2+i],
|
||||
&samples[2*i]);
|
||||
}
|
||||
|
||||
|
||||
av_always_inline
|
||||
static int32_t aptx_bin_search(int32_t value, int32_t factor,
|
||||
const int32_t *intervals, int32_t nb_intervals)
|
||||
{
|
||||
int32_t idx = 0;
|
||||
int i;
|
||||
|
||||
for (i = nb_intervals >> 1; i > 0; i >>= 1)
|
||||
if (MUL64(factor, intervals[idx + i]) <= ((int64_t)value << 24))
|
||||
idx += i;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
static void aptx_quantize_difference(Quantize *quantize,
|
||||
int32_t sample_difference,
|
||||
int32_t dither,
|
||||
int32_t quantization_factor,
|
||||
ConstTables *tables)
|
||||
{
|
||||
const int32_t *intervals = tables->quantize_intervals;
|
||||
int32_t quantized_sample, dithered_sample, parity_change;
|
||||
int32_t d, mean, interval, inv;
|
||||
int64_t error;
|
||||
|
||||
quantized_sample = aptx_bin_search(FFABS(sample_difference) >> 4,
|
||||
quantization_factor,
|
||||
intervals, tables->tables_size);
|
||||
|
||||
d = rshift32_clip24(MULH(dither, dither), 7) - (1 << 23);
|
||||
d = rshift64(MUL64(d, tables->quantize_dither_factors[quantized_sample]), 23);
|
||||
|
||||
intervals += quantized_sample;
|
||||
mean = (intervals[1] + intervals[0]) / 2;
|
||||
interval = (intervals[1] - intervals[0]) * (-(sample_difference < 0) | 1);
|
||||
|
||||
dithered_sample = rshift64_clip24(MUL64(dither, interval) + ((int64_t)(mean + d) << 32), 32);
|
||||
error = ((int64_t)FFABS(sample_difference) << 20) - MUL64(dithered_sample, quantization_factor);
|
||||
quantize->error = FFABS(rshift64(error, 23));
|
||||
|
||||
parity_change = quantized_sample;
|
||||
if (error < 0)
|
||||
quantized_sample--;
|
||||
else
|
||||
parity_change--;
|
||||
|
||||
inv = -(sample_difference < 0);
|
||||
quantize->quantized_sample = quantized_sample ^ inv;
|
||||
quantize->quantized_sample_parity_change = parity_change ^ inv;
|
||||
}
|
||||
|
||||
static void aptx_encode_channel(Channel *channel, int32_t samples[4])
|
||||
{
|
||||
int32_t subband_samples[4];
|
||||
int subband;
|
||||
aptx_qmf_tree_analysis(&channel->qmf, samples, subband_samples);
|
||||
aptx_generate_dither(channel);
|
||||
for (subband = 0; subband < NB_SUBBANDS; subband++) {
|
||||
int32_t diff = av_clip_intp2(subband_samples[subband] - channel->prediction[subband].predicted_sample, 23);
|
||||
aptx_quantize_difference(&channel->quantize[subband], diff,
|
||||
channel->dither[subband],
|
||||
channel->invert_quantize[subband].quantization_factor,
|
||||
&tables[subband]);
|
||||
}
|
||||
}
|
||||
|
||||
static void aptx_decode_channel(Channel *channel, int32_t samples[4])
|
||||
{
|
||||
int32_t subband_samples[4];
|
||||
int subband;
|
||||
for (subband = 0; subband < NB_SUBBANDS; subband++)
|
||||
subband_samples[subband] = channel->prediction[subband].previous_reconstructed_sample;
|
||||
aptx_qmf_tree_synthesis(&channel->qmf, subband_samples, samples);
|
||||
}
|
||||
|
||||
|
||||
static void aptx_invert_quantization(InvertQuantize *invert_quantize,
|
||||
int32_t quantized_sample, int32_t dither,
|
||||
ConstTables *tables)
|
||||
{
|
||||
int32_t qr, idx, shift, factor_select;
|
||||
|
||||
idx = (quantized_sample ^ -(quantized_sample < 0)) + 1;
|
||||
qr = tables->quantize_intervals[idx] / 2;
|
||||
if (quantized_sample < 0)
|
||||
qr = -qr;
|
||||
|
||||
qr = rshift64_clip24(((int64_t)qr<<32) + MUL64(dither, tables->invert_quantize_dither_factors[idx]), 32);
|
||||
invert_quantize->reconstructed_difference = MUL64(invert_quantize->quantization_factor, qr) >> 19;
|
||||
|
||||
shift = 24 - tables->quantized_bits;
|
||||
|
||||
/* update factor_select */
|
||||
factor_select = 32620 * invert_quantize->factor_select;
|
||||
factor_select = rshift32(factor_select + (tables->quantize_factor_select_offset[idx] << 15), 15);
|
||||
invert_quantize->factor_select = av_clip(factor_select, 0, (shift << 8) | 0xFF);
|
||||
|
||||
/* update quantization factor */
|
||||
idx = (invert_quantize->factor_select & 0xFF) >> 3;
|
||||
shift -= invert_quantize->factor_select >> 8;
|
||||
invert_quantize->quantization_factor = (quantization_factors[idx] << 11) >> shift;
|
||||
}
|
||||
|
||||
static int32_t *aptx_reconstructed_differences_update(Prediction *prediction,
|
||||
int32_t reconstructed_difference,
|
||||
int order)
|
||||
{
|
||||
int32_t *rd1 = prediction->reconstructed_differences, *rd2 = rd1 + order;
|
||||
int p = prediction->pos;
|
||||
|
||||
rd1[p] = rd2[p];
|
||||
prediction->pos = p = (p + 1) % order;
|
||||
rd2[p] = reconstructed_difference;
|
||||
return &rd2[p];
|
||||
}
|
||||
|
||||
static void aptx_prediction_filtering(Prediction *prediction,
|
||||
int32_t reconstructed_difference,
|
||||
int order)
|
||||
{
|
||||
int32_t reconstructed_sample, predictor, srd0;
|
||||
int32_t *reconstructed_differences;
|
||||
int64_t predicted_difference = 0;
|
||||
int i;
|
||||
|
||||
reconstructed_sample = av_clip_intp2(reconstructed_difference + prediction->predicted_sample, 23);
|
||||
predictor = av_clip_intp2((MUL64(prediction->s_weight[0], prediction->previous_reconstructed_sample)
|
||||
+ MUL64(prediction->s_weight[1], reconstructed_sample)) >> 22, 23);
|
||||
prediction->previous_reconstructed_sample = reconstructed_sample;
|
||||
|
||||
reconstructed_differences = aptx_reconstructed_differences_update(prediction, reconstructed_difference, order);
|
||||
srd0 = FFDIFFSIGN(reconstructed_difference, 0) << 23;
|
||||
for (i = 0; i < order; i++) {
|
||||
int32_t srd = FF_SIGNBIT(reconstructed_differences[-i-1]) | 1;
|
||||
prediction->d_weight[i] -= rshift32(prediction->d_weight[i] - srd*srd0, 8);
|
||||
predicted_difference += MUL64(reconstructed_differences[-i], prediction->d_weight[i]);
|
||||
}
|
||||
|
||||
prediction->predicted_difference = av_clip_intp2(predicted_difference >> 22, 23);
|
||||
prediction->predicted_sample = av_clip_intp2(predictor + prediction->predicted_difference, 23);
|
||||
}
|
||||
|
||||
static void aptx_process_subband(InvertQuantize *invert_quantize,
|
||||
Prediction *prediction,
|
||||
int32_t quantized_sample, int32_t dither,
|
||||
ConstTables *tables)
|
||||
{
|
||||
int32_t sign, same_sign[2], weight[2], sw1, range;
|
||||
|
||||
aptx_invert_quantization(invert_quantize, quantized_sample, dither, tables);
|
||||
|
||||
sign = FFDIFFSIGN(invert_quantize->reconstructed_difference,
|
||||
-prediction->predicted_difference);
|
||||
same_sign[0] = sign * prediction->prev_sign[0];
|
||||
same_sign[1] = sign * prediction->prev_sign[1];
|
||||
prediction->prev_sign[0] = prediction->prev_sign[1];
|
||||
prediction->prev_sign[1] = sign | 1;
|
||||
|
||||
range = 0x100000;
|
||||
sw1 = rshift32(-same_sign[1] * prediction->s_weight[1], 1);
|
||||
sw1 = (av_clip(sw1, -range, range) & ~0xF) << 4;
|
||||
|
||||
range = 0x300000;
|
||||
weight[0] = 254 * prediction->s_weight[0] + 0x800000*same_sign[0] + sw1;
|
||||
prediction->s_weight[0] = av_clip(rshift32(weight[0], 8), -range, range);
|
||||
|
||||
range = 0x3C0000 - prediction->s_weight[0];
|
||||
weight[1] = 255 * prediction->s_weight[1] + 0xC00000*same_sign[1];
|
||||
prediction->s_weight[1] = av_clip(rshift32(weight[1], 8), -range, range);
|
||||
|
||||
aptx_prediction_filtering(prediction,
|
||||
invert_quantize->reconstructed_difference,
|
||||
tables->prediction_order);
|
||||
}
|
||||
|
||||
static void aptx_invert_quantize_and_prediction(Channel *channel)
|
||||
{
|
||||
int subband;
|
||||
for (subband = 0; subband < NB_SUBBANDS; subband++)
|
||||
aptx_process_subband(&channel->invert_quantize[subband],
|
||||
&channel->prediction[subband],
|
||||
channel->quantize[subband].quantized_sample,
|
||||
channel->dither[subband],
|
||||
&tables[subband]);
|
||||
}
|
||||
|
||||
static int32_t aptx_quantized_parity(Channel *channel)
|
||||
{
|
||||
int32_t parity = channel->dither_parity;
|
||||
int subband;
|
||||
|
||||
for (subband = 0; subband < NB_SUBBANDS; subband++)
|
||||
parity ^= channel->quantize[subband].quantized_sample;
|
||||
|
||||
return parity & 1;
|
||||
}
|
||||
|
||||
/* For each sample, ensure that the parity of all subbands of all channels
|
||||
* is 0 except once every 8 samples where the parity is forced to 1. */
|
||||
static int aptx_check_parity(Channel channels[NB_CHANNELS], int32_t *idx)
|
||||
{
|
||||
int32_t parity = aptx_quantized_parity(&channels[LEFT])
|
||||
^ aptx_quantized_parity(&channels[RIGHT]);
|
||||
|
||||
int eighth = *idx == 7;
|
||||
*idx = (*idx + 1) & 7;
|
||||
|
||||
return parity ^ eighth;
|
||||
}
|
||||
|
||||
static void aptx_insert_sync(Channel channels[NB_CHANNELS], int32_t *idx)
|
||||
{
|
||||
if (aptx_check_parity(channels, idx)) {
|
||||
int i;
|
||||
Channel *c;
|
||||
static const int map[] = { 1, 2, 0, 3 };
|
||||
Quantize *min = &channels[NB_CHANNELS-1].quantize[map[0]];
|
||||
for (c = &channels[NB_CHANNELS-1]; c >= channels; c--)
|
||||
for (i = 0; i < NB_SUBBANDS; i++)
|
||||
if (c->quantize[map[i]].error < min->error)
|
||||
min = &c->quantize[map[i]];
|
||||
|
||||
/* Forcing the desired parity is done by offsetting by 1 the quantized
|
||||
* sample from the subband featuring the smallest quantization error. */
|
||||
min->quantized_sample = min->quantized_sample_parity_change;
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t aptx_pack_codeword(Channel *channel)
|
||||
{
|
||||
int32_t parity = aptx_quantized_parity(channel);
|
||||
return (((channel->quantize[3].quantized_sample & 0x06) | parity) << 13)
|
||||
| (((channel->quantize[2].quantized_sample & 0x03) ) << 11)
|
||||
| (((channel->quantize[1].quantized_sample & 0x0F) ) << 7)
|
||||
| (((channel->quantize[0].quantized_sample & 0x7F) ) << 0);
|
||||
}
|
||||
|
||||
static void aptx_unpack_codeword(Channel *channel, uint16_t codeword)
|
||||
{
|
||||
channel->quantize[0].quantized_sample = sign_extend(codeword >> 0, 7);
|
||||
channel->quantize[1].quantized_sample = sign_extend(codeword >> 7, 4);
|
||||
channel->quantize[2].quantized_sample = sign_extend(codeword >> 11, 2);
|
||||
channel->quantize[3].quantized_sample = sign_extend(codeword >> 13, 3);
|
||||
channel->quantize[3].quantized_sample = (channel->quantize[3].quantized_sample & ~1)
|
||||
| aptx_quantized_parity(channel);
|
||||
}
|
||||
|
||||
static void aptx_encode_samples(AptXContext *ctx,
|
||||
int32_t samples[NB_CHANNELS][4],
|
||||
uint8_t output[2*NB_CHANNELS])
|
||||
{
|
||||
int channel;
|
||||
for (channel = 0; channel < NB_CHANNELS; channel++)
|
||||
aptx_encode_channel(&ctx->channels[channel], samples[channel]);
|
||||
|
||||
aptx_insert_sync(ctx->channels, &ctx->sync_idx);
|
||||
|
||||
for (channel = 0; channel < NB_CHANNELS; channel++) {
|
||||
aptx_invert_quantize_and_prediction(&ctx->channels[channel]);
|
||||
AV_WB16(output + 2*channel, aptx_pack_codeword(&ctx->channels[channel]));
|
||||
}
|
||||
}
|
||||
|
||||
static int aptx_decode_samples(AptXContext *ctx,
|
||||
const uint8_t input[2*NB_CHANNELS],
|
||||
int32_t samples[NB_CHANNELS][4])
|
||||
{
|
||||
int channel, ret;
|
||||
|
||||
for (channel = 0; channel < NB_CHANNELS; channel++) {
|
||||
uint16_t codeword;
|
||||
aptx_generate_dither(&ctx->channels[channel]);
|
||||
|
||||
codeword = AV_RB16(input + 2*channel);
|
||||
aptx_unpack_codeword(&ctx->channels[channel], codeword);
|
||||
aptx_invert_quantize_and_prediction(&ctx->channels[channel]);
|
||||
}
|
||||
|
||||
ret = aptx_check_parity(ctx->channels, &ctx->sync_idx);
|
||||
|
||||
for (channel = 0; channel < NB_CHANNELS; channel++)
|
||||
aptx_decode_channel(&ctx->channels[channel], samples[channel]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static av_cold int aptx_init(AVCodecContext *avctx)
|
||||
{
|
||||
AptXContext *s = avctx->priv_data;
|
||||
int chan, subband;
|
||||
|
||||
if (avctx->frame_size == 0)
|
||||
avctx->frame_size = 1024;
|
||||
|
||||
if (avctx->frame_size & 3) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Frame size must be a multiple of 4 samples\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
for (chan = 0; chan < NB_CHANNELS; chan++) {
|
||||
Channel *channel = &s->channels[chan];
|
||||
for (subband = 0; subband < NB_SUBBANDS; subband++) {
|
||||
Prediction *prediction = &channel->prediction[subband];
|
||||
prediction->prev_sign[0] = 1;
|
||||
prediction->prev_sign[1] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ff_af_queue_init(avctx, &s->afq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aptx_decode_frame(AVCodecContext *avctx, void *data,
|
||||
int *got_frame_ptr, AVPacket *avpkt)
|
||||
{
|
||||
AptXContext *s = avctx->priv_data;
|
||||
AVFrame *frame = data;
|
||||
int pos, channel, sample, ret;
|
||||
|
||||
if (avpkt->size < 4) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Packet is too small\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
/* get output buffer */
|
||||
frame->channels = NB_CHANNELS;
|
||||
frame->format = AV_SAMPLE_FMT_S32P;
|
||||
frame->nb_samples = avpkt->size & ~3;
|
||||
if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
|
||||
return ret;
|
||||
|
||||
for (pos = 0; pos < frame->nb_samples; pos += 4) {
|
||||
int32_t samples[NB_CHANNELS][4];
|
||||
|
||||
if (aptx_decode_samples(s, &avpkt->data[pos], samples)) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Synchronization error\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
for (channel = 0; channel < NB_CHANNELS; channel++)
|
||||
for (sample = 0; sample < 4; sample++)
|
||||
AV_WN32A(&frame->data[channel][4*(sample+pos)],
|
||||
samples[channel][sample] << 8);
|
||||
}
|
||||
|
||||
*got_frame_ptr = 1;
|
||||
return frame->nb_samples;
|
||||
}
|
||||
|
||||
static int aptx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
|
||||
const AVFrame *frame, int *got_packet_ptr)
|
||||
{
|
||||
AptXContext *s = avctx->priv_data;
|
||||
int pos, channel, sample, ret;
|
||||
|
||||
if ((ret = ff_af_queue_add(&s->afq, frame)) < 0)
|
||||
return ret;
|
||||
|
||||
if ((ret = ff_alloc_packet2(avctx, avpkt, frame->nb_samples, 0)) < 0)
|
||||
return ret;
|
||||
|
||||
for (pos = 0; pos < frame->nb_samples; pos += 4) {
|
||||
int32_t samples[NB_CHANNELS][4];
|
||||
|
||||
for (channel = 0; channel < NB_CHANNELS; channel++)
|
||||
for (sample = 0; sample < 4; sample++)
|
||||
samples[channel][sample] = (int32_t)AV_RN32A(&frame->data[channel][4*(sample+pos)]) >> 8;
|
||||
|
||||
aptx_encode_samples(s, samples, avpkt->data + pos);
|
||||
}
|
||||
|
||||
ff_af_queue_remove(&s->afq, frame->nb_samples, &avpkt->pts, &avpkt->duration);
|
||||
*got_packet_ptr = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_cold int aptx_close(AVCodecContext *avctx)
|
||||
{
|
||||
AptXContext *s = avctx->priv_data;
|
||||
ff_af_queue_close(&s->afq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if CONFIG_APTX_DECODER
|
||||
AVCodec ff_aptx_decoder = {
|
||||
.name = "aptx",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("aptX (Audio Processing Technology for Bluetooth)"),
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.id = AV_CODEC_ID_APTX,
|
||||
.priv_data_size = sizeof(AptXContext),
|
||||
.init = aptx_init,
|
||||
.decode = aptx_decode_frame,
|
||||
.close = aptx_close,
|
||||
.capabilities = AV_CODEC_CAP_DR1,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
|
||||
.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0},
|
||||
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P,
|
||||
AV_SAMPLE_FMT_NONE },
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_APTX_ENCODER
|
||||
AVCodec ff_aptx_encoder = {
|
||||
.name = "aptx",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("aptX (Audio Processing Technology for Bluetooth)"),
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.id = AV_CODEC_ID_APTX,
|
||||
.priv_data_size = sizeof(AptXContext),
|
||||
.init = aptx_init,
|
||||
.encode2 = aptx_encode_frame,
|
||||
.close = aptx_close,
|
||||
.capabilities = AV_CODEC_CAP_SMALL_LAST_FRAME,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
|
||||
.channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_STEREO, 0},
|
||||
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S32P,
|
||||
AV_SAMPLE_FMT_NONE },
|
||||
.supported_samplerates = (const int[]) {8000, 16000, 24000, 32000, 44100, 48000, 0},
|
||||
};
|
||||
#endif
|
||||
@@ -42,10 +42,8 @@ av_cold void ff_fmt_convert_init_arm(FmtConvertContext *c, AVCodecContext *avctx
|
||||
int cpu_flags = av_get_cpu_flags();
|
||||
|
||||
if (have_vfp_vm(cpu_flags)) {
|
||||
if (!have_vfpv3(cpu_flags)) {
|
||||
c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_vfp;
|
||||
c->int32_to_float_fmul_array8 = ff_int32_to_float_fmul_array8_vfp;
|
||||
}
|
||||
c->int32_to_float_fmul_scalar = ff_int32_to_float_fmul_scalar_vfp;
|
||||
c->int32_to_float_fmul_array8 = ff_int32_to_float_fmul_array8_vfp;
|
||||
}
|
||||
|
||||
if (have_neon(cpu_flags)) {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "libavutil/arm/asm.S"
|
||||
|
||||
function ff_h264_idct_add_neon, export=1
|
||||
h264_idct_add_neon_nothumb:
|
||||
vld1.64 {d0-d3}, [r1,:128]
|
||||
vmov.i16 q15, #0
|
||||
|
||||
@@ -73,6 +74,7 @@ function ff_h264_idct_add_neon, export=1
|
||||
endfunc
|
||||
|
||||
function ff_h264_idct_dc_add_neon, export=1
|
||||
h264_idct_dc_add_neon_nothumb:
|
||||
mov r3, #0
|
||||
vld1.16 {d2[],d3[]}, [r1,:16]
|
||||
strh r3, [r1]
|
||||
@@ -113,8 +115,8 @@ function ff_h264_idct_add16_neon, export=1
|
||||
movne lr, #0
|
||||
cmp lr, #0
|
||||
ite ne
|
||||
adrne lr, X(ff_h264_idct_dc_add_neon) + CONFIG_THUMB
|
||||
adreq lr, X(ff_h264_idct_add_neon) + CONFIG_THUMB
|
||||
adrne lr, h264_idct_dc_add_neon_nothumb + CONFIG_THUMB
|
||||
adreq lr, h264_idct_add_neon_nothumb + CONFIG_THUMB
|
||||
blx lr
|
||||
2: subs ip, ip, #1
|
||||
add r1, r1, #32
|
||||
@@ -138,8 +140,8 @@ function ff_h264_idct_add16intra_neon, export=1
|
||||
cmp r8, #0
|
||||
ldrsh r8, [r1]
|
||||
iteet ne
|
||||
adrne lr, X(ff_h264_idct_add_neon) + CONFIG_THUMB
|
||||
adreq lr, X(ff_h264_idct_dc_add_neon) + CONFIG_THUMB
|
||||
adrne lr, h264_idct_add_neon_nothumb + CONFIG_THUMB
|
||||
adreq lr, h264_idct_dc_add_neon_nothumb + CONFIG_THUMB
|
||||
cmpeq r8, #0
|
||||
blxne lr
|
||||
subs ip, ip, #1
|
||||
@@ -166,8 +168,8 @@ function ff_h264_idct_add8_neon, export=1
|
||||
cmp r8, #0
|
||||
ldrsh r8, [r1]
|
||||
iteet ne
|
||||
adrne lr, X(ff_h264_idct_add_neon) + CONFIG_THUMB
|
||||
adreq lr, X(ff_h264_idct_dc_add_neon) + CONFIG_THUMB
|
||||
adrne lr, h264_idct_add_neon_nothumb + CONFIG_THUMB
|
||||
adreq lr, h264_idct_dc_add_neon_nothumb + CONFIG_THUMB
|
||||
cmpeq r8, #0
|
||||
blxne lr
|
||||
add r12, r12, #1
|
||||
@@ -267,6 +269,7 @@ endfunc
|
||||
.endm
|
||||
|
||||
function ff_h264_idct8_add_neon, export=1
|
||||
h264_idct8_add_neon_nothumb:
|
||||
vmov.i16 q3, #0
|
||||
vld1.16 {q8-q9}, [r1,:128]
|
||||
vst1.16 {q3}, [r1,:128]!
|
||||
@@ -328,6 +331,7 @@ function ff_h264_idct8_add_neon, export=1
|
||||
endfunc
|
||||
|
||||
function ff_h264_idct8_dc_add_neon, export=1
|
||||
h264_idct8_dc_add_neon_nothumb:
|
||||
mov r3, #0
|
||||
vld1.16 {d30[],d31[]},[r1,:16]
|
||||
strh r3, [r1]
|
||||
@@ -388,8 +392,8 @@ function ff_h264_idct8_add4_neon, export=1
|
||||
movne lr, #0
|
||||
cmp lr, #0
|
||||
ite ne
|
||||
adrne lr, X(ff_h264_idct8_dc_add_neon) + CONFIG_THUMB
|
||||
adreq lr, X(ff_h264_idct8_add_neon) + CONFIG_THUMB
|
||||
adrne lr, h264_idct8_dc_add_neon_nothumb + CONFIG_THUMB
|
||||
adreq lr, h264_idct8_add_neon_nothumb + CONFIG_THUMB
|
||||
blx lr
|
||||
2: subs r12, r12, #4
|
||||
add r1, r1, #128
|
||||
|
||||
@@ -21,6 +21,6 @@
|
||||
|
||||
#include "libavcodec/hevcdsp.h"
|
||||
|
||||
void ff_hevcdsp_init_neon(HEVCDSPContext *c, const int bit_depth);
|
||||
void ff_hevc_dsp_init_neon(HEVCDSPContext *c, const int bit_depth);
|
||||
|
||||
#endif /* AVCODEC_ARM_HEVCDSP_ARM_H */
|
||||
|
||||
+958
-380
File diff suppressed because it is too large
Load Diff
@@ -19,14 +19,16 @@
|
||||
*/
|
||||
|
||||
#include "libavutil/attributes.h"
|
||||
#include "libavutil/cpu.h"
|
||||
#include "libavutil/arm/cpu.h"
|
||||
|
||||
#include "libavcodec/hevcdsp.h"
|
||||
#include "hevcdsp_arm.h"
|
||||
|
||||
av_cold void ff_hevcdsp_init_arm(HEVCDSPContext *c, const int bit_depth)
|
||||
av_cold void ff_hevc_dsp_init_arm(HEVCDSPContext *c, const int bit_depth)
|
||||
{
|
||||
int cpu_flags = av_get_cpu_flags();
|
||||
|
||||
if (have_neon(cpu_flags))
|
||||
ff_hevcdsp_init_neon(c, bit_depth);
|
||||
ff_hevc_dsp_init_neon(c, bit_depth);
|
||||
}
|
||||
|
||||
@@ -27,21 +27,39 @@ void ff_hevc_v_loop_filter_luma_neon(uint8_t *_pix, ptrdiff_t _stride, int _beta
|
||||
void ff_hevc_h_loop_filter_luma_neon(uint8_t *_pix, ptrdiff_t _stride, int _beta, int *_tc, uint8_t *_no_p, uint8_t *_no_q);
|
||||
void ff_hevc_v_loop_filter_chroma_neon(uint8_t *_pix, ptrdiff_t _stride, int *_tc, uint8_t *_no_p, uint8_t *_no_q);
|
||||
void ff_hevc_h_loop_filter_chroma_neon(uint8_t *_pix, ptrdiff_t _stride, int *_tc, uint8_t *_no_p, uint8_t *_no_q);
|
||||
void ff_hevc_transform_4x4_neon_8(int16_t *coeffs, int col_limit);
|
||||
void ff_hevc_transform_8x8_neon_8(int16_t *coeffs, int col_limit);
|
||||
void ff_hevc_idct_4x4_dc_neon_8(int16_t *coeffs);
|
||||
void ff_hevc_idct_8x8_dc_neon_8(int16_t *coeffs);
|
||||
void ff_hevc_idct_16x16_dc_neon_8(int16_t *coeffs);
|
||||
void ff_hevc_idct_32x32_dc_neon_8(int16_t *coeffs);
|
||||
void ff_hevc_add_residual_4x4_8_neon(uint8_t *_dst, int16_t *coeffs,
|
||||
ptrdiff_t stride);
|
||||
void ff_hevc_add_residual_4x4_10_neon(uint8_t *_dst, int16_t *coeffs,
|
||||
ptrdiff_t stride);
|
||||
void ff_hevc_add_residual_8x8_8_neon(uint8_t *_dst, int16_t *coeffs,
|
||||
ptrdiff_t stride);
|
||||
void ff_hevc_add_residual_8x8_10_neon(uint8_t *_dst, int16_t *coeffs,
|
||||
ptrdiff_t stride);
|
||||
void ff_hevc_add_residual_16x16_8_neon(uint8_t *_dst, int16_t *coeffs,
|
||||
ptrdiff_t stride);
|
||||
void ff_hevc_add_residual_16x16_10_neon(uint8_t *_dst, int16_t *coeffs,
|
||||
ptrdiff_t stride);
|
||||
void ff_hevc_add_residual_32x32_8_neon(uint8_t *_dst, int16_t *coeffs,
|
||||
ptrdiff_t stride);
|
||||
void ff_hevc_add_residual_32x32_10_neon(uint8_t *_dst, int16_t *coeffs,
|
||||
ptrdiff_t stride);
|
||||
void ff_hevc_idct_4x4_dc_8_neon(int16_t *coeffs);
|
||||
void ff_hevc_idct_8x8_dc_8_neon(int16_t *coeffs);
|
||||
void ff_hevc_idct_16x16_dc_8_neon(int16_t *coeffs);
|
||||
void ff_hevc_idct_32x32_dc_8_neon(int16_t *coeffs);
|
||||
void ff_hevc_idct_4x4_dc_10_neon(int16_t *coeffs);
|
||||
void ff_hevc_idct_8x8_dc_10_neon(int16_t *coeffs);
|
||||
void ff_hevc_idct_16x16_dc_10_neon(int16_t *coeffs);
|
||||
void ff_hevc_idct_32x32_dc_10_neon(int16_t *coeffs);
|
||||
void ff_hevc_idct_4x4_8_neon(int16_t *coeffs, int col_limit);
|
||||
void ff_hevc_idct_8x8_8_neon(int16_t *coeffs, int col_limit);
|
||||
void ff_hevc_idct_16x16_8_neon(int16_t *coeffs, int col_limit);
|
||||
void ff_hevc_idct_32x32_8_neon(int16_t *coeffs, int col_limit);
|
||||
void ff_hevc_idct_4x4_10_neon(int16_t *coeffs, int col_limit);
|
||||
void ff_hevc_idct_8x8_10_neon(int16_t *coeffs, int col_limit);
|
||||
void ff_hevc_idct_16x16_10_neon(int16_t *coeffs, int col_limit);
|
||||
void ff_hevc_idct_32x32_10_neon(int16_t *coeffs, int col_limit);
|
||||
void ff_hevc_transform_luma_4x4_neon_8(int16_t *coeffs);
|
||||
void ff_hevc_add_residual_4x4_neon_8(uint8_t *_dst, int16_t *coeffs,
|
||||
ptrdiff_t stride);
|
||||
void ff_hevc_add_residual_8x8_neon_8(uint8_t *_dst, int16_t *coeffs,
|
||||
ptrdiff_t stride);
|
||||
void ff_hevc_add_residual_16x16_neon_8(uint8_t *_dst, int16_t *coeffs,
|
||||
ptrdiff_t stride);
|
||||
void ff_hevc_add_residual_32x32_neon_8(uint8_t *_dst, int16_t *coeffs,
|
||||
ptrdiff_t stride);
|
||||
|
||||
#define PUT_PIXELS(name) \
|
||||
void name(int16_t *dst, uint8_t *src, \
|
||||
@@ -142,7 +160,7 @@ void ff_hevc_put_qpel_bi_neon_wrapper(uint8_t *dst, ptrdiff_t dststride, uint8_t
|
||||
put_hevc_qpel_uw_neon[my][mx](dst, dststride, src, srcstride, width, height, src2, MAX_PB_SIZE);
|
||||
}
|
||||
|
||||
av_cold void ff_hevcdsp_init_neon(HEVCDSPContext *c, const int bit_depth)
|
||||
av_cold void ff_hevc_dsp_init_neon(HEVCDSPContext *c, const int bit_depth)
|
||||
{
|
||||
if (bit_depth == 8) {
|
||||
int x;
|
||||
@@ -150,16 +168,18 @@ av_cold void ff_hevcdsp_init_neon(HEVCDSPContext *c, const int bit_depth)
|
||||
c->hevc_h_loop_filter_luma = ff_hevc_h_loop_filter_luma_neon;
|
||||
c->hevc_v_loop_filter_chroma = ff_hevc_v_loop_filter_chroma_neon;
|
||||
c->hevc_h_loop_filter_chroma = ff_hevc_h_loop_filter_chroma_neon;
|
||||
c->idct[0] = ff_hevc_transform_4x4_neon_8;
|
||||
c->idct[1] = ff_hevc_transform_8x8_neon_8;
|
||||
c->idct_dc[0] = ff_hevc_idct_4x4_dc_neon_8;
|
||||
c->idct_dc[1] = ff_hevc_idct_8x8_dc_neon_8;
|
||||
c->idct_dc[2] = ff_hevc_idct_16x16_dc_neon_8;
|
||||
c->idct_dc[3] = ff_hevc_idct_32x32_dc_neon_8;
|
||||
c->add_residual[0] = ff_hevc_add_residual_4x4_neon_8;
|
||||
c->add_residual[1] = ff_hevc_add_residual_8x8_neon_8;
|
||||
c->add_residual[2] = ff_hevc_add_residual_16x16_neon_8;
|
||||
c->add_residual[3] = ff_hevc_add_residual_32x32_neon_8;
|
||||
c->add_residual[0] = ff_hevc_add_residual_4x4_8_neon;
|
||||
c->add_residual[1] = ff_hevc_add_residual_8x8_8_neon;
|
||||
c->add_residual[2] = ff_hevc_add_residual_16x16_8_neon;
|
||||
c->add_residual[3] = ff_hevc_add_residual_32x32_8_neon;
|
||||
c->idct_dc[0] = ff_hevc_idct_4x4_dc_8_neon;
|
||||
c->idct_dc[1] = ff_hevc_idct_8x8_dc_8_neon;
|
||||
c->idct_dc[2] = ff_hevc_idct_16x16_dc_8_neon;
|
||||
c->idct_dc[3] = ff_hevc_idct_32x32_dc_8_neon;
|
||||
c->idct[0] = ff_hevc_idct_4x4_8_neon;
|
||||
c->idct[1] = ff_hevc_idct_8x8_8_neon;
|
||||
c->idct[2] = ff_hevc_idct_16x16_8_neon;
|
||||
c->idct[3] = ff_hevc_idct_32x32_8_neon;
|
||||
c->transform_4x4_luma = ff_hevc_transform_luma_4x4_neon_8;
|
||||
put_hevc_qpel_neon[1][0] = ff_hevc_put_qpel_v1_neon_8;
|
||||
put_hevc_qpel_neon[2][0] = ff_hevc_put_qpel_v2_neon_8;
|
||||
@@ -221,4 +241,21 @@ av_cold void ff_hevcdsp_init_neon(HEVCDSPContext *c, const int bit_depth)
|
||||
c->put_hevc_qpel_uni[8][0][0] = ff_hevc_put_qpel_uw_pixels_w48_neon_8;
|
||||
c->put_hevc_qpel_uni[9][0][0] = ff_hevc_put_qpel_uw_pixels_w64_neon_8;
|
||||
}
|
||||
|
||||
if (bit_depth == 10) {
|
||||
c->add_residual[0] = ff_hevc_add_residual_4x4_10_neon;
|
||||
c->add_residual[1] = ff_hevc_add_residual_8x8_10_neon;
|
||||
c->add_residual[2] = ff_hevc_add_residual_16x16_10_neon;
|
||||
c->add_residual[3] = ff_hevc_add_residual_32x32_10_neon;
|
||||
|
||||
c->idct_dc[0] = ff_hevc_idct_4x4_dc_10_neon;
|
||||
c->idct_dc[1] = ff_hevc_idct_8x8_dc_10_neon;
|
||||
c->idct_dc[2] = ff_hevc_idct_16x16_dc_10_neon;
|
||||
c->idct_dc[3] = ff_hevc_idct_32x32_dc_10_neon;
|
||||
|
||||
c->idct[0] = ff_hevc_idct_4x4_10_neon;
|
||||
c->idct[1] = ff_hevc_idct_8x8_10_neon;
|
||||
c->idct[2] = ff_hevc_idct_16x16_10_neon;
|
||||
c->idct[3] = ff_hevc_idct_32x32_10_neon;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,11 +336,11 @@ function ff_sbr_hf_apply_noise_0_neon, export=1
|
||||
vld1.32 {d0}, [r0,:64]
|
||||
vld1.32 {d6}, [lr,:64]
|
||||
vld1.32 {d2[]}, [r1,:32]!
|
||||
vld1.32 {d3[]}, [r2,:32]!
|
||||
vld1.32 {d18[]}, [r2,:32]!
|
||||
vceq.f32 d4, d2, #0
|
||||
veor d2, d2, d3
|
||||
vmov d1, d0
|
||||
vmla.f32 d0, d6, d3
|
||||
vmla.f32 d0, d6, d18
|
||||
vadd.f32 s2, s2, s4
|
||||
vbif d0, d1, d4
|
||||
vst1.32 {d0}, [r0,:64]!
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
#include "libavcodec/vc1dsp.h"
|
||||
#include "vc1dsp.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
void ff_vc1_inv_trans_8x8_neon(int16_t *block);
|
||||
void ff_vc1_inv_trans_4x8_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block);
|
||||
void ff_vc1_inv_trans_8x4_neon(uint8_t *dest, ptrdiff_t stride, int16_t *block);
|
||||
@@ -95,7 +93,6 @@ av_cold void ff_vc1dsp_init_neon(VC1DSPContext *dsp)
|
||||
dsp->vc1_inv_trans_4x4_dc = ff_vc1_inv_trans_4x4_dc_neon;
|
||||
|
||||
dsp->put_vc1_mspel_pixels_tab[1][ 0] = ff_put_pixels8x8_neon;
|
||||
if (HAVE_AS_DN_DIRECTIVE) {
|
||||
FN_ASSIGN(1, 0);
|
||||
FN_ASSIGN(2, 0);
|
||||
FN_ASSIGN(3, 0);
|
||||
@@ -114,7 +111,6 @@ av_cold void ff_vc1dsp_init_neon(VC1DSPContext *dsp)
|
||||
FN_ASSIGN(1, 3);
|
||||
FN_ASSIGN(2, 3);
|
||||
FN_ASSIGN(3, 3);
|
||||
}
|
||||
|
||||
dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = ff_put_vc1_chroma_mc8_neon;
|
||||
dsp->avg_no_rnd_vc1_chroma_pixels_tab[0] = ff_avg_vc1_chroma_mc8_neon;
|
||||
|
||||
@@ -663,7 +663,6 @@ function ff_vc1_inv_trans_4x4_neon, export=1
|
||||
bx lr
|
||||
endfunc
|
||||
|
||||
#if HAVE_AS_DN_DIRECTIVE
|
||||
@ The absolute value of multiplication constants from vc1_mspel_filter and vc1_mspel_{ver,hor}_filter_16bits.
|
||||
@ The sign is embedded in the code below that carries out the multiplication (mspel_filter{,.16}).
|
||||
#define MSPEL_MODE_1_MUL_CONSTANTS 4 53 18 3
|
||||
@@ -689,22 +688,18 @@ endfunc
|
||||
|
||||
@ Setup constants in registers for a subsequent use of mspel_filter{,.16}.
|
||||
.macro mspel_constants typesize reg_a reg_b reg_c reg_d filter_a filter_b filter_c filter_d reg_add filter_add_register
|
||||
@ Define double-word register aliases. Typesize should be i8 or i16.
|
||||
ra .dn \reg_a\().\typesize
|
||||
rb .dn \reg_b\().\typesize
|
||||
rc .dn \reg_c\().\typesize
|
||||
rd .dn \reg_d\().\typesize
|
||||
@ Typesize should be i8 or i16.
|
||||
|
||||
@ Only set the register if the value is not 1 and unique
|
||||
.if \filter_a != 1
|
||||
vmov ra, #\filter_a @ ra = filter_a
|
||||
vmov.\typesize \reg_a, #\filter_a @ reg_a = filter_a
|
||||
.endif
|
||||
vmov rb, #\filter_b @ rb = filter_b
|
||||
vmov.\typesize \reg_b, #\filter_b @ reg_b = filter_b
|
||||
.if \filter_b != \filter_c
|
||||
vmov rc, #\filter_c @ rc = filter_c
|
||||
vmov.\typesize \reg_c, #\filter_c @ reg_c = filter_c
|
||||
.endif
|
||||
.if \filter_d != 1
|
||||
vmov rd, #\filter_d @ rd = filter_d
|
||||
vmov.\typesize \reg_d, #\filter_d @ reg_d = filter_d
|
||||
.endif
|
||||
@ vdup to double the size of typesize
|
||||
.ifc \typesize,i8
|
||||
@@ -712,11 +707,6 @@ endfunc
|
||||
.else
|
||||
vdup.32 \reg_add, \filter_add_register @ reg_add = filter_add_register
|
||||
.endif
|
||||
|
||||
.unreq ra
|
||||
.unreq rb
|
||||
.unreq rc
|
||||
.unreq rd
|
||||
.endm
|
||||
|
||||
@ After mspel_constants has been used, do the filtering.
|
||||
@@ -987,7 +977,6 @@ PUT_VC1_MSPEL_MC_V_ONLY(2)
|
||||
PUT_VC1_MSPEL_MC_V_ONLY(3)
|
||||
|
||||
#undef PUT_VC1_MSPEL_MC_V_ONLY
|
||||
#endif
|
||||
|
||||
function ff_put_pixels8x8_neon, export=1
|
||||
vld1.64 {d0}, [r1], r2
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* audio conversion
|
||||
* Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||
*
|
||||
* 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
|
||||
* audio conversion
|
||||
* @author Michael Niedermayer <michaelni@gmx.at>
|
||||
*/
|
||||
|
||||
#include "libavutil/avstring.h"
|
||||
#include "libavutil/common.h"
|
||||
#include "libavutil/libm.h"
|
||||
#include "libavutil/samplefmt.h"
|
||||
#include "avcodec.h"
|
||||
#include "audioconvert.h"
|
||||
|
||||
#if FF_API_AUDIO_CONVERT
|
||||
|
||||
struct AVAudioConvert {
|
||||
int in_channels, out_channels;
|
||||
int fmt_pair;
|
||||
};
|
||||
|
||||
AVAudioConvert *av_audio_convert_alloc(enum AVSampleFormat out_fmt, int out_channels,
|
||||
enum AVSampleFormat in_fmt, int in_channels,
|
||||
const float *matrix, int flags)
|
||||
{
|
||||
AVAudioConvert *ctx;
|
||||
if (in_channels!=out_channels)
|
||||
return NULL; /* FIXME: not supported */
|
||||
ctx = av_malloc(sizeof(AVAudioConvert));
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
ctx->in_channels = in_channels;
|
||||
ctx->out_channels = out_channels;
|
||||
ctx->fmt_pair = out_fmt + AV_SAMPLE_FMT_NB*in_fmt;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void av_audio_convert_free(AVAudioConvert *ctx)
|
||||
{
|
||||
av_free(ctx);
|
||||
}
|
||||
|
||||
int av_audio_convert(AVAudioConvert *ctx,
|
||||
void * const out[6], const int out_stride[6],
|
||||
const void * const in[6], const int in_stride[6], int len)
|
||||
{
|
||||
int ch;
|
||||
|
||||
//FIXME optimize common cases
|
||||
|
||||
for(ch=0; ch<ctx->out_channels; ch++){
|
||||
const int is= in_stride[ch];
|
||||
const int os= out_stride[ch];
|
||||
const uint8_t *pi= in[ch];
|
||||
uint8_t *po= out[ch];
|
||||
uint8_t *end= po + os*len;
|
||||
if(!out[ch])
|
||||
continue;
|
||||
|
||||
#define CONV(ofmt, otype, ifmt, expr)\
|
||||
if(ctx->fmt_pair == ofmt + AV_SAMPLE_FMT_NB*ifmt){\
|
||||
do{\
|
||||
*(otype*)po = expr; pi += is; po += os;\
|
||||
}while(po < end);\
|
||||
}
|
||||
|
||||
//FIXME put things below under ifdefs so we do not waste space for cases no codec will need
|
||||
//FIXME rounding ?
|
||||
|
||||
CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_U8 , *(const uint8_t*)pi)
|
||||
else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)<<8)
|
||||
else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)<<24)
|
||||
else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)*(1.0 / (1<<7)))
|
||||
else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_U8 , (*(const uint8_t*)pi - 0x80)*(1.0 / (1<<7)))
|
||||
else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_S16, (*(const int16_t*)pi>>8) + 0x80)
|
||||
else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S16, *(const int16_t*)pi)
|
||||
else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S16, *(const int16_t*)pi<<16)
|
||||
else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_S16, *(const int16_t*)pi*(1.0 / (1<<15)))
|
||||
else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_S16, *(const int16_t*)pi*(1.0 / (1<<15)))
|
||||
else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_S32, (*(const int32_t*)pi>>24) + 0x80)
|
||||
else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_S32, *(const int32_t*)pi>>16)
|
||||
else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_S32, *(const int32_t*)pi)
|
||||
else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_S32, *(const int32_t*)pi*(1.0 / (1U<<31)))
|
||||
else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_S32, *(const int32_t*)pi*(1.0 / (1U<<31)))
|
||||
else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8( lrintf(*(const float*)pi * (1<<7)) + 0x80))
|
||||
else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16( lrintf(*(const float*)pi * (1<<15))))
|
||||
else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float*)pi * (1U<<31))))
|
||||
else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_FLT, *(const float*)pi)
|
||||
else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_FLT, *(const float*)pi)
|
||||
else CONV(AV_SAMPLE_FMT_U8 , uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8( lrint(*(const double*)pi * (1<<7)) + 0x80))
|
||||
else CONV(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16( lrint(*(const double*)pi * (1<<15))))
|
||||
else CONV(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double*)pi * (1U<<31))))
|
||||
else CONV(AV_SAMPLE_FMT_FLT, float , AV_SAMPLE_FMT_DBL, *(const double*)pi)
|
||||
else CONV(AV_SAMPLE_FMT_DBL, double , AV_SAMPLE_FMT_DBL, *(const double*)pi)
|
||||
else return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* FF_API_AUDIO_CONVERT */
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* audio conversion
|
||||
* Copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at>
|
||||
* Copyright (c) 2008 Peter Ross
|
||||
*
|
||||
* 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_AUDIOCONVERT_H
|
||||
#define AVCODEC_AUDIOCONVERT_H
|
||||
|
||||
#include "version.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Audio format conversion routines
|
||||
* This interface is deprecated and will be dropped in a future
|
||||
* version. You should use the libswresample library instead.
|
||||
*/
|
||||
|
||||
#if FF_API_AUDIO_CONVERT
|
||||
|
||||
#include "libavutil/cpu.h"
|
||||
#include "avcodec.h"
|
||||
#include "libavutil/channel_layout.h"
|
||||
|
||||
struct AVAudioConvert;
|
||||
typedef struct AVAudioConvert AVAudioConvert;
|
||||
|
||||
/**
|
||||
* Create an audio sample format converter context
|
||||
* @param out_fmt Output sample format
|
||||
* @param out_channels Number of output channels
|
||||
* @param in_fmt Input sample format
|
||||
* @param in_channels Number of input channels
|
||||
* @param[in] matrix Channel mixing matrix (of dimension in_channel*out_channels). Set to NULL to ignore.
|
||||
* @param flags See AV_CPU_FLAG_xx
|
||||
* @return NULL on error
|
||||
* @deprecated See libswresample
|
||||
*/
|
||||
|
||||
attribute_deprecated
|
||||
AVAudioConvert *av_audio_convert_alloc(enum AVSampleFormat out_fmt, int out_channels,
|
||||
enum AVSampleFormat in_fmt, int in_channels,
|
||||
const float *matrix, int flags);
|
||||
|
||||
/**
|
||||
* Free audio sample format converter context
|
||||
* @deprecated See libswresample
|
||||
*/
|
||||
|
||||
attribute_deprecated
|
||||
void av_audio_convert_free(AVAudioConvert *ctx);
|
||||
|
||||
/**
|
||||
* Convert between audio sample formats
|
||||
* @param[in] out array of output buffers for each channel. set to NULL to ignore processing of the given channel.
|
||||
* @param[in] out_stride distance between consecutive output samples (measured in bytes)
|
||||
* @param[in] in array of input buffers for each channel
|
||||
* @param[in] in_stride distance between consecutive input samples (measured in bytes)
|
||||
* @param len length of audio frame size (measured in samples)
|
||||
* @deprecated See libswresample
|
||||
*/
|
||||
|
||||
attribute_deprecated
|
||||
int av_audio_convert(AVAudioConvert *ctx,
|
||||
void * const out[6], const int out_stride[6],
|
||||
const void * const in[6], const int in_stride[6], int len);
|
||||
|
||||
#endif /* FF_API_AUDIO_CONVERT */
|
||||
|
||||
#endif /* AVCODEC_AUDIOCONVERT_H */
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "avcodec.h"
|
||||
#include "ac3_parser.h"
|
||||
#include "ac3_parser_internal.h"
|
||||
#include "bytestream.h"
|
||||
#include "internal.h"
|
||||
#include "mpegaudiodecheader.h"
|
||||
@@ -350,10 +350,10 @@ static av_cold int ffat_create_decoder(AVCodecContext *avctx, AVPacket *pkt)
|
||||
} else if (pkt && pkt->size >= 7 &&
|
||||
(avctx->codec_id == AV_CODEC_ID_AC3 ||
|
||||
avctx->codec_id == AV_CODEC_ID_EAC3)) {
|
||||
AC3HeaderInfo hdr, *phdr = &hdr;
|
||||
AC3HeaderInfo hdr;
|
||||
GetBitContext gbc;
|
||||
init_get_bits(&gbc, pkt->data, pkt->size);
|
||||
if (avpriv_ac3_parse_header(&gbc, &phdr) < 0)
|
||||
if (ff_ac3_parse_header(&gbc, &hdr) < 0)
|
||||
return AVERROR_INVALIDDATA;
|
||||
in_format.mSampleRate = hdr.sample_rate;
|
||||
in_format.mChannelsPerFrame = hdr.channels;
|
||||
@@ -597,6 +597,7 @@ static av_cold int ffat_close_decoder(AVCodecContext *avctx)
|
||||
.bsfs = bsf_name, \
|
||||
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY, \
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, \
|
||||
.wrapper_name = "at", \
|
||||
};
|
||||
|
||||
FFAT_DEC(aac, AV_CODEC_ID_AAC, "aac_adtstoasc")
|
||||
|
||||
@@ -48,6 +48,8 @@ typedef struct ATDecodeContext {
|
||||
AudioFrameQueue afq;
|
||||
int eof;
|
||||
int frame_size;
|
||||
|
||||
AVFrame* encoding_frame;
|
||||
} ATDecodeContext;
|
||||
|
||||
static UInt32 ffat_get_format_id(enum AVCodecID codec, int profile)
|
||||
@@ -442,6 +444,10 @@ static av_cold int ffat_init_encoder(AVCodecContext *avctx)
|
||||
|
||||
ff_af_queue_init(avctx, &at->afq);
|
||||
|
||||
at->encoding_frame = av_frame_alloc();
|
||||
if (!at->encoding_frame)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -453,6 +459,7 @@ static OSStatus ffat_encode_callback(AudioConverterRef converter, UInt32 *nb_pac
|
||||
AVCodecContext *avctx = inctx;
|
||||
ATDecodeContext *at = avctx->priv_data;
|
||||
AVFrame *frame;
|
||||
int ret;
|
||||
|
||||
if (!at->frame_queue.available) {
|
||||
if (at->eof) {
|
||||
@@ -475,6 +482,13 @@ static OSStatus ffat_encode_callback(AudioConverterRef converter, UInt32 *nb_pac
|
||||
if (*nb_packets > frame->nb_samples)
|
||||
*nb_packets = frame->nb_samples;
|
||||
|
||||
av_frame_unref(at->encoding_frame);
|
||||
ret = av_frame_ref(at->encoding_frame, frame);
|
||||
if (ret < 0) {
|
||||
*nb_packets = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ff_bufqueue_add(avctx, &at->used_frame_queue, frame);
|
||||
|
||||
return 0;
|
||||
@@ -565,6 +579,7 @@ static av_cold int ffat_close_encoder(AVCodecContext *avctx)
|
||||
ff_bufqueue_discard_all(&at->frame_queue);
|
||||
ff_bufqueue_discard_all(&at->used_frame_queue);
|
||||
ff_af_queue_close(&at->afq);
|
||||
av_frame_free(&at->encoding_frame);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -619,6 +634,7 @@ static const AVOption options[] = {
|
||||
}, \
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, \
|
||||
.profiles = PROFILES, \
|
||||
.wrapper_name = "at", \
|
||||
};
|
||||
|
||||
static const uint64_t aac_at_channel_layouts[] = {
|
||||
|
||||
+292
-679
File diff suppressed because it is too large
Load Diff
@@ -48,19 +48,10 @@ static const AVOption avdct_options[] = {
|
||||
{"simplemmx", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEMMX }, INT_MIN, INT_MAX, V|E|D, "idct"},
|
||||
{"arm", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_ARM }, INT_MIN, INT_MAX, V|E|D, "idct"},
|
||||
{"altivec", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_ALTIVEC }, INT_MIN, INT_MAX, V|E|D, "idct"},
|
||||
#if FF_API_ARCH_SH4
|
||||
{"sh4", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SH4 }, INT_MIN, INT_MAX, V|E|D, "idct"},
|
||||
#endif
|
||||
{"simplearm", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARM }, INT_MIN, INT_MAX, V|E|D, "idct"},
|
||||
{"simplearmv5te", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARMV5TE }, INT_MIN, INT_MAX, V|E|D, "idct"},
|
||||
{"simplearmv6", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEARMV6 }, INT_MIN, INT_MAX, V|E|D, "idct"},
|
||||
{"simpleneon", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLENEON }, INT_MIN, INT_MAX, V|E|D, "idct"},
|
||||
#if FF_API_ARCH_ALPHA
|
||||
{"simplealpha", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_SIMPLEALPHA }, INT_MIN, INT_MAX, V|E|D, "idct"},
|
||||
#endif
|
||||
#if FF_API_UNUSED_MEMBERS
|
||||
{"ipp", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_IPP }, INT_MIN, INT_MAX, V|E|D, "idct"},
|
||||
#endif
|
||||
{"xvid", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_XVID }, INT_MIN, INT_MAX, V|E|D, "idct"},
|
||||
{"xvidmmx", "experimental / for debugging", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_XVID }, INT_MIN, INT_MAX, V|E|D, "idct"},
|
||||
{"faani", "floating point AAN IDCT (experimental / for debugging)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_IDCT_FAAN }, INT_MIN, INT_MAX, V|D|E, "idct"},
|
||||
|
||||
@@ -479,34 +479,6 @@ int av_packet_split_side_data(AVPacket *pkt){
|
||||
}
|
||||
#endif
|
||||
|
||||
#if FF_API_MERGE_SD
|
||||
int ff_packet_split_and_drop_side_data(AVPacket *pkt){
|
||||
if (!pkt->side_data_elems && pkt->size >12 && AV_RB64(pkt->data + pkt->size - 8) == FF_MERGE_MARKER){
|
||||
int i;
|
||||
unsigned int size;
|
||||
uint8_t *p;
|
||||
|
||||
p = pkt->data + pkt->size - 8 - 5;
|
||||
for (i=1; ; i++){
|
||||
size = AV_RB32(p);
|
||||
if (size>INT_MAX - 5 || p - pkt->data < size)
|
||||
return 0;
|
||||
if (p[4]&128)
|
||||
break;
|
||||
if (p - pkt->data < size + 5)
|
||||
return 0;
|
||||
p-= size+5;
|
||||
if (i > AV_PKT_DATA_NB)
|
||||
return 0;
|
||||
}
|
||||
pkt->size = p - pkt->data - size;
|
||||
av_assert0(pkt->size >= 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t *av_packet_pack_dictionary(AVDictionary *dict, int *size)
|
||||
{
|
||||
AVDictionaryEntry *t = NULL;
|
||||
|
||||
@@ -168,7 +168,6 @@ AVCodec ff_avrn_decoder = {
|
||||
.init = init,
|
||||
.close = end,
|
||||
.decode = decode_frame,
|
||||
.capabilities = AV_CODEC_CAP_DR1,
|
||||
.max_lowres = 3,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
|
||||
};
|
||||
|
||||
+29
-14
@@ -601,17 +601,16 @@ static inline int binkb_get_value(BinkContext *c, int bundle_num)
|
||||
* @param quant_matrices quantization matrices
|
||||
* @return 0 for success, negative value in other cases
|
||||
*/
|
||||
static int read_dct_coeffs(GetBitContext *gb, int32_t block[64], const uint8_t *scan,
|
||||
const int32_t quant_matrices[16][64], int q)
|
||||
static int read_dct_coeffs(GetBitContext *gb, int32_t block[64],
|
||||
const uint8_t *scan, int *coef_count_,
|
||||
int coef_idx[64], int q)
|
||||
{
|
||||
int coef_list[128];
|
||||
int mode_list[128];
|
||||
int i, t, bits, ccoef, mode, sign;
|
||||
int list_start = 64, list_end = 64, list_pos;
|
||||
int coef_count = 0;
|
||||
int coef_idx[64];
|
||||
int quant_idx;
|
||||
const int32_t *quant;
|
||||
|
||||
coef_list[list_end] = 4; mode_list[list_end++] = 0;
|
||||
coef_list[list_end] = 24; mode_list[list_end++] = 0;
|
||||
@@ -690,15 +689,21 @@ static int read_dct_coeffs(GetBitContext *gb, int32_t block[64], const uint8_t *
|
||||
}
|
||||
}
|
||||
|
||||
quant = quant_matrices[quant_idx];
|
||||
*coef_count_ = coef_count;
|
||||
|
||||
return quant_idx;
|
||||
}
|
||||
|
||||
static void unquantize_dct_coeffs(int32_t block[64], const int32_t quant[64],
|
||||
int coef_count, int coef_idx[64],
|
||||
const uint8_t *scan)
|
||||
{
|
||||
int i;
|
||||
block[0] = (block[0] * quant[0]) >> 11;
|
||||
for (i = 0; i < coef_count; i++) {
|
||||
int idx = coef_idx[i];
|
||||
block[scan[idx]] = (block[scan[idx]] * quant[idx]) >> 11;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -817,7 +822,7 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb,
|
||||
LOCAL_ALIGNED_16(int32_t, dctblock, [64]);
|
||||
int coordmap[64];
|
||||
int ybias = is_key ? -15 : 0;
|
||||
int qp;
|
||||
int qp, quant_idx, coef_count, coef_idx[64];
|
||||
|
||||
const int stride = frame->linesize[plane_idx];
|
||||
int bw = is_chroma ? (c->avctx->width + 15) >> 4 : (c->avctx->width + 7) >> 3;
|
||||
@@ -872,7 +877,9 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb,
|
||||
memset(dctblock, 0, sizeof(*dctblock) * 64);
|
||||
dctblock[0] = binkb_get_value(c, BINKB_SRC_INTRA_DC);
|
||||
qp = binkb_get_value(c, BINKB_SRC_INTRA_Q);
|
||||
read_dct_coeffs(gb, dctblock, bink_scan, (const int32_t (*)[64])binkb_intra_quant, qp);
|
||||
if ((quant_idx = read_dct_coeffs(gb, dctblock, bink_scan, &coef_count, coef_idx, qp)) < 0)
|
||||
return quant_idx;
|
||||
unquantize_dct_coeffs(dctblock, binkb_intra_quant[quant_idx], coef_count, coef_idx, bink_scan);
|
||||
c->binkdsp.idct_put(dst, stride, dctblock);
|
||||
break;
|
||||
case 3:
|
||||
@@ -905,7 +912,9 @@ static int binkb_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb,
|
||||
memset(dctblock, 0, sizeof(*dctblock) * 64);
|
||||
dctblock[0] = binkb_get_value(c, BINKB_SRC_INTER_DC);
|
||||
qp = binkb_get_value(c, BINKB_SRC_INTER_Q);
|
||||
read_dct_coeffs(gb, dctblock, bink_scan, (const int32_t (*)[64])binkb_inter_quant, qp);
|
||||
if ((quant_idx = read_dct_coeffs(gb, dctblock, bink_scan, &coef_count, coef_idx, qp)) < 0)
|
||||
return quant_idx;
|
||||
unquantize_dct_coeffs(dctblock, binkb_inter_quant[quant_idx], coef_count, coef_idx, bink_scan);
|
||||
c->binkdsp.idct_add(dst, stride, dctblock);
|
||||
break;
|
||||
case 5:
|
||||
@@ -979,7 +988,7 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb,
|
||||
LOCAL_ALIGNED_32(int16_t, block, [64]);
|
||||
LOCAL_ALIGNED_16(uint8_t, ublock, [64]);
|
||||
LOCAL_ALIGNED_16(int32_t, dctblock, [64]);
|
||||
int coordmap[64];
|
||||
int coordmap[64], quant_idx, coef_count, coef_idx[64];
|
||||
|
||||
const int stride = frame->linesize[plane_idx];
|
||||
int bw = is_chroma ? (c->avctx->width + 15) >> 4 : (c->avctx->width + 7) >> 3;
|
||||
@@ -1065,7 +1074,9 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb,
|
||||
case INTRA_BLOCK:
|
||||
memset(dctblock, 0, sizeof(*dctblock) * 64);
|
||||
dctblock[0] = get_value(c, BINK_SRC_INTRA_DC);
|
||||
read_dct_coeffs(gb, dctblock, bink_scan, bink_intra_quant, -1);
|
||||
if ((quant_idx = read_dct_coeffs(gb, dctblock, bink_scan, &coef_count, coef_idx, -1)) < 0)
|
||||
return quant_idx;
|
||||
unquantize_dct_coeffs(dctblock, bink_intra_quant[quant_idx], coef_count, coef_idx, bink_scan);
|
||||
c->binkdsp.idct_put(ublock, 8, dctblock);
|
||||
break;
|
||||
case FILL_BLOCK:
|
||||
@@ -1138,7 +1149,9 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb,
|
||||
case INTRA_BLOCK:
|
||||
memset(dctblock, 0, sizeof(*dctblock) * 64);
|
||||
dctblock[0] = get_value(c, BINK_SRC_INTRA_DC);
|
||||
read_dct_coeffs(gb, dctblock, bink_scan, bink_intra_quant, -1);
|
||||
if ((quant_idx = read_dct_coeffs(gb, dctblock, bink_scan, &coef_count, coef_idx, -1)) < 0)
|
||||
return quant_idx;
|
||||
unquantize_dct_coeffs(dctblock, bink_intra_quant[quant_idx], coef_count, coef_idx, bink_scan);
|
||||
c->binkdsp.idct_put(dst, stride, dctblock);
|
||||
break;
|
||||
case FILL_BLOCK:
|
||||
@@ -1152,7 +1165,9 @@ static int bink_decode_plane(BinkContext *c, AVFrame *frame, GetBitContext *gb,
|
||||
return ret;
|
||||
memset(dctblock, 0, sizeof(*dctblock) * 64);
|
||||
dctblock[0] = get_value(c, BINK_SRC_INTER_DC);
|
||||
read_dct_coeffs(gb, dctblock, bink_scan, bink_inter_quant, -1);
|
||||
if ((quant_idx = read_dct_coeffs(gb, dctblock, bink_scan, &coef_count, coef_idx, -1)) < 0)
|
||||
return quant_idx;
|
||||
unquantize_dct_coeffs(dctblock, bink_inter_quant[quant_idx], coef_count, coef_idx, bink_scan);
|
||||
c->binkdsp.idct_add(dst, stride, dctblock);
|
||||
break;
|
||||
case PATTERN_BLOCK:
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#if FF_API_OLD_BSF
|
||||
FF_DISABLE_DEPRECATION_WARNINGS
|
||||
|
||||
AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f)
|
||||
const AVBitStreamFilter *av_bitstream_filter_next(const AVBitStreamFilter *f)
|
||||
{
|
||||
const AVBitStreamFilter *filter = NULL;
|
||||
void *opaque = NULL;
|
||||
@@ -131,7 +131,7 @@ int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
|
||||
return ret;
|
||||
}
|
||||
|
||||
pkt.data = buf;
|
||||
pkt.data = (uint8_t *)buf;
|
||||
pkt.size = buf_size;
|
||||
|
||||
ret = av_bsf_send_packet(priv->ctx, &pkt);
|
||||
|
||||
@@ -29,18 +29,23 @@ extern const AVBitStreamFilter ff_chomp_bsf;
|
||||
extern const AVBitStreamFilter ff_dump_extradata_bsf;
|
||||
extern const AVBitStreamFilter ff_dca_core_bsf;
|
||||
extern const AVBitStreamFilter ff_extract_extradata_bsf;
|
||||
extern const AVBitStreamFilter ff_h264_metadata_bsf;
|
||||
extern const AVBitStreamFilter ff_h264_mp4toannexb_bsf;
|
||||
extern const AVBitStreamFilter ff_h264_redundant_pps_bsf;
|
||||
extern const AVBitStreamFilter ff_hevc_metadata_bsf;
|
||||
extern const AVBitStreamFilter ff_hevc_mp4toannexb_bsf;
|
||||
extern const AVBitStreamFilter ff_imx_dump_header_bsf;
|
||||
extern const AVBitStreamFilter ff_mjpeg2jpeg_bsf;
|
||||
extern const AVBitStreamFilter ff_mjpega_dump_header_bsf;
|
||||
extern const AVBitStreamFilter ff_mp3_header_decompress_bsf;
|
||||
extern const AVBitStreamFilter ff_mpeg2_metadata_bsf;
|
||||
extern const AVBitStreamFilter ff_mpeg4_unpack_bframes_bsf;
|
||||
extern const AVBitStreamFilter ff_mov2textsub_bsf;
|
||||
extern const AVBitStreamFilter ff_noise_bsf;
|
||||
extern const AVBitStreamFilter ff_null_bsf;
|
||||
extern const AVBitStreamFilter ff_remove_extradata_bsf;
|
||||
extern const AVBitStreamFilter ff_text2movsub_bsf;
|
||||
extern const AVBitStreamFilter ff_trace_headers_bsf;
|
||||
extern const AVBitStreamFilter ff_vp9_raw_reorder_bsf;
|
||||
extern const AVBitStreamFilter ff_vp9_superframe_bsf;
|
||||
extern const AVBitStreamFilter ff_vp9_superframe_split_bsf;
|
||||
|
||||
@@ -33,8 +33,8 @@ typedef void (*op_fill_func)(uint8_t *block /* align width (8 or 16) */,
|
||||
uint8_t value, ptrdiff_t line_size, int h);
|
||||
|
||||
typedef struct BlockDSPContext {
|
||||
void (*clear_block)(int16_t *block /* align 16 */);
|
||||
void (*clear_blocks)(int16_t *blocks /* align 16 */);
|
||||
void (*clear_block)(int16_t *block /* align 32 */);
|
||||
void (*clear_blocks)(int16_t *blocks /* align 32 */);
|
||||
|
||||
op_fill_func fill_block_tab[2];
|
||||
} BlockDSPContext;
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@
|
||||
#include "cabac.h"
|
||||
#include "cabac_functions.h"
|
||||
|
||||
const uint8_t ff_h264_cabac_tables[512 + 4*2*64 + 4*64 + 63] = {
|
||||
DECLARE_ASM_ALIGNED(1, const uint8_t, ff_h264_cabac_tables)[512 + 4*2*64 + 4*64 + 63] = {
|
||||
9,8,7,7,6,6,6,6,5,5,5,5,5,5,5,5,
|
||||
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
|
||||
|
||||
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
* 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 <string.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "libavutil/avassert.h"
|
||||
#include "libavutil/common.h"
|
||||
|
||||
#include "cbs.h"
|
||||
#include "cbs_internal.h"
|
||||
|
||||
|
||||
static const CodedBitstreamType *cbs_type_table[] = {
|
||||
#if CONFIG_CBS_H264
|
||||
&ff_cbs_type_h264,
|
||||
#endif
|
||||
#if CONFIG_CBS_H265
|
||||
&ff_cbs_type_h265,
|
||||
#endif
|
||||
#if CONFIG_CBS_MPEG2
|
||||
&ff_cbs_type_mpeg2,
|
||||
#endif
|
||||
};
|
||||
|
||||
int ff_cbs_init(CodedBitstreamContext **ctx_ptr,
|
||||
enum AVCodecID codec_id, void *log_ctx)
|
||||
{
|
||||
CodedBitstreamContext *ctx;
|
||||
const CodedBitstreamType *type;
|
||||
int i;
|
||||
|
||||
type = NULL;
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(cbs_type_table); i++) {
|
||||
if (cbs_type_table[i]->codec_id == codec_id) {
|
||||
type = cbs_type_table[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!type)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
ctx = av_mallocz(sizeof(*ctx));
|
||||
if (!ctx)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
ctx->log_ctx = log_ctx;
|
||||
ctx->codec = type;
|
||||
|
||||
ctx->priv_data = av_mallocz(ctx->codec->priv_data_size);
|
||||
if (!ctx->priv_data) {
|
||||
av_freep(&ctx);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
ctx->decompose_unit_types = NULL;
|
||||
|
||||
ctx->trace_enable = 0;
|
||||
ctx->trace_level = AV_LOG_TRACE;
|
||||
|
||||
*ctx_ptr = ctx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ff_cbs_close(CodedBitstreamContext **ctx_ptr)
|
||||
{
|
||||
CodedBitstreamContext *ctx = *ctx_ptr;
|
||||
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
if (ctx->codec && ctx->codec->close)
|
||||
ctx->codec->close(ctx);
|
||||
|
||||
av_freep(&ctx->priv_data);
|
||||
av_freep(ctx_ptr);
|
||||
}
|
||||
|
||||
static void cbs_unit_uninit(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamUnit *unit)
|
||||
{
|
||||
if (ctx->codec->free_unit && unit->content && !unit->content_external)
|
||||
ctx->codec->free_unit(unit);
|
||||
|
||||
av_freep(&unit->data);
|
||||
unit->data_size = 0;
|
||||
unit->data_bit_padding = 0;
|
||||
}
|
||||
|
||||
void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < frag->nb_units; i++)
|
||||
cbs_unit_uninit(ctx, &frag->units[i]);
|
||||
av_freep(&frag->units);
|
||||
frag->nb_units = 0;
|
||||
|
||||
av_freep(&frag->data);
|
||||
frag->data_size = 0;
|
||||
frag->data_bit_padding = 0;
|
||||
}
|
||||
|
||||
static int cbs_read_fragment_content(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag)
|
||||
{
|
||||
int err, i, j;
|
||||
|
||||
for (i = 0; i < frag->nb_units; i++) {
|
||||
if (ctx->decompose_unit_types) {
|
||||
for (j = 0; j < ctx->nb_decompose_unit_types; j++) {
|
||||
if (ctx->decompose_unit_types[j] == frag->units[i].type)
|
||||
break;
|
||||
}
|
||||
if (j >= ctx->nb_decompose_unit_types)
|
||||
continue;
|
||||
}
|
||||
|
||||
err = ctx->codec->read_unit(ctx, &frag->units[i]);
|
||||
if (err == AVERROR(ENOSYS)) {
|
||||
av_log(ctx->log_ctx, AV_LOG_WARNING,
|
||||
"Decomposition unimplemented for unit %d "
|
||||
"(type %"PRIu32").\n", i, frag->units[i].type);
|
||||
} else if (err < 0) {
|
||||
av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to read unit %d "
|
||||
"(type %"PRIu32").\n", i, frag->units[i].type);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_cbs_read_extradata(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag,
|
||||
const AVCodecParameters *par)
|
||||
{
|
||||
int err;
|
||||
|
||||
memset(frag, 0, sizeof(*frag));
|
||||
|
||||
frag->data = par->extradata;
|
||||
frag->data_size = par->extradata_size;
|
||||
|
||||
err = ctx->codec->split_fragment(ctx, frag, 1);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
frag->data = NULL;
|
||||
frag->data_size = 0;
|
||||
|
||||
return cbs_read_fragment_content(ctx, frag);
|
||||
}
|
||||
|
||||
int ff_cbs_read_packet(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag,
|
||||
const AVPacket *pkt)
|
||||
{
|
||||
int err;
|
||||
|
||||
memset(frag, 0, sizeof(*frag));
|
||||
|
||||
frag->data = pkt->data;
|
||||
frag->data_size = pkt->size;
|
||||
|
||||
err = ctx->codec->split_fragment(ctx, frag, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
frag->data = NULL;
|
||||
frag->data_size = 0;
|
||||
|
||||
return cbs_read_fragment_content(ctx, frag);
|
||||
}
|
||||
|
||||
int ff_cbs_read(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag,
|
||||
const uint8_t *data, size_t size)
|
||||
{
|
||||
int err;
|
||||
|
||||
memset(frag, 0, sizeof(*frag));
|
||||
|
||||
// (We won't write to this during split.)
|
||||
frag->data = (uint8_t*)data;
|
||||
frag->data_size = size;
|
||||
|
||||
err = ctx->codec->split_fragment(ctx, frag, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
frag->data = NULL;
|
||||
frag->data_size = 0;
|
||||
|
||||
return cbs_read_fragment_content(ctx, frag);
|
||||
}
|
||||
|
||||
|
||||
int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag)
|
||||
{
|
||||
int err, i;
|
||||
|
||||
for (i = 0; i < frag->nb_units; i++) {
|
||||
if (!frag->units[i].content)
|
||||
continue;
|
||||
|
||||
err = ctx->codec->write_unit(ctx, &frag->units[i]);
|
||||
if (err < 0) {
|
||||
av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to write unit %d "
|
||||
"(type %"PRIu32").\n", i, frag->units[i].type);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = ctx->codec->assemble_fragment(ctx, frag);
|
||||
if (err < 0) {
|
||||
av_log(ctx->log_ctx, AV_LOG_ERROR, "Failed to assemble fragment.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_cbs_write_extradata(CodedBitstreamContext *ctx,
|
||||
AVCodecParameters *par,
|
||||
CodedBitstreamFragment *frag)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = ff_cbs_write_fragment_data(ctx, frag);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
av_freep(&par->extradata);
|
||||
|
||||
par->extradata = av_malloc(frag->data_size +
|
||||
AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
if (!par->extradata)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
memcpy(par->extradata, frag->data, frag->data_size);
|
||||
memset(par->extradata + frag->data_size, 0,
|
||||
AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
par->extradata_size = frag->data_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_cbs_write_packet(CodedBitstreamContext *ctx,
|
||||
AVPacket *pkt,
|
||||
CodedBitstreamFragment *frag)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = ff_cbs_write_fragment_data(ctx, frag);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = av_new_packet(pkt, frag->data_size);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
memcpy(pkt->data, frag->data, frag->data_size);
|
||||
pkt->size = frag->data_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void ff_cbs_trace_header(CodedBitstreamContext *ctx,
|
||||
const char *name)
|
||||
{
|
||||
if (!ctx->trace_enable)
|
||||
return;
|
||||
|
||||
av_log(ctx->log_ctx, ctx->trace_level, "%s\n", name);
|
||||
}
|
||||
|
||||
void ff_cbs_trace_syntax_element(CodedBitstreamContext *ctx, int position,
|
||||
const char *name, const char *bits,
|
||||
int64_t value)
|
||||
{
|
||||
size_t name_len, bits_len;
|
||||
int pad;
|
||||
|
||||
if (!ctx->trace_enable)
|
||||
return;
|
||||
|
||||
av_assert0(value >= INT_MIN && value <= UINT32_MAX);
|
||||
|
||||
name_len = strlen(name);
|
||||
bits_len = strlen(bits);
|
||||
|
||||
if (name_len + bits_len > 60)
|
||||
pad = bits_len + 2;
|
||||
else
|
||||
pad = 61 - name_len;
|
||||
|
||||
av_log(ctx->log_ctx, ctx->trace_level, "%-10d %s%*s = %"PRId64"\n",
|
||||
position, name, pad, bits, value);
|
||||
}
|
||||
|
||||
int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, GetBitContext *gbc,
|
||||
int width, const char *name, uint32_t *write_to,
|
||||
uint32_t range_min, uint32_t range_max)
|
||||
{
|
||||
uint32_t value;
|
||||
int position;
|
||||
|
||||
av_assert0(width > 0 && width <= 32);
|
||||
|
||||
if (get_bits_left(gbc) < width) {
|
||||
av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid value at "
|
||||
"%s: bitstream ended.\n", name);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if (ctx->trace_enable)
|
||||
position = get_bits_count(gbc);
|
||||
|
||||
value = get_bits_long(gbc, width);
|
||||
|
||||
if (ctx->trace_enable) {
|
||||
char bits[33];
|
||||
int i;
|
||||
for (i = 0; i < width; i++)
|
||||
bits[i] = value >> (width - i - 1) & 1 ? '1' : '0';
|
||||
bits[i] = 0;
|
||||
|
||||
ff_cbs_trace_syntax_element(ctx, position, name, bits, value);
|
||||
}
|
||||
|
||||
if (value < range_min || value > range_max) {
|
||||
av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
|
||||
"%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
|
||||
name, value, range_min, range_max);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
*write_to = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
|
||||
int width, const char *name, uint32_t value,
|
||||
uint32_t range_min, uint32_t range_max)
|
||||
{
|
||||
av_assert0(width > 0 && width <= 32);
|
||||
|
||||
if (value < range_min || value > range_max) {
|
||||
av_log(ctx->log_ctx, AV_LOG_ERROR, "%s out of range: "
|
||||
"%"PRIu32", but must be in [%"PRIu32",%"PRIu32"].\n",
|
||||
name, value, range_min, range_max);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
|
||||
if (put_bits_left(pbc) < width)
|
||||
return AVERROR(ENOSPC);
|
||||
|
||||
if (ctx->trace_enable) {
|
||||
char bits[33];
|
||||
int i;
|
||||
for (i = 0; i < width; i++)
|
||||
bits[i] = value >> (width - i - 1) & 1 ? '1' : '0';
|
||||
bits[i] = 0;
|
||||
|
||||
ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc), name, bits, value);
|
||||
}
|
||||
|
||||
if (width < 32)
|
||||
put_bits(pbc, width, value);
|
||||
else
|
||||
put_bits32(pbc, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int cbs_insert_unit(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag,
|
||||
int position)
|
||||
{
|
||||
CodedBitstreamUnit *units;
|
||||
|
||||
units = av_malloc_array(frag->nb_units + 1, sizeof(*units));
|
||||
if (!units)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
if (position > 0)
|
||||
memcpy(units, frag->units, position * sizeof(*units));
|
||||
if (position < frag->nb_units)
|
||||
memcpy(units + position + 1, frag->units + position,
|
||||
(frag->nb_units - position) * sizeof(*units));
|
||||
|
||||
memset(units + position, 0, sizeof(*units));
|
||||
|
||||
av_freep(&frag->units);
|
||||
frag->units = units;
|
||||
++frag->nb_units;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag,
|
||||
int position,
|
||||
CodedBitstreamUnitType type,
|
||||
void *content)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (position == -1)
|
||||
position = frag->nb_units;
|
||||
av_assert0(position >= 0 && position <= frag->nb_units);
|
||||
|
||||
err = cbs_insert_unit(ctx, frag, position);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
frag->units[position].type = type;
|
||||
frag->units[position].content = content;
|
||||
frag->units[position].content_external = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag,
|
||||
int position,
|
||||
CodedBitstreamUnitType type,
|
||||
uint8_t *data, size_t data_size)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (position == -1)
|
||||
position = frag->nb_units;
|
||||
av_assert0(position >= 0 && position <= frag->nb_units);
|
||||
|
||||
err = cbs_insert_unit(ctx, frag, position);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
frag->units[position].type = type;
|
||||
frag->units[position].data = data;
|
||||
frag->units[position].data_size = data_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_cbs_delete_unit(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag,
|
||||
int position)
|
||||
{
|
||||
if (position < 0 || position >= frag->nb_units)
|
||||
return AVERROR(EINVAL);
|
||||
|
||||
cbs_unit_uninit(ctx, &frag->units[position]);
|
||||
|
||||
--frag->nb_units;
|
||||
|
||||
if (frag->nb_units == 0) {
|
||||
av_freep(&frag->units);
|
||||
|
||||
} else {
|
||||
memmove(frag->units + position,
|
||||
frag->units + position + 1,
|
||||
(frag->nb_units - position) * sizeof(*frag->units));
|
||||
|
||||
// Don't bother reallocating the unit array.
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* 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_CBS_H
|
||||
#define AVCODEC_CBS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "avcodec.h"
|
||||
|
||||
|
||||
/*
|
||||
* This defines a framework for converting between a coded bitstream
|
||||
* and structures defining all individual syntax elements found in
|
||||
* such a stream.
|
||||
*
|
||||
* Conversion in both directions is possible. Given a coded bitstream
|
||||
* (any meaningful fragment), it can be parsed and decomposed into
|
||||
* syntax elements stored in a set of codec-specific structures.
|
||||
* Similarly, given a set of those same codec-specific structures the
|
||||
* syntax elements can be serialised and combined to create a coded
|
||||
* bitstream.
|
||||
*/
|
||||
|
||||
struct CodedBitstreamType;
|
||||
|
||||
/**
|
||||
* The codec-specific type of a bitstream unit.
|
||||
*
|
||||
* H.264 / AVC: nal_unit_type
|
||||
* H.265 / HEVC: nal_unit_type
|
||||
* MPEG-2: start code value (without prefix)
|
||||
*/
|
||||
typedef uint32_t CodedBitstreamUnitType;
|
||||
|
||||
/**
|
||||
* Coded bitstream unit structure.
|
||||
*
|
||||
* A bitstream unit the smallest element of a bitstream which
|
||||
* is meaningful on its own. For example, an H.264 NAL unit.
|
||||
*
|
||||
* See the codec-specific header for the meaning of this for any
|
||||
* particular codec.
|
||||
*/
|
||||
typedef struct CodedBitstreamUnit {
|
||||
/**
|
||||
* Codec-specific type of this unit.
|
||||
*/
|
||||
CodedBitstreamUnitType type;
|
||||
|
||||
/**
|
||||
* Pointer to the directly-parsable bitstream form of this unit.
|
||||
*
|
||||
* May be NULL if the unit currently only exists in decomposed form.
|
||||
*/
|
||||
uint8_t *data;
|
||||
/**
|
||||
* The number of bytes in the bitstream (including any padding bits
|
||||
* in the final byte).
|
||||
*/
|
||||
size_t data_size;
|
||||
/**
|
||||
* The number of bits which should be ignored in the final byte.
|
||||
*
|
||||
* This supports non-byte-aligned bitstreams.
|
||||
*/
|
||||
size_t data_bit_padding;
|
||||
|
||||
/**
|
||||
* Pointer to the decomposed form of this unit.
|
||||
*
|
||||
* The type of this structure depends on both the codec and the
|
||||
* type of this unit. May be NULL if the unit only exists in
|
||||
* bitstream form.
|
||||
*/
|
||||
void *content;
|
||||
/**
|
||||
* Whether the content was supplied externally.
|
||||
*
|
||||
* If so, it should not be freed when freeing the unit.
|
||||
*/
|
||||
int content_external;
|
||||
} CodedBitstreamUnit;
|
||||
|
||||
/**
|
||||
* Coded bitstream fragment structure, combining one or more units.
|
||||
*
|
||||
* This is any sequence of units. It need not form some greater whole,
|
||||
* though in many cases it will. For example, an H.264 access unit,
|
||||
* which is composed of a sequence of H.264 NAL units.
|
||||
*/
|
||||
typedef struct CodedBitstreamFragment {
|
||||
/**
|
||||
* Pointer to the bitstream form of this fragment.
|
||||
*
|
||||
* May be NULL if the fragment only exists as component units.
|
||||
*/
|
||||
uint8_t *data;
|
||||
/**
|
||||
* The number of bytes in the bitstream.
|
||||
*
|
||||
* The number of bytes in the bitstream (including any padding bits
|
||||
* in the final byte).
|
||||
*/
|
||||
size_t data_size;
|
||||
/**
|
||||
* The number of bits which should be ignored in the final byte.
|
||||
*/
|
||||
size_t data_bit_padding;
|
||||
|
||||
/**
|
||||
* Number of units in this fragment.
|
||||
*
|
||||
* This may be zero if the fragment only exists in bitstream form
|
||||
* and has not been decomposed.
|
||||
*/
|
||||
int nb_units;
|
||||
/**
|
||||
* Pointer to an array of units of length nb_units.
|
||||
*
|
||||
* Must be NULL if nb_units is zero.
|
||||
*/
|
||||
CodedBitstreamUnit *units;
|
||||
} CodedBitstreamFragment;
|
||||
|
||||
/**
|
||||
* Context structure for coded bitstream operations.
|
||||
*/
|
||||
typedef struct CodedBitstreamContext {
|
||||
/**
|
||||
* Logging context to be passed to all av_log() calls associated
|
||||
* with this context.
|
||||
*/
|
||||
void *log_ctx;
|
||||
|
||||
/**
|
||||
* Internal codec-specific hooks.
|
||||
*/
|
||||
const struct CodedBitstreamType *codec;
|
||||
|
||||
/**
|
||||
* Internal codec-specific data.
|
||||
*
|
||||
* This contains any information needed when reading/writing
|
||||
* bitsteams which will not necessarily be present in a fragment.
|
||||
* For example, for H.264 it contains all currently visible
|
||||
* parameter sets - they are required to determine the bitstream
|
||||
* syntax but need not be present in every access unit.
|
||||
*/
|
||||
void *priv_data;
|
||||
|
||||
/**
|
||||
* Array of unit types which should be decomposed when reading.
|
||||
*
|
||||
* Types not in this list will be available in bitstream form only.
|
||||
* If NULL, all supported types will be decomposed.
|
||||
*/
|
||||
CodedBitstreamUnitType *decompose_unit_types;
|
||||
/**
|
||||
* Length of the decompose_unit_types array.
|
||||
*/
|
||||
int nb_decompose_unit_types;
|
||||
|
||||
/**
|
||||
* Enable trace output during read/write operations.
|
||||
*/
|
||||
int trace_enable;
|
||||
/**
|
||||
* Log level to use for trace output.
|
||||
*
|
||||
* From AV_LOG_*; defaults to AV_LOG_TRACE.
|
||||
*/
|
||||
int trace_level;
|
||||
} CodedBitstreamContext;
|
||||
|
||||
|
||||
/**
|
||||
* Create and initialise a new context for the given codec.
|
||||
*/
|
||||
int ff_cbs_init(CodedBitstreamContext **ctx,
|
||||
enum AVCodecID codec_id, void *log_ctx);
|
||||
|
||||
/**
|
||||
* Close a context and free all internal state.
|
||||
*/
|
||||
void ff_cbs_close(CodedBitstreamContext **ctx);
|
||||
|
||||
|
||||
/**
|
||||
* Read the extradata bitstream found in codec parameters into a
|
||||
* fragment, then split into units and decompose.
|
||||
*
|
||||
* This also updates the internal state, so will need to be called for
|
||||
* codecs with extradata to read parameter sets necessary for further
|
||||
* parsing even if the fragment itself is not desired.
|
||||
*/
|
||||
int ff_cbs_read_extradata(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag,
|
||||
const AVCodecParameters *par);
|
||||
|
||||
/**
|
||||
* Read the data bitstream from a packet into a fragment, then
|
||||
* split into units and decompose.
|
||||
*
|
||||
* This also updates the internal state of the coded bitstream context
|
||||
* with any persistent data from the fragment which may be required to
|
||||
* read following fragments (e.g. parameter sets).
|
||||
*/
|
||||
int ff_cbs_read_packet(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag,
|
||||
const AVPacket *pkt);
|
||||
|
||||
/**
|
||||
* Read a bitstream from a memory region into a fragment, then
|
||||
* split into units and decompose.
|
||||
*
|
||||
* This also updates the internal state of the coded bitstream context
|
||||
* with any persistent data from the fragment which may be required to
|
||||
* read following fragments (e.g. parameter sets).
|
||||
*/
|
||||
int ff_cbs_read(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag,
|
||||
const uint8_t *data, size_t size);
|
||||
|
||||
|
||||
/**
|
||||
* Write the content of the fragment to its own internal buffer.
|
||||
*
|
||||
* Writes the content of all units and then assembles them into a new
|
||||
* data buffer. When modifying the content of decomposed units, this
|
||||
* can be used to regenerate the bitstream form of units or the whole
|
||||
* fragment so that it can be extracted for other use.
|
||||
*
|
||||
* This also updates the internal state of the coded bitstream context
|
||||
* with any persistent data from the fragment which may be required to
|
||||
* write following fragments (e.g. parameter sets).
|
||||
*/
|
||||
int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag);
|
||||
|
||||
/**
|
||||
* Write the bitstream of a fragment to the extradata in codec parameters.
|
||||
*
|
||||
* This replaces any existing extradata in the structure.
|
||||
*/
|
||||
int ff_cbs_write_extradata(CodedBitstreamContext *ctx,
|
||||
AVCodecParameters *par,
|
||||
CodedBitstreamFragment *frag);
|
||||
|
||||
/**
|
||||
* Write the bitstream of a fragment to a packet.
|
||||
*/
|
||||
int ff_cbs_write_packet(CodedBitstreamContext *ctx,
|
||||
AVPacket *pkt,
|
||||
CodedBitstreamFragment *frag);
|
||||
|
||||
|
||||
/**
|
||||
* Free all allocated memory in a fragment.
|
||||
*/
|
||||
void ff_cbs_fragment_uninit(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag);
|
||||
|
||||
|
||||
/**
|
||||
* Insert a new unit into a fragment with the given content.
|
||||
*
|
||||
* The content structure continues to be owned by the caller, and
|
||||
* will not be freed when the unit is.
|
||||
*/
|
||||
int ff_cbs_insert_unit_content(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag,
|
||||
int position,
|
||||
CodedBitstreamUnitType type,
|
||||
void *content);
|
||||
|
||||
/**
|
||||
* Insert a new unit into a fragment with the given data bitstream.
|
||||
*
|
||||
* The data buffer will be owned by the unit after this operation.
|
||||
*/
|
||||
int ff_cbs_insert_unit_data(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag,
|
||||
int position,
|
||||
CodedBitstreamUnitType type,
|
||||
uint8_t *data, size_t data_size);
|
||||
|
||||
/**
|
||||
* Delete a unit from a fragment and free all memory it uses.
|
||||
*/
|
||||
int ff_cbs_delete_unit(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag,
|
||||
int position);
|
||||
|
||||
|
||||
#endif /* AVCODEC_CBS_H */
|
||||
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
* 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_CBS_H264_H
|
||||
#define AVCODEC_CBS_H264_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "cbs_h2645.h"
|
||||
#include "h264.h"
|
||||
|
||||
|
||||
enum {
|
||||
// This limit is arbitrary - it is sufficient for one message of each
|
||||
// type plus some repeats, and will therefore easily cover all sane
|
||||
// streams. However, it is possible to make technically-valid streams
|
||||
// for which it will fail (for example, by including a large number of
|
||||
// user-data-unregistered messages).
|
||||
H264_MAX_SEI_PAYLOADS = 64,
|
||||
};
|
||||
|
||||
|
||||
typedef struct H264RawNALUnitHeader {
|
||||
uint8_t forbidden_zero_bit;
|
||||
uint8_t nal_ref_idc;
|
||||
uint8_t nal_unit_type;
|
||||
|
||||
uint8_t svc_extension_flag;
|
||||
uint8_t avc_3d_extension_flag;
|
||||
} H264RawNALUnitHeader;
|
||||
|
||||
typedef struct H264RawScalingList {
|
||||
int8_t delta_scale[64];
|
||||
} H264RawScalingList;
|
||||
|
||||
typedef struct H264RawHRD {
|
||||
uint8_t cpb_cnt_minus1;
|
||||
uint8_t bit_rate_scale;
|
||||
uint8_t cpb_size_scale;
|
||||
|
||||
uint32_t bit_rate_value_minus1[H264_MAX_CPB_CNT];
|
||||
uint32_t cpb_size_value_minus1[H264_MAX_CPB_CNT];
|
||||
uint8_t cbr_flag[H264_MAX_CPB_CNT];
|
||||
|
||||
uint8_t initial_cpb_removal_delay_length_minus1;
|
||||
uint8_t cpb_removal_delay_length_minus1;
|
||||
uint8_t dpb_output_delay_length_minus1;
|
||||
uint8_t time_offset_length;
|
||||
} H264RawHRD;
|
||||
|
||||
typedef struct H264RawVUI {
|
||||
uint8_t aspect_ratio_info_present_flag;
|
||||
uint8_t aspect_ratio_idc;
|
||||
uint16_t sar_width;
|
||||
uint16_t sar_height;
|
||||
|
||||
uint8_t overscan_info_present_flag;
|
||||
uint8_t overscan_appropriate_flag;
|
||||
|
||||
uint8_t video_signal_type_present_flag;
|
||||
uint8_t video_format;
|
||||
uint8_t video_full_range_flag;
|
||||
uint8_t colour_description_present_flag;
|
||||
uint8_t colour_primaries;
|
||||
uint8_t transfer_characteristics;
|
||||
uint8_t matrix_coefficients;
|
||||
|
||||
uint8_t chroma_loc_info_present_flag;
|
||||
uint8_t chroma_sample_loc_type_top_field;
|
||||
uint8_t chroma_sample_loc_type_bottom_field;
|
||||
|
||||
uint8_t timing_info_present_flag;
|
||||
uint32_t num_units_in_tick;
|
||||
uint32_t time_scale;
|
||||
uint8_t fixed_frame_rate_flag;
|
||||
|
||||
uint8_t nal_hrd_parameters_present_flag;
|
||||
H264RawHRD nal_hrd_parameters;
|
||||
uint8_t vcl_hrd_parameters_present_flag;
|
||||
H264RawHRD vcl_hrd_parameters;
|
||||
uint8_t low_delay_hrd_flag;
|
||||
|
||||
uint8_t pic_struct_present_flag;
|
||||
|
||||
uint8_t bitstream_restriction_flag;
|
||||
uint8_t motion_vectors_over_pic_boundaries_flag;
|
||||
uint8_t max_bytes_per_pic_denom;
|
||||
uint8_t max_bits_per_mb_denom;
|
||||
uint8_t log2_max_mv_length_horizontal;
|
||||
uint8_t log2_max_mv_length_vertical;
|
||||
uint8_t max_num_reorder_frames;
|
||||
uint8_t max_dec_frame_buffering;
|
||||
} H264RawVUI;
|
||||
|
||||
typedef struct H264RawSPS {
|
||||
H264RawNALUnitHeader nal_unit_header;
|
||||
|
||||
uint8_t profile_idc;
|
||||
uint8_t constraint_set0_flag;
|
||||
uint8_t constraint_set1_flag;
|
||||
uint8_t constraint_set2_flag;
|
||||
uint8_t constraint_set3_flag;
|
||||
uint8_t constraint_set4_flag;
|
||||
uint8_t constraint_set5_flag;
|
||||
uint8_t reserved_zero_2bits;
|
||||
uint8_t level_idc;
|
||||
|
||||
uint8_t seq_parameter_set_id;
|
||||
|
||||
uint8_t chroma_format_idc;
|
||||
uint8_t separate_colour_plane_flag;
|
||||
uint8_t bit_depth_luma_minus8;
|
||||
uint8_t bit_depth_chroma_minus8;
|
||||
uint8_t qpprime_y_zero_transform_bypass_flag;
|
||||
|
||||
uint8_t seq_scaling_matrix_present_flag;
|
||||
uint8_t seq_scaling_list_present_flag[12];
|
||||
H264RawScalingList scaling_list_4x4[6];
|
||||
H264RawScalingList scaling_list_8x8[6];
|
||||
|
||||
uint8_t log2_max_frame_num_minus4;
|
||||
uint8_t pic_order_cnt_type;
|
||||
uint8_t log2_max_pic_order_cnt_lsb_minus4;
|
||||
uint8_t delta_pic_order_always_zero_flag;
|
||||
int32_t offset_for_non_ref_pic;
|
||||
int32_t offset_for_top_to_bottom_field;
|
||||
uint8_t num_ref_frames_in_pic_order_cnt_cycle;
|
||||
int32_t offset_for_ref_frame[256];
|
||||
|
||||
uint8_t max_num_ref_frames;
|
||||
uint8_t gaps_in_frame_num_allowed_flag;
|
||||
|
||||
uint16_t pic_width_in_mbs_minus1;
|
||||
uint16_t pic_height_in_map_units_minus1;
|
||||
|
||||
uint8_t frame_mbs_only_flag;
|
||||
uint8_t mb_adaptive_frame_field_flag;
|
||||
uint8_t direct_8x8_inference_flag;
|
||||
|
||||
uint8_t frame_cropping_flag;
|
||||
uint16_t frame_crop_left_offset;
|
||||
uint16_t frame_crop_right_offset;
|
||||
uint16_t frame_crop_top_offset;
|
||||
uint16_t frame_crop_bottom_offset;
|
||||
|
||||
uint8_t vui_parameters_present_flag;
|
||||
H264RawVUI vui;
|
||||
} H264RawSPS;
|
||||
|
||||
typedef struct H264RawSPSExtension {
|
||||
H264RawNALUnitHeader nal_unit_header;
|
||||
|
||||
uint8_t seq_parameter_set_id;
|
||||
|
||||
uint8_t aux_format_idc;
|
||||
uint8_t bit_depth_aux_minus8;
|
||||
uint8_t alpha_incr_flag;
|
||||
uint16_t alpha_opaque_value;
|
||||
uint16_t alpha_transparent_value;
|
||||
|
||||
uint8_t additional_extension_flag;
|
||||
} H264RawSPSExtension;
|
||||
|
||||
typedef struct H264RawPPS {
|
||||
H264RawNALUnitHeader nal_unit_header;
|
||||
|
||||
uint8_t pic_parameter_set_id;
|
||||
uint8_t seq_parameter_set_id;
|
||||
|
||||
uint8_t entropy_coding_mode_flag;
|
||||
uint8_t bottom_field_pic_order_in_frame_present_flag;
|
||||
|
||||
uint8_t num_slice_groups_minus1;
|
||||
uint8_t slice_group_map_type;
|
||||
uint16_t run_length_minus1[H264_MAX_SLICE_GROUPS];
|
||||
uint16_t top_left[H264_MAX_SLICE_GROUPS];
|
||||
uint16_t bottom_right[H264_MAX_SLICE_GROUPS];
|
||||
uint8_t slice_group_change_direction_flag;
|
||||
uint16_t slice_group_change_rate_minus1;
|
||||
uint16_t pic_size_in_map_units_minus1;
|
||||
uint8_t slice_group_id[H264_MAX_MB_PIC_SIZE];
|
||||
|
||||
uint8_t num_ref_idx_l0_default_active_minus1;
|
||||
uint8_t num_ref_idx_l1_default_active_minus1;
|
||||
|
||||
uint8_t weighted_pred_flag;
|
||||
uint8_t weighted_bipred_idc;
|
||||
|
||||
int8_t pic_init_qp_minus26;
|
||||
int8_t pic_init_qs_minus26;
|
||||
int8_t chroma_qp_index_offset;
|
||||
|
||||
uint8_t deblocking_filter_control_present_flag;
|
||||
uint8_t constrained_intra_pred_flag;
|
||||
|
||||
uint8_t more_rbsp_data;
|
||||
|
||||
uint8_t redundant_pic_cnt_present_flag;
|
||||
uint8_t transform_8x8_mode_flag;
|
||||
|
||||
uint8_t pic_scaling_matrix_present_flag;
|
||||
uint8_t pic_scaling_list_present_flag[12];
|
||||
H264RawScalingList scaling_list_4x4[6];
|
||||
H264RawScalingList scaling_list_8x8[6];
|
||||
|
||||
int8_t second_chroma_qp_index_offset;
|
||||
} H264RawPPS;
|
||||
|
||||
typedef struct H264RawAUD {
|
||||
H264RawNALUnitHeader nal_unit_header;
|
||||
|
||||
uint8_t primary_pic_type;
|
||||
} H264RawAUD;
|
||||
|
||||
typedef struct H264RawSEIBufferingPeriod {
|
||||
uint8_t seq_parameter_set_id;
|
||||
struct {
|
||||
uint32_t initial_cpb_removal_delay[H264_MAX_CPB_CNT];
|
||||
uint32_t initial_cpb_removal_delay_offset[H264_MAX_CPB_CNT];
|
||||
} nal, vcl;
|
||||
} H264RawSEIBufferingPeriod;
|
||||
|
||||
typedef struct H264RawSEIPicTimestamp {
|
||||
uint8_t ct_type;
|
||||
uint8_t nuit_field_based_flag;
|
||||
uint8_t counting_type;
|
||||
uint8_t full_timestamp_flag;
|
||||
uint8_t discontinuity_flag;
|
||||
uint8_t cnt_dropped_flag;
|
||||
uint8_t n_frames;
|
||||
uint8_t seconds_flag;
|
||||
uint8_t seconds_value;
|
||||
uint8_t minutes_flag;
|
||||
uint8_t minutes_value;
|
||||
uint8_t hours_flag;
|
||||
uint8_t hours_value;
|
||||
uint32_t time_offset;
|
||||
} H264RawSEIPicTimestamp;
|
||||
|
||||
typedef struct H264RawSEIPicTiming {
|
||||
uint32_t cpb_removal_delay;
|
||||
uint32_t dpb_output_delay;
|
||||
uint8_t pic_struct;
|
||||
uint8_t clock_timestamp_flag[3];
|
||||
H264RawSEIPicTimestamp timestamp[3];
|
||||
} H264RawSEIPicTiming;
|
||||
|
||||
typedef struct H264RawSEIUserDataRegistered {
|
||||
uint8_t itu_t_t35_country_code;
|
||||
uint8_t itu_t_t35_country_code_extension_byte;
|
||||
uint8_t *data;
|
||||
size_t data_length;
|
||||
} H264RawSEIUserDataRegistered;
|
||||
|
||||
typedef struct H264RawSEIUserDataUnregistered {
|
||||
uint8_t uuid_iso_iec_11578[16];
|
||||
uint8_t *data;
|
||||
size_t data_length;
|
||||
} H264RawSEIUserDataUnregistered;
|
||||
|
||||
typedef struct H264RawSEIRecoveryPoint {
|
||||
uint16_t recovery_frame_cnt;
|
||||
uint8_t exact_match_flag;
|
||||
uint8_t broken_link_flag;
|
||||
uint8_t changing_slice_group_idc;
|
||||
} H264RawSEIRecoveryPoint;
|
||||
|
||||
typedef struct H264RawSEIDisplayOrientation {
|
||||
uint8_t display_orientation_cancel_flag;
|
||||
uint8_t hor_flip;
|
||||
uint8_t ver_flip;
|
||||
uint16_t anticlockwise_rotation;
|
||||
uint16_t display_orientation_repetition_period;
|
||||
uint8_t display_orientation_extension_flag;
|
||||
} H264RawSEIDisplayOrientation;
|
||||
|
||||
typedef struct H264RawSEIPayload {
|
||||
uint32_t payload_type;
|
||||
uint32_t payload_size;
|
||||
union {
|
||||
H264RawSEIBufferingPeriod buffering_period;
|
||||
H264RawSEIPicTiming pic_timing;
|
||||
// H264RawSEIFiller filler -> no fields.
|
||||
H264RawSEIUserDataRegistered user_data_registered;
|
||||
H264RawSEIUserDataUnregistered user_data_unregistered;
|
||||
H264RawSEIRecoveryPoint recovery_point;
|
||||
H264RawSEIDisplayOrientation display_orientation;
|
||||
struct {
|
||||
uint8_t *data;
|
||||
size_t data_length;
|
||||
} other;
|
||||
} payload;
|
||||
} H264RawSEIPayload;
|
||||
|
||||
typedef struct H264RawSEI {
|
||||
H264RawNALUnitHeader nal_unit_header;
|
||||
|
||||
H264RawSEIPayload payload[H264_MAX_SEI_PAYLOADS];
|
||||
uint8_t payload_count;
|
||||
} H264RawSEI;
|
||||
|
||||
typedef struct H264RawSliceHeader {
|
||||
H264RawNALUnitHeader nal_unit_header;
|
||||
|
||||
uint32_t first_mb_in_slice;
|
||||
uint8_t slice_type;
|
||||
|
||||
uint8_t pic_parameter_set_id;
|
||||
|
||||
uint8_t colour_plane_id;
|
||||
|
||||
uint16_t frame_num;
|
||||
uint8_t field_pic_flag;
|
||||
uint8_t bottom_field_flag;
|
||||
|
||||
uint16_t idr_pic_id;
|
||||
|
||||
uint16_t pic_order_cnt_lsb;
|
||||
int32_t delta_pic_order_cnt_bottom;
|
||||
int32_t delta_pic_order_cnt[2];
|
||||
|
||||
uint8_t redundant_pic_cnt;
|
||||
uint8_t direct_spatial_mv_pred_flag;
|
||||
|
||||
uint8_t num_ref_idx_active_override_flag;
|
||||
uint8_t num_ref_idx_l0_active_minus1;
|
||||
uint8_t num_ref_idx_l1_active_minus1;
|
||||
|
||||
uint8_t ref_pic_list_modification_flag_l0;
|
||||
uint8_t ref_pic_list_modification_flag_l1;
|
||||
struct {
|
||||
uint8_t modification_of_pic_nums_idc;
|
||||
int32_t abs_diff_pic_num_minus1;
|
||||
uint8_t long_term_pic_num;
|
||||
} rplm_l0[H264_MAX_RPLM_COUNT], rplm_l1[H264_MAX_RPLM_COUNT];
|
||||
|
||||
uint8_t luma_log2_weight_denom;
|
||||
uint8_t chroma_log2_weight_denom;
|
||||
|
||||
uint8_t luma_weight_l0_flag[H264_MAX_REFS];
|
||||
int8_t luma_weight_l0[H264_MAX_REFS];
|
||||
int8_t luma_offset_l0[H264_MAX_REFS];
|
||||
uint8_t chroma_weight_l0_flag[H264_MAX_REFS];
|
||||
int8_t chroma_weight_l0[H264_MAX_REFS][2];
|
||||
int8_t chroma_offset_l0[H264_MAX_REFS][2];
|
||||
|
||||
uint8_t luma_weight_l1_flag[H264_MAX_REFS];
|
||||
int8_t luma_weight_l1[H264_MAX_REFS];
|
||||
int8_t luma_offset_l1[H264_MAX_REFS];
|
||||
uint8_t chroma_weight_l1_flag[H264_MAX_REFS];
|
||||
int8_t chroma_weight_l1[H264_MAX_REFS][2];
|
||||
int8_t chroma_offset_l1[H264_MAX_REFS][2];
|
||||
|
||||
uint8_t no_output_of_prior_pics_flag;
|
||||
uint8_t long_term_reference_flag;
|
||||
|
||||
uint8_t adaptive_ref_pic_marking_mode_flag;
|
||||
struct {
|
||||
uint8_t memory_management_control_operation;
|
||||
int32_t difference_of_pic_nums_minus1;
|
||||
uint8_t long_term_pic_num;
|
||||
uint8_t long_term_frame_idx;
|
||||
uint8_t max_long_term_frame_idx_plus1;
|
||||
} mmco[H264_MAX_MMCO_COUNT];
|
||||
|
||||
uint8_t cabac_init_idc;
|
||||
|
||||
int8_t slice_qp_delta;
|
||||
|
||||
uint8_t sp_for_switch_flag;
|
||||
int8_t slice_qs_delta;
|
||||
|
||||
uint8_t disable_deblocking_filter_idc;
|
||||
int8_t slice_alpha_c0_offset_div2;
|
||||
int8_t slice_beta_offset_div2;
|
||||
|
||||
uint16_t slice_group_change_cycle;
|
||||
} H264RawSliceHeader;
|
||||
|
||||
typedef struct H264RawSlice {
|
||||
H264RawSliceHeader header;
|
||||
|
||||
uint8_t *data;
|
||||
size_t data_size;
|
||||
int data_bit_start;
|
||||
} H264RawSlice;
|
||||
|
||||
|
||||
typedef struct CodedBitstreamH264Context {
|
||||
// Reader/writer context in common with the H.265 implementation.
|
||||
CodedBitstreamH2645Context common;
|
||||
|
||||
// All currently available parameter sets. These are updated when
|
||||
// any parameter set NAL unit is read/written with this context.
|
||||
H264RawSPS *sps[H264_MAX_SPS_COUNT];
|
||||
H264RawPPS *pps[H264_MAX_PPS_COUNT];
|
||||
|
||||
// The currently active parameter sets. These are updated when any
|
||||
// NAL unit refers to the relevant parameter set. These pointers
|
||||
// must also be present in the arrays above.
|
||||
const H264RawSPS *active_sps;
|
||||
const H264RawPPS *active_pps;
|
||||
|
||||
// The NAL unit type of the most recent normal slice. This is required
|
||||
// to be able to read/write auxiliary slices, because IdrPicFlag is
|
||||
// otherwise unknown.
|
||||
uint8_t last_slice_nal_unit_type;
|
||||
} CodedBitstreamH264Context;
|
||||
|
||||
|
||||
#endif /* AVCODEC_CBS_H264_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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_CBS_H2645_H
|
||||
#define AVCODEC_CBS_H2645_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "h2645_parse.h"
|
||||
|
||||
|
||||
typedef struct CodedBitstreamH2645Context {
|
||||
// If set, the stream being read is in MP4 (AVCC/HVCC) format. If not
|
||||
// set, the stream is assumed to be in annex B format.
|
||||
int mp4;
|
||||
// Size in bytes of the NAL length field for MP4 format.
|
||||
int nal_length_size;
|
||||
// Packet reader.
|
||||
H2645Packet read_packet;
|
||||
|
||||
// Write buffer
|
||||
uint8_t *write_buffer;
|
||||
size_t write_buffer_size;
|
||||
} CodedBitstreamH2645Context;
|
||||
|
||||
|
||||
#endif /* AVCODEC_CBS_H2645_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,537 @@
|
||||
/*
|
||||
* 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_CBS_H265_H
|
||||
#define AVCODEC_CBS_H265_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "cbs_h2645.h"
|
||||
#include "hevc.h"
|
||||
|
||||
|
||||
typedef struct H265RawNALUnitHeader {
|
||||
uint8_t forbidden_zero_bit;
|
||||
uint8_t nal_unit_type;
|
||||
uint8_t nuh_layer_id;
|
||||
uint8_t nuh_temporal_id_plus1;
|
||||
} H265RawNALUnitHeader;
|
||||
|
||||
typedef struct H265RawProfileTierLevel {
|
||||
uint8_t general_profile_space;
|
||||
uint8_t general_tier_flag;
|
||||
uint8_t general_profile_idc;
|
||||
|
||||
uint8_t general_profile_compatibility_flag[32];
|
||||
|
||||
uint8_t general_progressive_source_flag;
|
||||
uint8_t general_interlaced_source_flag;
|
||||
uint8_t general_non_packed_constraint_flag;
|
||||
uint8_t general_frame_only_constraint_flag;
|
||||
|
||||
uint8_t general_max_12bit_constraint_flag;
|
||||
uint8_t general_max_10bit_constraint_flag;
|
||||
uint8_t general_max_8bit_constraint_flag;
|
||||
uint8_t general_max_422chroma_constraint_flag;
|
||||
uint8_t general_max_420chroma_constraint_flag;
|
||||
uint8_t general_max_monochrome_constraint_flag;
|
||||
uint8_t general_intra_constraint_flag;
|
||||
uint8_t general_one_picture_only_constraint_flag;
|
||||
uint8_t general_lower_bit_rate_constraint_flag;
|
||||
uint8_t general_max_14bit_constraint_flag;
|
||||
|
||||
uint8_t general_inbld_flag;
|
||||
|
||||
uint8_t general_level_idc;
|
||||
|
||||
uint8_t sub_layer_profile_present_flag[HEVC_MAX_SUB_LAYERS];
|
||||
uint8_t sub_layer_level_present_flag[HEVC_MAX_SUB_LAYERS];
|
||||
|
||||
// TODO: much of that again for each sub-layer.
|
||||
} H265RawProfileTierLevel;
|
||||
|
||||
typedef struct H265RawSubLayerHRDParameters {
|
||||
uint32_t bit_rate_value_minus1[HEVC_MAX_CPB_CNT];
|
||||
uint32_t cpb_size_value_minus1[HEVC_MAX_CPB_CNT];
|
||||
uint32_t cpb_size_du_value_minus1[HEVC_MAX_CPB_CNT];
|
||||
uint32_t bit_rate_du_value_minus1[HEVC_MAX_CPB_CNT];
|
||||
uint8_t cbr_flag[HEVC_MAX_CPB_CNT];
|
||||
} H265RawSubLayerHRDParameters;
|
||||
|
||||
typedef struct H265RawHRDParameters {
|
||||
uint8_t nal_hrd_parameters_present_flag;
|
||||
uint8_t vcl_hrd_parameters_present_flag;
|
||||
|
||||
uint8_t sub_pic_hrd_params_present_flag;
|
||||
uint8_t tick_divisor_minus2;
|
||||
uint8_t du_cpb_removal_delay_increment_length_minus1;
|
||||
uint8_t sub_pic_cpb_params_in_pic_timing_sei_flag;
|
||||
uint8_t dpb_output_delay_du_length_minus1;
|
||||
|
||||
uint8_t bit_rate_scale;
|
||||
uint8_t cpb_size_scale;
|
||||
uint8_t cpb_size_du_scale;
|
||||
|
||||
uint8_t initial_cpb_removal_delay_length_minus1;
|
||||
uint8_t au_cpb_removal_delay_length_minus1;
|
||||
uint8_t dpb_output_delay_length_minus1;
|
||||
|
||||
uint8_t fixed_pic_rate_general_flag[HEVC_MAX_SUB_LAYERS];
|
||||
uint8_t fixed_pic_rate_within_cvs_flag[HEVC_MAX_SUB_LAYERS];
|
||||
uint16_t elemental_duration_in_tc_minus1[HEVC_MAX_SUB_LAYERS];
|
||||
uint8_t low_delay_hrd_flag[HEVC_MAX_SUB_LAYERS];
|
||||
uint8_t cpb_cnt_minus1[HEVC_MAX_SUB_LAYERS];
|
||||
H265RawSubLayerHRDParameters nal_sub_layer_hrd_parameters[HEVC_MAX_SUB_LAYERS];
|
||||
H265RawSubLayerHRDParameters vcl_sub_layer_hrd_parameters[HEVC_MAX_SUB_LAYERS];
|
||||
} H265RawHRDParameters;
|
||||
|
||||
typedef struct H265RawVUI {
|
||||
uint8_t aspect_ratio_info_present_flag;
|
||||
uint8_t aspect_ratio_idc;
|
||||
uint16_t sar_width;
|
||||
uint16_t sar_height;
|
||||
|
||||
uint8_t overscan_info_present_flag;
|
||||
uint8_t overscan_appropriate_flag;
|
||||
|
||||
uint8_t video_signal_type_present_flag;
|
||||
uint8_t video_format;
|
||||
uint8_t video_full_range_flag;
|
||||
uint8_t colour_description_present_flag;
|
||||
uint8_t colour_primaries;
|
||||
uint8_t transfer_characteristics;
|
||||
uint8_t matrix_coefficients;
|
||||
|
||||
uint8_t chroma_loc_info_present_flag;
|
||||
uint8_t chroma_sample_loc_type_top_field;
|
||||
uint8_t chroma_sample_loc_type_bottom_field;
|
||||
|
||||
uint8_t neutral_chroma_indication_flag;
|
||||
uint8_t field_seq_flag;
|
||||
uint8_t frame_field_info_present_flag;
|
||||
|
||||
uint8_t default_display_window_flag;
|
||||
uint16_t def_disp_win_left_offset;
|
||||
uint16_t def_disp_win_right_offset;
|
||||
uint16_t def_disp_win_top_offset;
|
||||
uint16_t def_disp_win_bottom_offset;
|
||||
|
||||
uint8_t vui_timing_info_present_flag;
|
||||
uint32_t vui_num_units_in_tick;
|
||||
uint32_t vui_time_scale;
|
||||
uint8_t vui_poc_proportional_to_timing_flag;
|
||||
uint32_t vui_num_ticks_poc_diff_one_minus1;
|
||||
uint8_t vui_hrd_parameters_present_flag;
|
||||
H265RawHRDParameters hrd_parameters;
|
||||
|
||||
uint8_t bitstream_restriction_flag;
|
||||
uint8_t tiles_fixed_structure_flag;
|
||||
uint8_t motion_vectors_over_pic_boundaries_flag;
|
||||
uint8_t restricted_ref_pic_lists_flag;
|
||||
uint16_t min_spatial_segmentation_idc;
|
||||
uint8_t max_bytes_per_pic_denom;
|
||||
uint8_t max_bits_per_min_cu_denom;
|
||||
uint8_t log2_max_mv_length_horizontal;
|
||||
uint8_t log2_max_mv_length_vertical;
|
||||
} H265RawVUI;
|
||||
|
||||
typedef struct H265RawPSExtensionData {
|
||||
uint8_t *data;
|
||||
size_t bit_length;
|
||||
} H265RawPSExtensionData;
|
||||
|
||||
typedef struct H265RawVPS {
|
||||
H265RawNALUnitHeader nal_unit_header;
|
||||
|
||||
uint8_t vps_video_parameter_set_id;
|
||||
|
||||
uint8_t vps_base_layer_internal_flag;
|
||||
uint8_t vps_base_layer_available_flag;
|
||||
uint8_t vps_max_layers_minus1;
|
||||
uint8_t vps_max_sub_layers_minus1;
|
||||
uint8_t vps_temporal_id_nesting_flag;
|
||||
|
||||
H265RawProfileTierLevel profile_tier_level;
|
||||
|
||||
uint8_t vps_sub_layer_ordering_info_present_flag;
|
||||
uint8_t vps_max_dec_pic_buffering_minus1[HEVC_MAX_SUB_LAYERS];
|
||||
uint8_t vps_max_num_reorder_pics[HEVC_MAX_SUB_LAYERS];
|
||||
uint32_t vps_max_latency_increase_plus1[HEVC_MAX_SUB_LAYERS];
|
||||
|
||||
uint8_t vps_max_layer_id;
|
||||
uint16_t vps_num_layer_sets_minus1;
|
||||
uint8_t layer_id_included_flag[HEVC_MAX_LAYER_SETS][HEVC_MAX_LAYERS];
|
||||
|
||||
uint8_t vps_timing_info_present_flag;
|
||||
uint32_t vps_num_units_in_tick;
|
||||
uint32_t vps_time_scale;
|
||||
uint8_t vps_poc_proportional_to_timing_flag;
|
||||
uint32_t vps_num_ticks_poc_diff_one_minus1;
|
||||
uint16_t vps_num_hrd_parameters;
|
||||
uint16_t hrd_layer_set_idx[HEVC_MAX_LAYER_SETS];
|
||||
uint8_t cprms_present_flag[HEVC_MAX_LAYER_SETS];
|
||||
H265RawHRDParameters hrd_parameters[HEVC_MAX_LAYER_SETS];
|
||||
|
||||
uint8_t vps_extension_flag;
|
||||
H265RawPSExtensionData extension_data;
|
||||
} H265RawVPS;
|
||||
|
||||
typedef struct H265RawSTRefPicSet {
|
||||
uint8_t inter_ref_pic_set_prediction_flag;
|
||||
|
||||
uint8_t delta_idx_minus1;
|
||||
uint8_t delta_rps_sign;
|
||||
uint16_t abs_delta_rps_minus1;
|
||||
|
||||
uint8_t used_by_curr_pic_flag[HEVC_MAX_REFS];
|
||||
uint8_t use_delta_flag[HEVC_MAX_REFS];
|
||||
|
||||
uint8_t num_negative_pics;
|
||||
uint8_t num_positive_pics;
|
||||
uint16_t delta_poc_s0_minus1[HEVC_MAX_REFS];
|
||||
uint8_t used_by_curr_pic_s0_flag[HEVC_MAX_REFS];
|
||||
uint16_t delta_poc_s1_minus1[HEVC_MAX_REFS];
|
||||
uint8_t used_by_curr_pic_s1_flag[HEVC_MAX_REFS];
|
||||
} H265RawSTRefPicSet;
|
||||
|
||||
typedef struct H265RawScalingList {
|
||||
uint8_t scaling_list_pred_mode_flag[4][6];
|
||||
uint8_t scaling_list_pred_matrix_id_delta[4][6];
|
||||
int16_t scaling_list_dc_coef_minus8[4][6];
|
||||
int8_t scaling_list_delta_coeff[4][6][64];
|
||||
} H265RawScalingList;
|
||||
|
||||
typedef struct H265RawSPS {
|
||||
H265RawNALUnitHeader nal_unit_header;
|
||||
|
||||
uint8_t sps_video_parameter_set_id;
|
||||
|
||||
uint8_t sps_max_sub_layers_minus1;
|
||||
uint8_t sps_temporal_id_nesting_flag;
|
||||
|
||||
H265RawProfileTierLevel profile_tier_level;
|
||||
|
||||
uint8_t sps_seq_parameter_set_id;
|
||||
|
||||
uint8_t chroma_format_idc;
|
||||
uint8_t separate_colour_plane_flag;
|
||||
|
||||
uint16_t pic_width_in_luma_samples;
|
||||
uint16_t pic_height_in_luma_samples;
|
||||
|
||||
uint8_t conformance_window_flag;
|
||||
uint16_t conf_win_left_offset;
|
||||
uint16_t conf_win_right_offset;
|
||||
uint16_t conf_win_top_offset;
|
||||
uint16_t conf_win_bottom_offset;
|
||||
|
||||
uint8_t bit_depth_luma_minus8;
|
||||
uint8_t bit_depth_chroma_minus8;
|
||||
|
||||
uint8_t log2_max_pic_order_cnt_lsb_minus4;
|
||||
|
||||
uint8_t sps_sub_layer_ordering_info_present_flag;
|
||||
uint8_t sps_max_dec_pic_buffering_minus1[HEVC_MAX_SUB_LAYERS];
|
||||
uint8_t sps_max_num_reorder_pics[HEVC_MAX_SUB_LAYERS];
|
||||
uint32_t sps_max_latency_increase_plus1[HEVC_MAX_SUB_LAYERS];
|
||||
|
||||
uint8_t log2_min_luma_coding_block_size_minus3;
|
||||
uint8_t log2_diff_max_min_luma_coding_block_size;
|
||||
uint8_t log2_min_luma_transform_block_size_minus2;
|
||||
uint8_t log2_diff_max_min_luma_transform_block_size;
|
||||
uint8_t max_transform_hierarchy_depth_inter;
|
||||
uint8_t max_transform_hierarchy_depth_intra;
|
||||
|
||||
uint8_t scaling_list_enabled_flag;
|
||||
uint8_t sps_scaling_list_data_present_flag;
|
||||
H265RawScalingList scaling_list;
|
||||
|
||||
uint8_t amp_enabled_flag;
|
||||
uint8_t sample_adaptive_offset_enabled_flag;
|
||||
|
||||
uint8_t pcm_enabled_flag;
|
||||
uint8_t pcm_sample_bit_depth_luma_minus1;
|
||||
uint8_t pcm_sample_bit_depth_chroma_minus1;
|
||||
uint8_t log2_min_pcm_luma_coding_block_size_minus3;
|
||||
uint8_t log2_diff_max_min_pcm_luma_coding_block_size;
|
||||
uint8_t pcm_loop_filter_disabled_flag;
|
||||
|
||||
uint8_t num_short_term_ref_pic_sets;
|
||||
H265RawSTRefPicSet st_ref_pic_set[HEVC_MAX_SHORT_TERM_REF_PIC_SETS];
|
||||
|
||||
uint8_t long_term_ref_pics_present_flag;
|
||||
uint8_t num_long_term_ref_pics_sps;
|
||||
uint16_t lt_ref_pic_poc_lsb_sps[HEVC_MAX_LONG_TERM_REF_PICS];
|
||||
uint8_t used_by_curr_pic_lt_sps_flag[HEVC_MAX_LONG_TERM_REF_PICS];
|
||||
|
||||
uint8_t sps_temporal_mvp_enabled_flag;
|
||||
uint8_t strong_intra_smoothing_enabled_flag;
|
||||
|
||||
uint8_t vui_parameters_present_flag;
|
||||
H265RawVUI vui;
|
||||
|
||||
uint8_t sps_extension_present_flag;
|
||||
uint8_t sps_range_extension_flag;
|
||||
uint8_t sps_multilayer_extension_flag;
|
||||
uint8_t sps_3d_extension_flag;
|
||||
uint8_t sps_scc_extension_flag;
|
||||
uint8_t sps_extension_4bits;
|
||||
|
||||
H265RawPSExtensionData extension_data;
|
||||
|
||||
// Range extension.
|
||||
uint8_t transform_skip_rotation_enabled_flag;
|
||||
uint8_t transform_skip_context_enabled_flag;
|
||||
uint8_t implicit_rdpcm_enabled_flag;
|
||||
uint8_t explicit_rdpcm_enabled_flag;
|
||||
uint8_t extended_precision_processing_flag;
|
||||
uint8_t intra_smoothing_disabled_flag;
|
||||
uint8_t high_precision_offsets_enabled_flag;
|
||||
uint8_t persistent_rice_adaptation_enabled_flag;
|
||||
uint8_t cabac_bypass_alignment_enabled_flag;
|
||||
|
||||
// Screen content coding extension.
|
||||
uint8_t sps_curr_pic_ref_enabled_flag;
|
||||
uint8_t palette_mode_enabled_flag;
|
||||
uint8_t palette_max_size;
|
||||
uint8_t delta_palette_max_predictor_size;
|
||||
uint8_t sps_palette_predictor_initializer_present_flag;
|
||||
uint8_t sps_num_palette_predictor_initializer_minus1;
|
||||
uint16_t sps_palette_predictor_initializers[3][128];
|
||||
|
||||
uint8_t motion_vector_resolution_control_idc;
|
||||
uint8_t intra_boundary_filtering_disable_flag;
|
||||
} H265RawSPS;
|
||||
|
||||
typedef struct H265RawPPS {
|
||||
H265RawNALUnitHeader nal_unit_header;
|
||||
|
||||
uint8_t pps_pic_parameter_set_id;
|
||||
uint8_t pps_seq_parameter_set_id;
|
||||
|
||||
uint8_t dependent_slice_segments_enabled_flag;
|
||||
uint8_t output_flag_present_flag;
|
||||
uint8_t num_extra_slice_header_bits;
|
||||
uint8_t sign_data_hiding_enabled_flag;
|
||||
uint8_t cabac_init_present_flag;
|
||||
|
||||
uint8_t num_ref_idx_l0_default_active_minus1;
|
||||
uint8_t num_ref_idx_l1_default_active_minus1;
|
||||
|
||||
int8_t init_qp_minus26;
|
||||
|
||||
uint8_t constrained_intra_pred_flag;
|
||||
uint8_t transform_skip_enabled_flag;
|
||||
uint8_t cu_qp_delta_enabled_flag;
|
||||
uint8_t diff_cu_qp_delta_depth;
|
||||
|
||||
int8_t pps_cb_qp_offset;
|
||||
int8_t pps_cr_qp_offset;
|
||||
uint8_t pps_slice_chroma_qp_offsets_present_flag;
|
||||
|
||||
uint8_t weighted_pred_flag;
|
||||
uint8_t weighted_bipred_flag;
|
||||
|
||||
uint8_t transquant_bypass_enabled_flag;
|
||||
uint8_t tiles_enabled_flag;
|
||||
uint8_t entropy_coding_sync_enabled_flag;
|
||||
|
||||
uint8_t num_tile_columns_minus1;
|
||||
uint8_t num_tile_rows_minus1;
|
||||
uint8_t uniform_spacing_flag;
|
||||
uint16_t column_width_minus1[HEVC_MAX_TILE_COLUMNS];
|
||||
uint16_t row_height_minus1[HEVC_MAX_TILE_ROWS];
|
||||
uint8_t loop_filter_across_tiles_enabled_flag;
|
||||
|
||||
uint8_t pps_loop_filter_across_slices_enabled_flag;
|
||||
uint8_t deblocking_filter_control_present_flag;
|
||||
uint8_t deblocking_filter_override_enabled_flag;
|
||||
uint8_t pps_deblocking_filter_disabled_flag;
|
||||
int8_t pps_beta_offset_div2;
|
||||
int8_t pps_tc_offset_div2;
|
||||
|
||||
uint8_t pps_scaling_list_data_present_flag;
|
||||
H265RawScalingList scaling_list;
|
||||
|
||||
uint8_t lists_modification_present_flag;
|
||||
uint8_t log2_parallel_merge_level_minus2;
|
||||
|
||||
uint8_t slice_segment_header_extension_present_flag;
|
||||
|
||||
uint8_t pps_extension_present_flag;
|
||||
uint8_t pps_range_extension_flag;
|
||||
uint8_t pps_multilayer_extension_flag;
|
||||
uint8_t pps_3d_extension_flag;
|
||||
uint8_t pps_scc_extension_flag;
|
||||
uint8_t pps_extension_4bits;
|
||||
|
||||
H265RawPSExtensionData extension_data;
|
||||
|
||||
// Range extension.
|
||||
uint8_t log2_max_transform_skip_block_size_minus2;
|
||||
uint8_t cross_component_prediction_enabled_flag;
|
||||
uint8_t chroma_qp_offset_list_enabled_flag;
|
||||
uint8_t diff_cu_chroma_qp_offset_depth;
|
||||
uint8_t chroma_qp_offset_list_len_minus1;
|
||||
int8_t cb_qp_offset_list[6];
|
||||
int8_t cr_qp_offset_list[6];
|
||||
uint8_t log2_sao_offset_scale_luma;
|
||||
uint8_t log2_sao_offset_scale_chroma;
|
||||
|
||||
// Screen content coding extension.
|
||||
uint8_t pps_curr_pic_ref_enabled_flag;
|
||||
uint8_t residual_adaptive_colour_transform_enabled_flag;
|
||||
uint8_t pps_slice_act_qp_offsets_present_flag;
|
||||
int8_t pps_act_y_qp_offset_plus5;
|
||||
int8_t pps_act_cb_qp_offset_plus5;
|
||||
int8_t pps_act_cr_qp_offset_plus3;
|
||||
|
||||
uint8_t pps_palette_predictor_initializer_present_flag;
|
||||
uint8_t pps_num_palette_predictor_initializer;
|
||||
uint8_t monochrome_palette_flag;
|
||||
uint8_t luma_bit_depth_entry_minus8;
|
||||
uint8_t chroma_bit_depth_entry_minus8;
|
||||
uint16_t pps_palette_predictor_initializers[3][128];
|
||||
} H265RawPPS;
|
||||
|
||||
typedef struct H265RawAUD {
|
||||
H265RawNALUnitHeader nal_unit_header;
|
||||
|
||||
uint8_t pic_type;
|
||||
} H265RawAUD;
|
||||
|
||||
typedef struct H265RawSliceHeader {
|
||||
H265RawNALUnitHeader nal_unit_header;
|
||||
|
||||
uint8_t first_slice_segment_in_pic_flag;
|
||||
uint8_t no_output_of_prior_pics_flag;
|
||||
uint8_t slice_pic_parameter_set_id;
|
||||
|
||||
uint8_t dependent_slice_segment_flag;
|
||||
uint16_t slice_segment_address;
|
||||
|
||||
uint8_t slice_reserved_flag[8];
|
||||
uint8_t slice_type;
|
||||
|
||||
uint8_t pic_output_flag;
|
||||
uint8_t colour_plane_id;
|
||||
|
||||
uint16_t slice_pic_order_cnt_lsb;
|
||||
|
||||
uint8_t short_term_ref_pic_set_sps_flag;
|
||||
H265RawSTRefPicSet short_term_ref_pic_set;
|
||||
uint8_t short_term_ref_pic_set_idx;
|
||||
|
||||
uint8_t num_long_term_sps;
|
||||
uint8_t num_long_term_pics;
|
||||
uint8_t lt_idx_sps[HEVC_MAX_REFS];
|
||||
uint8_t poc_lsb_lt[HEVC_MAX_REFS];
|
||||
uint8_t used_by_curr_pic_lt_flag[HEVC_MAX_REFS];
|
||||
uint8_t delta_poc_msb_present_flag[HEVC_MAX_REFS];
|
||||
uint32_t delta_poc_msb_cycle_lt[HEVC_MAX_REFS];
|
||||
|
||||
uint8_t slice_temporal_mvp_enabled_flag;
|
||||
|
||||
uint8_t slice_sao_luma_flag;
|
||||
uint8_t slice_sao_chroma_flag;
|
||||
|
||||
uint8_t num_ref_idx_active_override_flag;
|
||||
uint8_t num_ref_idx_l0_active_minus1;
|
||||
uint8_t num_ref_idx_l1_active_minus1;
|
||||
|
||||
uint8_t ref_pic_list_modification_flag_l0;
|
||||
uint8_t list_entry_l0[HEVC_MAX_REFS];
|
||||
uint8_t ref_pic_list_modification_flag_l1;
|
||||
uint8_t list_entry_l1[HEVC_MAX_REFS];
|
||||
|
||||
uint8_t mvd_l1_zero_flag;
|
||||
uint8_t cabac_init_flag;
|
||||
uint8_t collocated_from_l0_flag;
|
||||
uint8_t collocated_ref_idx;
|
||||
|
||||
uint8_t luma_log2_weight_denom;
|
||||
int8_t delta_chroma_log2_weight_denom;
|
||||
uint8_t luma_weight_l0_flag[HEVC_MAX_REFS];
|
||||
uint8_t chroma_weight_l0_flag[HEVC_MAX_REFS];
|
||||
int8_t delta_luma_weight_l0[HEVC_MAX_REFS];
|
||||
int16_t luma_offset_l0[HEVC_MAX_REFS];
|
||||
int8_t delta_chroma_weight_l0[HEVC_MAX_REFS][2];
|
||||
int16_t chroma_offset_l0[HEVC_MAX_REFS][2];
|
||||
uint8_t luma_weight_l1_flag[HEVC_MAX_REFS];
|
||||
uint8_t chroma_weight_l1_flag[HEVC_MAX_REFS];
|
||||
int8_t delta_luma_weight_l1[HEVC_MAX_REFS];
|
||||
int16_t luma_offset_l1[HEVC_MAX_REFS];
|
||||
int8_t delta_chroma_weight_l1[HEVC_MAX_REFS][2];
|
||||
int16_t chroma_offset_l1[HEVC_MAX_REFS][2];
|
||||
|
||||
uint8_t five_minus_max_num_merge_cand;
|
||||
uint8_t use_integer_mv_flag;
|
||||
|
||||
int8_t slice_qp_delta;
|
||||
int8_t slice_cb_qp_offset;
|
||||
int8_t slice_cr_qp_offset;
|
||||
int8_t slice_act_y_qp_offset;
|
||||
int8_t slice_act_cb_qp_offset;
|
||||
int8_t slice_act_cr_qp_offset;
|
||||
uint8_t cu_chroma_qp_offset_enabled_flag;
|
||||
|
||||
uint8_t deblocking_filter_override_flag;
|
||||
uint8_t slice_deblocking_filter_disabled_flag;
|
||||
int8_t slice_beta_offset_div2;
|
||||
int8_t slice_tc_offset_div2;
|
||||
uint8_t slice_loop_filter_across_slices_enabled_flag;
|
||||
|
||||
uint16_t num_entry_point_offsets;
|
||||
uint8_t offset_len_minus1;
|
||||
uint32_t entry_point_offset_minus1[HEVC_MAX_ENTRY_POINT_OFFSETS];
|
||||
|
||||
uint16_t slice_segment_header_extension_length;
|
||||
uint8_t slice_segment_header_extension_data_byte[256];
|
||||
} H265RawSliceHeader;
|
||||
|
||||
|
||||
typedef struct H265RawSlice {
|
||||
H265RawSliceHeader header;
|
||||
|
||||
uint8_t *data;
|
||||
size_t data_size;
|
||||
int data_bit_start;
|
||||
} H265RawSlice;
|
||||
|
||||
|
||||
typedef struct CodedBitstreamH265Context {
|
||||
// Reader/writer context in common with the H.264 implementation.
|
||||
CodedBitstreamH2645Context common;
|
||||
|
||||
// All currently available parameter sets. These are updated when
|
||||
// any parameter set NAL unit is read/written with this context.
|
||||
H265RawVPS *vps[HEVC_MAX_VPS_COUNT];
|
||||
H265RawSPS *sps[HEVC_MAX_SPS_COUNT];
|
||||
H265RawPPS *pps[HEVC_MAX_PPS_COUNT];
|
||||
|
||||
// The currently active parameter sets. These are updated when any
|
||||
// NAL unit refers to the relevant parameter set. These pointers
|
||||
// must also be present in the arrays above.
|
||||
const H265RawVPS *active_vps;
|
||||
const H265RawSPS *active_sps;
|
||||
const H265RawPPS *active_pps;
|
||||
} CodedBitstreamH265Context;
|
||||
|
||||
|
||||
#endif /* AVCODEC_CBS_H265_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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_CBS_INTERNAL_H
|
||||
#define AVCODEC_CBS_INTERNAL_H
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "cbs.h"
|
||||
#include "get_bits.h"
|
||||
#include "put_bits.h"
|
||||
|
||||
|
||||
typedef struct CodedBitstreamType {
|
||||
enum AVCodecID codec_id;
|
||||
|
||||
size_t priv_data_size;
|
||||
|
||||
// Split frag->data into coded bitstream units, creating the
|
||||
// frag->units array. Fill data but not content on each unit.
|
||||
// header is set if the fragment came from a header block, which
|
||||
// may require different parsing for some codecs (e.g. the AVCC
|
||||
// header in H.264).
|
||||
int (*split_fragment)(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag,
|
||||
int header);
|
||||
|
||||
// Read the unit->data bitstream and decompose it, creating
|
||||
// unit->content.
|
||||
int (*read_unit)(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamUnit *unit);
|
||||
|
||||
// Write the unit->data bitstream from unit->content.
|
||||
int (*write_unit)(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamUnit *unit);
|
||||
|
||||
// Read the data from all of frag->units and assemble it into
|
||||
// a bitstream for the whole fragment.
|
||||
int (*assemble_fragment)(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag);
|
||||
|
||||
// Free the content and data of a single unit.
|
||||
void (*free_unit)(CodedBitstreamUnit *unit);
|
||||
|
||||
// Free the codec internal state.
|
||||
void (*close)(CodedBitstreamContext *ctx);
|
||||
} CodedBitstreamType;
|
||||
|
||||
|
||||
// Helper functions for trace output.
|
||||
|
||||
void ff_cbs_trace_header(CodedBitstreamContext *ctx,
|
||||
const char *name);
|
||||
|
||||
void ff_cbs_trace_syntax_element(CodedBitstreamContext *ctx,
|
||||
int position, const char *name,
|
||||
const char *bitstring, int64_t value);
|
||||
|
||||
|
||||
// Helper functions for read/write of common bitstream elements, including
|
||||
// generation of trace output.
|
||||
|
||||
int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, GetBitContext *gbc,
|
||||
int width, const char *name, uint32_t *write_to,
|
||||
uint32_t range_min, uint32_t range_max);
|
||||
|
||||
int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
|
||||
int width, const char *name, uint32_t value,
|
||||
uint32_t range_min, uint32_t range_max);
|
||||
|
||||
|
||||
extern const CodedBitstreamType ff_cbs_type_h264;
|
||||
extern const CodedBitstreamType ff_cbs_type_h265;
|
||||
extern const CodedBitstreamType ff_cbs_type_mpeg2;
|
||||
|
||||
|
||||
#endif /* AVCODEC_CBS_INTERNAL_H */
|
||||
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* 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/avassert.h"
|
||||
|
||||
#include "cbs.h"
|
||||
#include "cbs_internal.h"
|
||||
#include "cbs_mpeg2.h"
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
#define HEADER(name) do { \
|
||||
ff_cbs_trace_header(ctx, name); \
|
||||
} while (0)
|
||||
|
||||
#define CHECK(call) do { \
|
||||
err = (call); \
|
||||
if (err < 0) \
|
||||
return err; \
|
||||
} while (0)
|
||||
|
||||
#define FUNC_NAME(rw, codec, name) cbs_ ## codec ## _ ## rw ## _ ## name
|
||||
#define FUNC_MPEG2(rw, name) FUNC_NAME(rw, mpeg2, name)
|
||||
#define FUNC(name) FUNC_MPEG2(READWRITE, name)
|
||||
|
||||
|
||||
#define READ
|
||||
#define READWRITE read
|
||||
#define RWContext GetBitContext
|
||||
|
||||
#define xui(width, name, var) do { \
|
||||
uint32_t value = 0; \
|
||||
CHECK(ff_cbs_read_unsigned(ctx, rw, width, #name, \
|
||||
&value, 0, (1 << width) - 1)); \
|
||||
var = value; \
|
||||
} while (0)
|
||||
|
||||
#define ui(width, name) \
|
||||
xui(width, name, current->name)
|
||||
|
||||
#define marker_bit() do { \
|
||||
av_unused uint32_t one; \
|
||||
CHECK(ff_cbs_read_unsigned(ctx, rw, 1, "marker_bit", &one, 1, 1)); \
|
||||
} while (0)
|
||||
|
||||
#define nextbits(width, compare, var) \
|
||||
(get_bits_left(rw) >= width && \
|
||||
(var = show_bits(rw, width)) == (compare))
|
||||
|
||||
#include "cbs_mpeg2_syntax_template.c"
|
||||
|
||||
#undef READ
|
||||
#undef READWRITE
|
||||
#undef RWContext
|
||||
#undef xui
|
||||
#undef ui
|
||||
#undef marker_bit
|
||||
#undef nextbits
|
||||
|
||||
|
||||
#define WRITE
|
||||
#define READWRITE write
|
||||
#define RWContext PutBitContext
|
||||
|
||||
#define xui(width, name, var) do { \
|
||||
CHECK(ff_cbs_write_unsigned(ctx, rw, width, #name, \
|
||||
var, 0, (1 << width) - 1)); \
|
||||
} while (0)
|
||||
|
||||
#define ui(width, name) \
|
||||
xui(width, name, current->name)
|
||||
|
||||
#define marker_bit() do { \
|
||||
CHECK(ff_cbs_write_unsigned(ctx, rw, 1, "marker_bit", 1, 1, 1)); \
|
||||
} while (0)
|
||||
|
||||
#define nextbits(width, compare, var) (var)
|
||||
|
||||
#include "cbs_mpeg2_syntax_template.c"
|
||||
|
||||
#undef READ
|
||||
#undef READWRITE
|
||||
#undef RWContext
|
||||
#undef xui
|
||||
#undef ui
|
||||
#undef marker_bit
|
||||
#undef nextbits
|
||||
|
||||
|
||||
static int cbs_mpeg2_split_fragment(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag,
|
||||
int header)
|
||||
{
|
||||
const uint8_t *start, *end;
|
||||
uint8_t *unit_data;
|
||||
uint32_t start_code = -1, next_start_code = -1;
|
||||
size_t unit_size;
|
||||
int err, i, unit_type;
|
||||
|
||||
start = avpriv_find_start_code(frag->data, frag->data + frag->data_size,
|
||||
&start_code);
|
||||
for (i = 0;; i++) {
|
||||
end = avpriv_find_start_code(start, frag->data + frag->data_size,
|
||||
&next_start_code);
|
||||
|
||||
unit_type = start_code & 0xff;
|
||||
|
||||
// The start and end pointers point at to the byte following the
|
||||
// start_code_identifier in the start code that they found.
|
||||
if (end == frag->data + frag->data_size) {
|
||||
// We didn't find a start code, so this is the final unit.
|
||||
unit_size = end - (start - 1);
|
||||
} else {
|
||||
// Unit runs from start to the beginning of the start code
|
||||
// pointed to by end (including any padding zeroes).
|
||||
unit_size = (end - 4) - (start - 1);
|
||||
}
|
||||
|
||||
unit_data = av_malloc(unit_size + AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
if (!unit_data)
|
||||
return AVERROR(ENOMEM);
|
||||
memcpy(unit_data, start - 1, unit_size);
|
||||
memset(unit_data + unit_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
|
||||
err = ff_cbs_insert_unit_data(ctx, frag, i, unit_type,
|
||||
unit_data, unit_size);
|
||||
if (err < 0) {
|
||||
av_freep(&unit_data);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (end == frag->data + frag->data_size)
|
||||
break;
|
||||
|
||||
start_code = next_start_code;
|
||||
start = end;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cbs_mpeg2_read_unit(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamUnit *unit)
|
||||
{
|
||||
GetBitContext gbc;
|
||||
int err;
|
||||
|
||||
err = init_get_bits(&gbc, unit->data, 8 * unit->data_size);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (MPEG2_START_IS_SLICE(unit->type)) {
|
||||
MPEG2RawSlice *slice;
|
||||
int pos, len;
|
||||
|
||||
slice = av_mallocz(sizeof(*slice));
|
||||
if (!slice)
|
||||
return AVERROR(ENOMEM);
|
||||
err = cbs_mpeg2_read_slice_header(ctx, &gbc, &slice->header);
|
||||
if (err < 0) {
|
||||
av_free(slice);
|
||||
return err;
|
||||
}
|
||||
|
||||
pos = get_bits_count(&gbc);
|
||||
len = unit->data_size;
|
||||
|
||||
slice->data_size = len - pos / 8;
|
||||
slice->data = av_malloc(slice->data_size +
|
||||
AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
if (!slice->data) {
|
||||
av_free(slice);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
memcpy(slice->data,
|
||||
unit->data + pos / 8, slice->data_size);
|
||||
memset(slice->data + slice->data_size, 0,
|
||||
AV_INPUT_BUFFER_PADDING_SIZE);
|
||||
slice->data_bit_start = pos % 8;
|
||||
|
||||
unit->content = slice;
|
||||
|
||||
} else {
|
||||
switch (unit->type) {
|
||||
#define START(start_code, type, func) \
|
||||
case start_code: \
|
||||
{ \
|
||||
type *header; \
|
||||
header = av_mallocz(sizeof(*header)); \
|
||||
if (!header) \
|
||||
return AVERROR(ENOMEM); \
|
||||
err = cbs_mpeg2_read_ ## func(ctx, &gbc, header); \
|
||||
if (err < 0) { \
|
||||
av_free(header); \
|
||||
return err; \
|
||||
} \
|
||||
unit->content = header; \
|
||||
} \
|
||||
break;
|
||||
START(0x00, MPEG2RawPictureHeader, picture_header);
|
||||
START(0xb2, MPEG2RawUserData, user_data);
|
||||
START(0xb3, MPEG2RawSequenceHeader, sequence_header);
|
||||
START(0xb5, MPEG2RawExtensionData, extension_data);
|
||||
START(0xb8, MPEG2RawGroupOfPicturesHeader, group_of_pictures_header);
|
||||
#undef START
|
||||
default:
|
||||
av_log(ctx->log_ctx, AV_LOG_ERROR, "Unknown start code %"PRIx32".\n",
|
||||
unit->type);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cbs_mpeg2_write_header(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamUnit *unit,
|
||||
PutBitContext *pbc)
|
||||
{
|
||||
int err;
|
||||
|
||||
switch (unit->type) {
|
||||
#define START(start_code, type, func) \
|
||||
case start_code: \
|
||||
err = cbs_mpeg2_write_ ## func(ctx, pbc, unit->content); \
|
||||
break;
|
||||
START(0x00, MPEG2RawPictureHeader, picture_header);
|
||||
START(0xb2, MPEG2RawUserData, user_data);
|
||||
START(0xb3, MPEG2RawSequenceHeader, sequence_header);
|
||||
START(0xb5, MPEG2RawExtensionData, extension_data);
|
||||
START(0xb8, MPEG2RawGroupOfPicturesHeader, group_of_pictures_header);
|
||||
#undef START
|
||||
default:
|
||||
av_log(ctx->log_ctx, AV_LOG_ERROR, "Write unimplemented for start "
|
||||
"code %02"PRIu32".\n", unit->type);
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cbs_mpeg2_write_slice(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamUnit *unit,
|
||||
PutBitContext *pbc)
|
||||
{
|
||||
MPEG2RawSlice *slice = unit->content;
|
||||
GetBitContext gbc;
|
||||
size_t bits_left;
|
||||
int err;
|
||||
|
||||
err = cbs_mpeg2_write_slice_header(ctx, pbc, &slice->header);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (slice->data) {
|
||||
if (slice->data_size * 8 + 8 > put_bits_left(pbc))
|
||||
return AVERROR(ENOSPC);
|
||||
|
||||
init_get_bits(&gbc, slice->data, slice->data_size * 8);
|
||||
skip_bits_long(&gbc, slice->data_bit_start);
|
||||
|
||||
while (get_bits_left(&gbc) > 15)
|
||||
put_bits(pbc, 16, get_bits(&gbc, 16));
|
||||
|
||||
bits_left = get_bits_left(&gbc);
|
||||
put_bits(pbc, bits_left, get_bits(&gbc, bits_left));
|
||||
|
||||
// Align with zeroes.
|
||||
while (put_bits_count(pbc) % 8 != 0)
|
||||
put_bits(pbc, 1, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cbs_mpeg2_write_unit(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamUnit *unit)
|
||||
{
|
||||
CodedBitstreamMPEG2Context *priv = ctx->priv_data;
|
||||
PutBitContext pbc;
|
||||
int err;
|
||||
|
||||
if (!priv->write_buffer) {
|
||||
// Initial write buffer size is 1MB.
|
||||
priv->write_buffer_size = 1024 * 1024;
|
||||
|
||||
reallocate_and_try_again:
|
||||
err = av_reallocp(&priv->write_buffer, priv->write_buffer_size);
|
||||
if (err < 0) {
|
||||
av_log(ctx->log_ctx, AV_LOG_ERROR, "Unable to allocate a "
|
||||
"sufficiently large write buffer (last attempt "
|
||||
"%"SIZE_SPECIFIER" bytes).\n", priv->write_buffer_size);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
init_put_bits(&pbc, priv->write_buffer, priv->write_buffer_size);
|
||||
|
||||
if (unit->type >= 0x01 && unit->type <= 0xaf)
|
||||
err = cbs_mpeg2_write_slice(ctx, unit, &pbc);
|
||||
else
|
||||
err = cbs_mpeg2_write_header(ctx, unit, &pbc);
|
||||
|
||||
if (err == AVERROR(ENOSPC)) {
|
||||
// Overflow.
|
||||
priv->write_buffer_size *= 2;
|
||||
goto reallocate_and_try_again;
|
||||
}
|
||||
if (err < 0) {
|
||||
// Write failed for some other reason.
|
||||
return err;
|
||||
}
|
||||
|
||||
if (put_bits_count(&pbc) % 8)
|
||||
unit->data_bit_padding = 8 - put_bits_count(&pbc) % 8;
|
||||
else
|
||||
unit->data_bit_padding = 0;
|
||||
|
||||
unit->data_size = (put_bits_count(&pbc) + 7) / 8;
|
||||
flush_put_bits(&pbc);
|
||||
|
||||
err = av_reallocp(&unit->data, unit->data_size);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
memcpy(unit->data, priv->write_buffer, unit->data_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cbs_mpeg2_assemble_fragment(CodedBitstreamContext *ctx,
|
||||
CodedBitstreamFragment *frag)
|
||||
{
|
||||
uint8_t *data;
|
||||
size_t size, dp, sp;
|
||||
int i;
|
||||
|
||||
size = 0;
|
||||
for (i = 0; i < frag->nb_units; i++)
|
||||
size += 3 + frag->units[i].data_size;
|
||||
|
||||
data = av_malloc(size);
|
||||
if (!data)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
dp = 0;
|
||||
for (i = 0; i < frag->nb_units; i++) {
|
||||
CodedBitstreamUnit *unit = &frag->units[i];
|
||||
|
||||
data[dp++] = 0;
|
||||
data[dp++] = 0;
|
||||
data[dp++] = 1;
|
||||
|
||||
for (sp = 0; sp < unit->data_size; sp++)
|
||||
data[dp++] = unit->data[sp];
|
||||
}
|
||||
|
||||
av_assert0(dp == size);
|
||||
|
||||
frag->data = data;
|
||||
frag->data_size = size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cbs_mpeg2_free_unit(CodedBitstreamUnit *unit)
|
||||
{
|
||||
if (MPEG2_START_IS_SLICE(unit->type)) {
|
||||
MPEG2RawSlice *slice = unit->content;
|
||||
av_freep(&slice->data);
|
||||
av_freep(&slice->header.extra_information);
|
||||
} else if (unit->type == MPEG2_START_USER_DATA) {
|
||||
MPEG2RawUserData *user = unit->content;
|
||||
av_freep(&user->user_data);
|
||||
}
|
||||
av_freep(&unit->content);
|
||||
}
|
||||
|
||||
static void cbs_mpeg2_close(CodedBitstreamContext *ctx)
|
||||
{
|
||||
CodedBitstreamMPEG2Context *priv = ctx->priv_data;
|
||||
|
||||
av_freep(&priv->write_buffer);
|
||||
}
|
||||
|
||||
const CodedBitstreamType ff_cbs_type_mpeg2 = {
|
||||
.codec_id = AV_CODEC_ID_MPEG2VIDEO,
|
||||
|
||||
.priv_data_size = sizeof(CodedBitstreamMPEG2Context),
|
||||
|
||||
.split_fragment = &cbs_mpeg2_split_fragment,
|
||||
.read_unit = &cbs_mpeg2_read_unit,
|
||||
.write_unit = &cbs_mpeg2_write_unit,
|
||||
.assemble_fragment = &cbs_mpeg2_assemble_fragment,
|
||||
|
||||
.free_unit = &cbs_mpeg2_free_unit,
|
||||
.close = &cbs_mpeg2_close,
|
||||
};
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* 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_CBS_MPEG2_H
|
||||
#define AVCODEC_CBS_MPEG2_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
enum {
|
||||
MPEG2_START_PICTURE = 0x00,
|
||||
MPEG2_START_SLICE_MIN = 0x01,
|
||||
MPEG2_START_SLICE_MAX = 0xaf,
|
||||
MPEG2_START_USER_DATA = 0xb2,
|
||||
MPEG2_START_SEQUENCE_HEADER = 0xb3,
|
||||
MPEG2_START_SEQUENCE_ERROR = 0xb4,
|
||||
MPEG2_START_EXTENSION = 0xb5,
|
||||
MPEG2_START_SEQUENCE_END = 0xb7,
|
||||
MPEG2_START_GROUP = 0xb8,
|
||||
};
|
||||
|
||||
#define MPEG2_START_IS_SLICE(type) \
|
||||
((type) >= MPEG2_START_SLICE_MIN && \
|
||||
(type) <= MPEG2_START_SLICE_MAX)
|
||||
|
||||
enum {
|
||||
MPEG2_EXTENSION_SEQUENCE = 0x1,
|
||||
MPEG2_EXTENSION_SEQUENCE_DISPLAY = 0x2,
|
||||
MPEG2_EXTENSION_QUANT_MATRIX = 0x3,
|
||||
MPEG2_EXTENSION_COPYRIGHT = 0x4,
|
||||
MPEG2_EXTENSION_SEQUENCE_SCALABLE = 0x5,
|
||||
MPEG2_EXTENSION_PICTURE_DISPLAY = 0x7,
|
||||
MPEG2_EXTENSION_PICTURE_CODING = 0x8,
|
||||
MPEG2_EXTENSION_PICTURE_SPATIAL_SCALABLE = 0x9,
|
||||
MPEG2_EXTENSION_PICTURE_TEMPORAL_SCALABLE = 0xa,
|
||||
MPEG2_EXTENSION_CAMAERA_PARAMETERS = 0xb,
|
||||
MPEG2_EXTENSION_ITU_T = 0xc,
|
||||
};
|
||||
|
||||
|
||||
typedef struct MPEG2RawSequenceHeader {
|
||||
uint8_t sequence_header_code;
|
||||
|
||||
uint16_t horizontal_size_value;
|
||||
uint16_t vertical_size_value;
|
||||
uint8_t aspect_ratio_information;
|
||||
uint8_t frame_rate_code;
|
||||
uint32_t bit_rate_value;
|
||||
uint16_t vbv_buffer_size_value;
|
||||
uint8_t constrained_parameters_flag;
|
||||
|
||||
uint8_t load_intra_quantiser_matrix;
|
||||
uint8_t intra_quantiser_matrix[64];
|
||||
uint8_t load_non_intra_quantiser_matrix;
|
||||
uint8_t non_intra_quantiser_matrix[64];
|
||||
} MPEG2RawSequenceHeader;
|
||||
|
||||
typedef struct MPEG2RawUserData {
|
||||
uint8_t user_data_start_code;
|
||||
|
||||
uint8_t *user_data;
|
||||
size_t user_data_length;
|
||||
} MPEG2RawUserData;
|
||||
|
||||
typedef struct MPEG2RawSequenceExtension {
|
||||
uint8_t profile_and_level_indication;
|
||||
uint8_t progressive_sequence;
|
||||
uint8_t chroma_format;
|
||||
uint8_t horizontal_size_extension;
|
||||
uint8_t vertical_size_extension;
|
||||
uint16_t bit_rate_extension;
|
||||
uint8_t vbv_buffer_size_extension;
|
||||
uint8_t low_delay;
|
||||
uint8_t frame_rate_extension_n;
|
||||
uint8_t frame_rate_extension_d;
|
||||
} MPEG2RawSequenceExtension;
|
||||
|
||||
typedef struct MPEG2RawSequenceDisplayExtension {
|
||||
uint8_t video_format;
|
||||
|
||||
uint8_t colour_description;
|
||||
uint8_t colour_primaries;
|
||||
uint8_t transfer_characteristics;
|
||||
uint8_t matrix_coefficients;
|
||||
|
||||
uint16_t display_horizontal_size;
|
||||
uint16_t display_vertical_size;
|
||||
} MPEG2RawSequenceDisplayExtension;
|
||||
|
||||
typedef struct MPEG2RawGroupOfPicturesHeader {
|
||||
uint8_t group_start_code;
|
||||
|
||||
uint32_t time_code;
|
||||
uint8_t closed_gop;
|
||||
uint8_t broken_link;
|
||||
} MPEG2RawGroupOfPicturesHeader;
|
||||
|
||||
typedef struct MPEG2RawPictureHeader {
|
||||
uint8_t picture_start_code;
|
||||
|
||||
uint16_t temporal_reference;
|
||||
uint8_t picture_coding_type;
|
||||
uint16_t vbv_delay;
|
||||
|
||||
uint8_t full_pel_forward_vector;
|
||||
uint8_t forward_f_code;
|
||||
uint8_t full_pel_backward_vector;
|
||||
uint8_t backward_f_code;
|
||||
|
||||
uint8_t extra_bit_picture;
|
||||
} MPEG2RawPictureHeader;
|
||||
|
||||
typedef struct MPEG2RawPictureCodingExtension {
|
||||
uint8_t f_code[2][2];
|
||||
|
||||
uint8_t intra_dc_precision;
|
||||
uint8_t picture_structure;
|
||||
uint8_t top_field_first;
|
||||
uint8_t frame_pred_frame_dct;
|
||||
uint8_t concealment_motion_vectors;
|
||||
uint8_t q_scale_type;
|
||||
uint8_t intra_vlc_format;
|
||||
uint8_t alternate_scan;
|
||||
uint8_t repeat_first_field;
|
||||
uint8_t chroma_420_type;
|
||||
uint8_t progressive_frame;
|
||||
|
||||
uint8_t composite_display_flag;
|
||||
uint8_t v_axis;
|
||||
uint8_t field_sequence;
|
||||
uint8_t sub_carrier;
|
||||
uint8_t burst_amplitude;
|
||||
uint8_t sub_carrier_phase;
|
||||
} MPEG2RawPictureCodingExtension;
|
||||
|
||||
typedef struct MPEG2RawQuantMatrixExtension {
|
||||
uint8_t load_intra_quantiser_matrix;
|
||||
uint8_t intra_quantiser_matrix[64];
|
||||
uint8_t load_non_intra_quantiser_matrix;
|
||||
uint8_t non_intra_quantiser_matrix[64];
|
||||
uint8_t load_chroma_intra_quantiser_matrix;
|
||||
uint8_t chroma_intra_quantiser_matrix[64];
|
||||
uint8_t load_chroma_non_intra_quantiser_matrix;
|
||||
uint8_t chroma_non_intra_quantiser_matrix[64];
|
||||
} MPEG2RawQuantMatrixExtension;
|
||||
|
||||
typedef struct MPEG2RawPictureDisplayExtension {
|
||||
uint16_t frame_centre_horizontal_offset[3];
|
||||
uint16_t frame_centre_vertical_offset[3];
|
||||
} MPEG2RawPictureDisplayExtension;
|
||||
|
||||
typedef struct MPEG2RawExtensionData {
|
||||
uint8_t extension_start_code;
|
||||
uint8_t extension_start_code_identifier;
|
||||
|
||||
union {
|
||||
MPEG2RawSequenceExtension sequence;
|
||||
MPEG2RawSequenceDisplayExtension sequence_display;
|
||||
MPEG2RawQuantMatrixExtension quant_matrix;
|
||||
MPEG2RawPictureCodingExtension picture_coding;
|
||||
MPEG2RawPictureDisplayExtension picture_display;
|
||||
} data;
|
||||
} MPEG2RawExtensionData;
|
||||
|
||||
typedef struct MPEG2RawSliceHeader {
|
||||
uint8_t slice_vertical_position;
|
||||
|
||||
uint8_t slice_vertical_position_extension;
|
||||
uint8_t priority_breakpoint;
|
||||
|
||||
uint8_t quantiser_scale_code;
|
||||
|
||||
uint8_t slice_extension_flag;
|
||||
uint8_t intra_slice;
|
||||
uint8_t slice_picture_id_enable;
|
||||
uint8_t slice_picture_id;
|
||||
|
||||
uint8_t extra_bit_slice;
|
||||
|
||||
size_t extra_information_length;
|
||||
uint8_t *extra_information;
|
||||
} MPEG2RawSliceHeader;
|
||||
|
||||
typedef struct MPEG2RawSlice {
|
||||
MPEG2RawSliceHeader header;
|
||||
|
||||
uint8_t *data;
|
||||
size_t data_size;
|
||||
int data_bit_start;
|
||||
} MPEG2RawSlice;
|
||||
|
||||
|
||||
typedef struct CodedBitstreamMPEG2Context {
|
||||
// Elements stored in headers which are required for other decoding.
|
||||
uint16_t horizontal_size;
|
||||
uint16_t vertical_size;
|
||||
uint8_t scalable;
|
||||
uint8_t scalable_mode;
|
||||
uint8_t progressive_sequence;
|
||||
uint8_t number_of_frame_centre_offsets;
|
||||
|
||||
// Write buffer.
|
||||
uint8_t *write_buffer;
|
||||
size_t write_buffer_size;
|
||||
} CodedBitstreamMPEG2Context;
|
||||
|
||||
|
||||
#endif /* AVCODEC_CBS_MPEG2_H */
|
||||
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
static int FUNC(sequence_header)(CodedBitstreamContext *ctx, RWContext *rw,
|
||||
MPEG2RawSequenceHeader *current)
|
||||
{
|
||||
CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data;
|
||||
int err, i;
|
||||
|
||||
HEADER("Sequence Header");
|
||||
|
||||
ui(8, sequence_header_code);
|
||||
|
||||
ui(12, horizontal_size_value);
|
||||
ui(12, vertical_size_value);
|
||||
|
||||
mpeg2->horizontal_size = current->horizontal_size_value;
|
||||
mpeg2->vertical_size = current->vertical_size_value;
|
||||
|
||||
ui(4, aspect_ratio_information);
|
||||
ui(4, frame_rate_code);
|
||||
ui(18, bit_rate_value);
|
||||
|
||||
marker_bit();
|
||||
|
||||
ui(10, vbv_buffer_size_value);
|
||||
ui(1, constrained_parameters_flag);
|
||||
|
||||
ui(1, load_intra_quantiser_matrix);
|
||||
if (current->load_intra_quantiser_matrix) {
|
||||
for (i = 0; i < 64; i++)
|
||||
ui(8, intra_quantiser_matrix[i]);
|
||||
}
|
||||
|
||||
ui(1, load_non_intra_quantiser_matrix);
|
||||
if (current->load_non_intra_quantiser_matrix) {
|
||||
for (i = 0; i < 64; i++)
|
||||
ui(8, non_intra_quantiser_matrix[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FUNC(user_data)(CodedBitstreamContext *ctx, RWContext *rw,
|
||||
MPEG2RawUserData *current)
|
||||
{
|
||||
size_t k;
|
||||
int err;
|
||||
|
||||
HEADER("User Data");
|
||||
|
||||
ui(8, user_data_start_code);
|
||||
|
||||
#ifdef READ
|
||||
k = get_bits_left(rw);
|
||||
av_assert0(k % 8 == 0);
|
||||
current->user_data_length = k /= 8;
|
||||
if (k > 0) {
|
||||
current->user_data = av_malloc(k);
|
||||
if (!current->user_data)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (k = 0; k < current->user_data_length; k++)
|
||||
xui(8, user_data, current->user_data[k]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FUNC(sequence_extension)(CodedBitstreamContext *ctx, RWContext *rw,
|
||||
MPEG2RawSequenceExtension *current)
|
||||
{
|
||||
CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data;
|
||||
int err;
|
||||
|
||||
HEADER("Sequence Extension");
|
||||
|
||||
ui(8, profile_and_level_indication);
|
||||
ui(1, progressive_sequence);
|
||||
ui(2, chroma_format);
|
||||
ui(2, horizontal_size_extension);
|
||||
ui(2, vertical_size_extension);
|
||||
|
||||
mpeg2->horizontal_size = (mpeg2->horizontal_size & 0xfff) |
|
||||
current->horizontal_size_extension << 12;
|
||||
mpeg2->vertical_size = (mpeg2->vertical_size & 0xfff) |
|
||||
current->vertical_size_extension << 12;
|
||||
mpeg2->progressive_sequence = current->progressive_sequence;
|
||||
|
||||
ui(12, bit_rate_extension);
|
||||
marker_bit();
|
||||
ui(8, vbv_buffer_size_extension);
|
||||
ui(1, low_delay);
|
||||
ui(2, frame_rate_extension_n);
|
||||
ui(5, frame_rate_extension_d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FUNC(sequence_display_extension)(CodedBitstreamContext *ctx, RWContext *rw,
|
||||
MPEG2RawSequenceDisplayExtension *current)
|
||||
{
|
||||
int err;
|
||||
|
||||
HEADER("Sequence Display Extension");
|
||||
|
||||
ui(3, video_format);
|
||||
|
||||
ui(1, colour_description);
|
||||
if (current->colour_description) {
|
||||
ui(8, colour_primaries);
|
||||
ui(8, transfer_characteristics);
|
||||
ui(8, matrix_coefficients);
|
||||
}
|
||||
|
||||
ui(14, display_horizontal_size);
|
||||
marker_bit();
|
||||
ui(14, display_vertical_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FUNC(group_of_pictures_header)(CodedBitstreamContext *ctx, RWContext *rw,
|
||||
MPEG2RawGroupOfPicturesHeader *current)
|
||||
{
|
||||
int err;
|
||||
|
||||
HEADER("Group of Pictures Header");
|
||||
|
||||
ui(8, group_start_code);
|
||||
|
||||
ui(25, time_code);
|
||||
ui(1, closed_gop);
|
||||
ui(1, broken_link);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FUNC(picture_header)(CodedBitstreamContext *ctx, RWContext *rw,
|
||||
MPEG2RawPictureHeader *current)
|
||||
{
|
||||
int err;
|
||||
|
||||
HEADER("Picture Header");
|
||||
|
||||
ui(8, picture_start_code);
|
||||
|
||||
ui(10, temporal_reference);
|
||||
ui(3, picture_coding_type);
|
||||
ui(16, vbv_delay);
|
||||
|
||||
if (current->picture_coding_type == 2 ||
|
||||
current->picture_coding_type == 3) {
|
||||
ui(1, full_pel_forward_vector);
|
||||
ui(3, forward_f_code);
|
||||
}
|
||||
|
||||
if (current->picture_coding_type == 3) {
|
||||
ui(1, full_pel_backward_vector);
|
||||
ui(3, backward_f_code);
|
||||
}
|
||||
|
||||
ui(1, extra_bit_picture);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FUNC(picture_coding_extension)(CodedBitstreamContext *ctx, RWContext *rw,
|
||||
MPEG2RawPictureCodingExtension *current)
|
||||
{
|
||||
CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data;
|
||||
int err;
|
||||
|
||||
HEADER("Picture Coding Extension");
|
||||
|
||||
ui(4, f_code[0][0]);
|
||||
ui(4, f_code[0][1]);
|
||||
ui(4, f_code[1][0]);
|
||||
ui(4, f_code[1][1]);
|
||||
|
||||
ui(2, intra_dc_precision);
|
||||
ui(2, picture_structure);
|
||||
ui(1, top_field_first);
|
||||
ui(1, frame_pred_frame_dct);
|
||||
ui(1, concealment_motion_vectors);
|
||||
ui(1, q_scale_type);
|
||||
ui(1, intra_vlc_format);
|
||||
ui(1, alternate_scan);
|
||||
ui(1, repeat_first_field);
|
||||
ui(1, chroma_420_type);
|
||||
ui(1, progressive_frame);
|
||||
|
||||
if (mpeg2->progressive_sequence) {
|
||||
if (current->repeat_first_field) {
|
||||
if (current->top_field_first)
|
||||
mpeg2->number_of_frame_centre_offsets = 3;
|
||||
else
|
||||
mpeg2->number_of_frame_centre_offsets = 2;
|
||||
} else {
|
||||
mpeg2->number_of_frame_centre_offsets = 1;
|
||||
}
|
||||
} else {
|
||||
if (current->picture_structure == 1 || // Top field.
|
||||
current->picture_structure == 2) { // Bottom field.
|
||||
mpeg2->number_of_frame_centre_offsets = 1;
|
||||
} else {
|
||||
if (current->repeat_first_field)
|
||||
mpeg2->number_of_frame_centre_offsets = 3;
|
||||
else
|
||||
mpeg2->number_of_frame_centre_offsets = 2;
|
||||
}
|
||||
}
|
||||
|
||||
ui(1, composite_display_flag);
|
||||
if (current->composite_display_flag) {
|
||||
ui(1, v_axis);
|
||||
ui(3, field_sequence);
|
||||
ui(1, sub_carrier);
|
||||
ui(7, burst_amplitude);
|
||||
ui(8, sub_carrier_phase);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FUNC(quant_matrix_extension)(CodedBitstreamContext *ctx, RWContext *rw,
|
||||
MPEG2RawQuantMatrixExtension *current)
|
||||
{
|
||||
int err, i;
|
||||
|
||||
HEADER("Quant Matrix Extension");
|
||||
|
||||
ui(1, load_intra_quantiser_matrix);
|
||||
if (current->load_intra_quantiser_matrix) {
|
||||
for (i = 0; i < 64; i++)
|
||||
ui(8, intra_quantiser_matrix[i]);
|
||||
}
|
||||
|
||||
ui(1, load_non_intra_quantiser_matrix);
|
||||
if (current->load_non_intra_quantiser_matrix) {
|
||||
for (i = 0; i < 64; i++)
|
||||
ui(8, non_intra_quantiser_matrix[i]);
|
||||
}
|
||||
|
||||
ui(1, load_chroma_intra_quantiser_matrix);
|
||||
if (current->load_chroma_intra_quantiser_matrix) {
|
||||
for (i = 0; i < 64; i++)
|
||||
ui(8, intra_quantiser_matrix[i]);
|
||||
}
|
||||
|
||||
ui(1, load_chroma_non_intra_quantiser_matrix);
|
||||
if (current->load_chroma_non_intra_quantiser_matrix) {
|
||||
for (i = 0; i < 64; i++)
|
||||
ui(8, chroma_non_intra_quantiser_matrix[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FUNC(picture_display_extension)(CodedBitstreamContext *ctx, RWContext *rw,
|
||||
MPEG2RawPictureDisplayExtension *current)
|
||||
{
|
||||
CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data;
|
||||
int err, i;
|
||||
|
||||
HEADER("Picture Display Extension");
|
||||
|
||||
for (i = 0; i < mpeg2->number_of_frame_centre_offsets; i++) {
|
||||
ui(16, frame_centre_horizontal_offset[i]);
|
||||
marker_bit();
|
||||
ui(16, frame_centre_vertical_offset[i]);
|
||||
marker_bit();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FUNC(extension_data)(CodedBitstreamContext *ctx, RWContext *rw,
|
||||
MPEG2RawExtensionData *current)
|
||||
{
|
||||
int err;
|
||||
|
||||
HEADER("Extension Data");
|
||||
|
||||
ui(8, extension_start_code);
|
||||
ui(4, extension_start_code_identifier);
|
||||
|
||||
switch (current->extension_start_code_identifier) {
|
||||
case 1:
|
||||
return FUNC(sequence_extension)
|
||||
(ctx, rw, ¤t->data.sequence);
|
||||
case 2:
|
||||
return FUNC(sequence_display_extension)
|
||||
(ctx, rw, ¤t->data.sequence_display);
|
||||
case 3:
|
||||
return FUNC(quant_matrix_extension)
|
||||
(ctx, rw, ¤t->data.quant_matrix);
|
||||
case 7:
|
||||
return FUNC(picture_display_extension)
|
||||
(ctx, rw, ¤t->data.picture_display);
|
||||
case 8:
|
||||
return FUNC(picture_coding_extension)
|
||||
(ctx, rw, ¤t->data.picture_coding);
|
||||
default:
|
||||
av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid extension ID %d.\n",
|
||||
current->extension_start_code_identifier);
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
}
|
||||
|
||||
static int FUNC(slice_header)(CodedBitstreamContext *ctx, RWContext *rw,
|
||||
MPEG2RawSliceHeader *current)
|
||||
{
|
||||
CodedBitstreamMPEG2Context *mpeg2 = ctx->priv_data;
|
||||
int err;
|
||||
|
||||
HEADER("Slice Header");
|
||||
|
||||
ui(8, slice_vertical_position);
|
||||
|
||||
if (mpeg2->vertical_size > 2800)
|
||||
ui(3, slice_vertical_position_extension);
|
||||
if (mpeg2->scalable) {
|
||||
if (mpeg2->scalable_mode == 0)
|
||||
ui(7, priority_breakpoint);
|
||||
}
|
||||
|
||||
ui(5, quantiser_scale_code);
|
||||
|
||||
if (nextbits(1, 1, current->slice_extension_flag)) {
|
||||
ui(1, slice_extension_flag);
|
||||
ui(1, intra_slice);
|
||||
ui(1, slice_picture_id_enable);
|
||||
ui(6, slice_picture_id);
|
||||
|
||||
{
|
||||
size_t k;
|
||||
#ifdef READ
|
||||
GetBitContext start;
|
||||
uint8_t bit;
|
||||
start = *rw;
|
||||
for (k = 0; nextbits(1, 1, bit); k++)
|
||||
skip_bits(rw, 8);
|
||||
current->extra_information_length = k;
|
||||
if (k > 0) {
|
||||
*rw = start;
|
||||
current->extra_information =
|
||||
av_malloc(current->extra_information_length);
|
||||
if (!current->extra_information)
|
||||
return AVERROR(ENOMEM);
|
||||
for (k = 0; k < current->extra_information_length; k++) {
|
||||
xui(1, extra_bit_slice, bit);
|
||||
xui(8, extra_information_slice,
|
||||
current->extra_information[k]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (k = 0; k < current->extra_information_length; k++) {
|
||||
xui(1, extra_bit_slice, 1);
|
||||
xui(8, extra_information_slice, current->extra_information[k]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
ui(1, extra_bit_slice);
|
||||
|
||||
return 0;
|
||||
}
|
||||
+88
-56
@@ -20,24 +20,39 @@
|
||||
|
||||
/**
|
||||
* @file
|
||||
* CFHD Video Decoder
|
||||
* Cineform HD video decoder
|
||||
*/
|
||||
|
||||
#include "libavutil/attributes.h"
|
||||
#include "libavutil/buffer.h"
|
||||
#include "libavutil/common.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
#include "libavutil/imgutils.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
#include "libavutil/opt.h"
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "internal.h"
|
||||
#include "bytestream.h"
|
||||
#include "get_bits.h"
|
||||
#include "internal.h"
|
||||
#include "thread.h"
|
||||
#include "cfhd.h"
|
||||
|
||||
#define SUBBAND_COUNT 10
|
||||
enum CFHDParam {
|
||||
ChannelCount = 12,
|
||||
SubbandCount = 14,
|
||||
ImageWidth = 20,
|
||||
ImageHeight = 21,
|
||||
LowpassPrecision = 35,
|
||||
SubbandNumber = 48,
|
||||
Quantization = 53,
|
||||
ChannelNumber = 62,
|
||||
BitsPerComponent = 101,
|
||||
ChannelWidth = 104,
|
||||
ChannelHeight = 105,
|
||||
PrescaleShift = 109,
|
||||
};
|
||||
|
||||
static av_cold int cfhd_decode_init(AVCodecContext *avctx)
|
||||
static av_cold int cfhd_init(AVCodecContext *avctx)
|
||||
{
|
||||
CFHDContext *s = avctx->priv_data;
|
||||
|
||||
@@ -58,9 +73,10 @@ static void init_frame_defaults(CFHDContext *s)
|
||||
{
|
||||
s->coded_width = 0;
|
||||
s->coded_height = 0;
|
||||
s->cropped_height = 0;
|
||||
s->bpc = 10;
|
||||
s->channel_cnt = 4;
|
||||
s->subband_cnt = 10;
|
||||
s->subband_cnt = SUBBAND_COUNT;
|
||||
s->channel_num = 0;
|
||||
s->lowpass_precision = 16;
|
||||
s->quantisation = 1;
|
||||
@@ -74,15 +90,18 @@ static void init_frame_defaults(CFHDContext *s)
|
||||
static inline int dequant_and_decompand(int level, int quantisation)
|
||||
{
|
||||
int64_t abslevel = abs(level);
|
||||
return (abslevel + ((768 * abslevel * abslevel * abslevel) / (255 * 255 * 255))) * FFSIGN(level) * quantisation;
|
||||
return (abslevel + ((768 * abslevel * abslevel * abslevel) / (255 * 255 * 255))) *
|
||||
FFSIGN(level) * quantisation;
|
||||
}
|
||||
|
||||
static inline void filter(int16_t *output, ptrdiff_t out_stride, int16_t *low, ptrdiff_t low_stride,
|
||||
int16_t *high, ptrdiff_t high_stride, int len, uint8_t clip)
|
||||
static inline void filter(int16_t *output, ptrdiff_t out_stride,
|
||||
int16_t *low, ptrdiff_t low_stride,
|
||||
int16_t *high, ptrdiff_t high_stride,
|
||||
int len, int clip)
|
||||
{
|
||||
int16_t tmp;
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (i == 0) {
|
||||
tmp = (11*low[0*low_stride] - 4*low[1*low_stride] + low[2*low_stride] + 4) >> 3;
|
||||
@@ -118,28 +137,30 @@ static inline void filter(int16_t *output, ptrdiff_t out_stride, int16_t *low, p
|
||||
}
|
||||
}
|
||||
|
||||
static void horiz_filter(int16_t *output, int16_t *low, int16_t *high, int width)
|
||||
static void horiz_filter(int16_t *output, int16_t *low, int16_t *high,
|
||||
int width)
|
||||
{
|
||||
filter(output, 1, low, 1, high, 1, width, 0);
|
||||
}
|
||||
|
||||
static void horiz_filter_clip(int16_t *output, int16_t *low, int16_t *high, int width, uint8_t clip)
|
||||
static void horiz_filter_clip(int16_t *output, int16_t *low, int16_t *high,
|
||||
int width, int clip)
|
||||
{
|
||||
filter(output, 1, low, 1, high, 1, width, clip);
|
||||
}
|
||||
|
||||
static void vert_filter(int16_t *output, int out_stride, int16_t *low, int low_stride,
|
||||
int16_t *high, int high_stride, int len)
|
||||
static void vert_filter(int16_t *output, ptrdiff_t out_stride,
|
||||
int16_t *low, ptrdiff_t low_stride,
|
||||
int16_t *high, ptrdiff_t high_stride, int len)
|
||||
{
|
||||
filter(output, out_stride, low, low_stride, high, high_stride, len, 0);
|
||||
}
|
||||
|
||||
static void free_buffers(AVCodecContext *avctx)
|
||||
static void free_buffers(CFHDContext *s)
|
||||
{
|
||||
CFHDContext *s = avctx->priv_data;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(s->plane); i++) {
|
||||
av_freep(&s->plane[i].idwt_buf);
|
||||
av_freep(&s->plane[i].idwt_tmp);
|
||||
|
||||
@@ -156,37 +177,43 @@ static void free_buffers(AVCodecContext *avctx)
|
||||
static int alloc_buffers(AVCodecContext *avctx)
|
||||
{
|
||||
CFHDContext *s = avctx->priv_data;
|
||||
int i, j, k, ret, planes;
|
||||
int i, j, ret, planes;
|
||||
int chroma_x_shift, chroma_y_shift;
|
||||
unsigned k;
|
||||
|
||||
if ((ret = ff_set_dimensions(avctx, s->coded_width, s->coded_height)) < 0)
|
||||
return ret;
|
||||
avctx->pix_fmt = s->coded_format;
|
||||
|
||||
avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_x_shift, &s->chroma_y_shift);
|
||||
planes = av_pix_fmt_count_planes(avctx->pix_fmt);
|
||||
if ((ret = av_pix_fmt_get_chroma_sub_sample(s->coded_format,
|
||||
&chroma_x_shift,
|
||||
&chroma_y_shift)) < 0)
|
||||
return ret;
|
||||
planes = av_pix_fmt_count_planes(s->coded_format);
|
||||
|
||||
for (i = 0; i < planes; i++) {
|
||||
int width = i ? avctx->width >> s->chroma_x_shift : avctx->width;
|
||||
int height = i ? avctx->height >> s->chroma_y_shift : avctx->height;
|
||||
int stride = FFALIGN(width / 8, 8) * 8;
|
||||
int w8, h8, w4, h4, w2, h2;
|
||||
height = FFALIGN(height / 8, 2) * 8;
|
||||
s->plane[i].width = width;
|
||||
int width = i ? avctx->width >> chroma_x_shift : avctx->width;
|
||||
int height = i ? avctx->height >> chroma_y_shift : avctx->height;
|
||||
ptrdiff_t stride = FFALIGN(width / 8, 8) * 8;
|
||||
height = FFALIGN(height / 8, 2) * 8;
|
||||
s->plane[i].width = width;
|
||||
s->plane[i].height = height;
|
||||
s->plane[i].stride = stride;
|
||||
|
||||
w8 = FFALIGN(s->plane[i].width / 8, 8);
|
||||
w8 = FFALIGN(s->plane[i].width / 8, 8);
|
||||
h8 = FFALIGN(s->plane[i].height / 8, 2);
|
||||
w4 = w8 * 2;
|
||||
h4 = h8 * 2;
|
||||
w2 = w4 * 2;
|
||||
h2 = h4 * 2;
|
||||
|
||||
s->plane[i].idwt_buf = av_mallocz_array(height * stride, sizeof(*s->plane[i].idwt_buf));
|
||||
s->plane[i].idwt_tmp = av_malloc_array(height * stride, sizeof(*s->plane[i].idwt_tmp));
|
||||
if (!s->plane[i].idwt_buf || !s->plane[i].idwt_tmp) {
|
||||
s->plane[i].idwt_buf =
|
||||
av_mallocz_array(height * stride, sizeof(*s->plane[i].idwt_buf));
|
||||
s->plane[i].idwt_tmp =
|
||||
av_malloc_array(height * stride, sizeof(*s->plane[i].idwt_tmp));
|
||||
if (!s->plane[i].idwt_buf || !s->plane[i].idwt_tmp)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
s->plane[i].subband[0] = s->plane[i].idwt_buf;
|
||||
s->plane[i].subband[1] = s->plane[i].idwt_buf + 2 * w8 * h8;
|
||||
@@ -200,7 +227,7 @@ static int alloc_buffers(AVCodecContext *avctx)
|
||||
s->plane[i].subband[9] = s->plane[i].idwt_buf + 3 * w2 * h2;
|
||||
|
||||
for (j = 0; j < DWT_LEVELS; j++) {
|
||||
for(k = 0; k < 4; k++) {
|
||||
for (k = 0; k < FF_ARRAY_ELEMS(s->plane[i].band[j]); k++) {
|
||||
s->plane[i].band[j][k].a_width = w8 << j;
|
||||
s->plane[i].band[j][k].a_height = h8 << j;
|
||||
}
|
||||
@@ -209,10 +236,10 @@ static int alloc_buffers(AVCodecContext *avctx)
|
||||
/* ll2 and ll1 commented out because they are done in-place */
|
||||
s->plane[i].l_h[0] = s->plane[i].idwt_tmp;
|
||||
s->plane[i].l_h[1] = s->plane[i].idwt_tmp + 2 * w8 * h8;
|
||||
//s->plane[i].l_h[2] = ll2;
|
||||
// s->plane[i].l_h[2] = ll2;
|
||||
s->plane[i].l_h[3] = s->plane[i].idwt_tmp;
|
||||
s->plane[i].l_h[4] = s->plane[i].idwt_tmp + 2 * w4 * h4;
|
||||
//s->plane[i].l_h[5] = ll1;
|
||||
// s->plane[i].l_h[5] = ll1;
|
||||
s->plane[i].l_h[6] = s->plane[i].idwt_tmp;
|
||||
s->plane[i].l_h[7] = s->plane[i].idwt_tmp + 2 * w2 * h2;
|
||||
}
|
||||
@@ -250,10 +277,10 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
|
||||
uint16_t data = bytestream2_get_be16(&gb);
|
||||
if (abs_tag8 >= 0x60 && abs_tag8 <= 0x6f) {
|
||||
av_log(avctx, AV_LOG_DEBUG, "large len %x\n", ((tagu & 0xff) << 16) | data);
|
||||
} else if (tag == 20) {
|
||||
} else if (tag == ImageWidth) {
|
||||
av_log(avctx, AV_LOG_DEBUG, "Width %"PRIu16"\n", data);
|
||||
s->coded_width = data;
|
||||
} else if (tag == 21) {
|
||||
} else if (tag == ImageHeight) {
|
||||
av_log(avctx, AV_LOG_DEBUG, "Height %"PRIu16"\n", data);
|
||||
s->coded_height = data;
|
||||
} else if (tag == 101) {
|
||||
@@ -264,7 +291,7 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
|
||||
break;
|
||||
}
|
||||
s->bpc = data;
|
||||
} else if (tag == 12) {
|
||||
} else if (tag == ChannelCount) {
|
||||
av_log(avctx, AV_LOG_DEBUG, "Channel Count: %"PRIu16"\n", data);
|
||||
s->channel_cnt = data;
|
||||
if (data > 4) {
|
||||
@@ -272,14 +299,14 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
|
||||
ret = AVERROR_PATCHWELCOME;
|
||||
break;
|
||||
}
|
||||
} else if (tag == 14) {
|
||||
} else if (tag == SubbandCount) {
|
||||
av_log(avctx, AV_LOG_DEBUG, "Subband Count: %"PRIu16"\n", data);
|
||||
if (data != SUBBAND_COUNT) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Subband Count of %"PRIu16" is unsupported\n", data);
|
||||
ret = AVERROR_PATCHWELCOME;
|
||||
break;
|
||||
}
|
||||
} else if (tag == 62) {
|
||||
} else if (tag == ChannelNumber) {
|
||||
s->channel_num = data;
|
||||
av_log(avctx, AV_LOG_DEBUG, "Channel number %"PRIu16"\n", data);
|
||||
if (s->channel_num >= planes) {
|
||||
@@ -288,7 +315,7 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
|
||||
break;
|
||||
}
|
||||
init_plane_defaults(s);
|
||||
} else if (tag == 48) {
|
||||
} else if (tag == SubbandNumber) {
|
||||
if (s->subband_num != 0 && data == 1) // hack
|
||||
s->level++;
|
||||
av_log(avctx, AV_LOG_DEBUG, "Subband number %"PRIu16"\n", data);
|
||||
@@ -311,12 +338,12 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
|
||||
ret = AVERROR(EINVAL);
|
||||
break;
|
||||
}
|
||||
} else if (tag == 35)
|
||||
} else if (tag == LowpassPrecision)
|
||||
av_log(avctx, AV_LOG_DEBUG, "Lowpass precision bits: %"PRIu16"\n", data);
|
||||
else if (tag == 53) {
|
||||
else if (tag == Quantization) {
|
||||
s->quantisation = data;
|
||||
av_log(avctx, AV_LOG_DEBUG, "Quantisation: %"PRIu16"\n", data);
|
||||
} else if (tag == 109) {
|
||||
} else if (tag == PrescaleShift) {
|
||||
s->prescale_shift[0] = (data >> 0) & 0x7;
|
||||
s->prescale_shift[1] = (data >> 3) & 0x7;
|
||||
s->prescale_shift[2] = (data >> 6) & 0x7;
|
||||
@@ -429,6 +456,9 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
|
||||
break;
|
||||
}
|
||||
planes = av_pix_fmt_count_planes(s->coded_format);
|
||||
} else if (tag == -85) {
|
||||
av_log(avctx, AV_LOG_DEBUG, "Cropped height %"PRIu16"\n", data);
|
||||
s->cropped_height = data;
|
||||
} else
|
||||
av_log(avctx, AV_LOG_DEBUG, "Unknown tag %i data %x\n", tag, data);
|
||||
|
||||
@@ -437,15 +467,17 @@ static int cfhd_decode(AVCodecContext *avctx, void *data, int *got_frame,
|
||||
s->coded_format != AV_PIX_FMT_NONE) {
|
||||
if (s->a_width != s->coded_width || s->a_height != s->coded_height ||
|
||||
s->a_format != s->coded_format) {
|
||||
free_buffers(avctx);
|
||||
free_buffers(s);
|
||||
if ((ret = alloc_buffers(avctx)) < 0) {
|
||||
free_buffers(avctx);
|
||||
free_buffers(s);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = ff_set_dimensions(avctx, s->coded_width, s->coded_height);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (s->cropped_height)
|
||||
avctx->height = s->cropped_height;
|
||||
frame.f->width =
|
||||
frame.f->height = 0;
|
||||
|
||||
@@ -775,11 +807,11 @@ end:
|
||||
return avpkt->size;
|
||||
}
|
||||
|
||||
static av_cold int cfhd_close_decoder(AVCodecContext *avctx)
|
||||
static av_cold int cfhd_close(AVCodecContext *avctx)
|
||||
{
|
||||
CFHDContext *s = avctx->priv_data;
|
||||
|
||||
free_buffers(avctx);
|
||||
free_buffers(s);
|
||||
|
||||
if (!avctx->internal->is_copy) {
|
||||
ff_free_vlc(&s->vlc_9);
|
||||
@@ -790,14 +822,14 @@ static av_cold int cfhd_close_decoder(AVCodecContext *avctx)
|
||||
}
|
||||
|
||||
AVCodec ff_cfhd_decoder = {
|
||||
.name = "cfhd",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Cineform HD"),
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_CFHD,
|
||||
.priv_data_size = sizeof(CFHDContext),
|
||||
.init = cfhd_decode_init,
|
||||
.close = cfhd_close_decoder,
|
||||
.decode = cfhd_decode,
|
||||
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
|
||||
.name = "cfhd",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Cineform HD"),
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_CFHD,
|
||||
.priv_data_size = sizeof(CFHDContext),
|
||||
.init = cfhd_init,
|
||||
.close = cfhd_close,
|
||||
.decode = cfhd_decode,
|
||||
.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
|
||||
};
|
||||
|
||||
+8
-11
@@ -27,10 +27,10 @@
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "get_bits.h"
|
||||
#include "vlc.h"
|
||||
|
||||
#define VLC_BITS 9
|
||||
#define NB_VLC_TABLE_9 (71+3)
|
||||
#define NB_VLC_TABLE_18 (263+1)
|
||||
#define VLC_BITS 9
|
||||
#define SUBBAND_COUNT 10
|
||||
|
||||
typedef struct CFHD_RL_VLC_ELEM {
|
||||
int16_t level;
|
||||
@@ -43,7 +43,7 @@ typedef struct CFHD_RL_VLC_ELEM {
|
||||
typedef struct SubBand {
|
||||
int level;
|
||||
int orientation;
|
||||
int stride;
|
||||
ptrdiff_t stride;
|
||||
int a_width;
|
||||
int width;
|
||||
int a_height;
|
||||
@@ -62,7 +62,7 @@ typedef struct Plane {
|
||||
int16_t *idwt_tmp;
|
||||
|
||||
/* TODO: merge this into SubBand structure */
|
||||
int16_t *subband[10];
|
||||
int16_t *subband[SUBBAND_COUNT];
|
||||
int16_t *l_h[8];
|
||||
|
||||
SubBand band[DWT_LEVELS][4];
|
||||
@@ -79,18 +79,16 @@ typedef struct CFHDContext {
|
||||
|
||||
GetBitContext gb;
|
||||
|
||||
int chroma_x_shift;
|
||||
int chroma_y_shift;
|
||||
|
||||
int coded_width;
|
||||
int coded_height;
|
||||
int coded_format;
|
||||
int cropped_height;
|
||||
enum AVPixelFormat coded_format;
|
||||
|
||||
int a_width;
|
||||
int a_height;
|
||||
int a_format;
|
||||
|
||||
int bpc;
|
||||
int bpc; // bits per channel/component
|
||||
int channel_cnt;
|
||||
int subband_cnt;
|
||||
int channel_num;
|
||||
@@ -106,7 +104,6 @@ typedef struct CFHDContext {
|
||||
|
||||
uint8_t prescale_shift[3];
|
||||
Plane plane[4];
|
||||
|
||||
} CFHDContext;
|
||||
|
||||
int ff_cfhd_init_vlcs(CFHDContext *s);
|
||||
|
||||
+128
-80
@@ -18,7 +18,10 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "stdint.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavutil/attributes.h"
|
||||
|
||||
#include "cfhd.h"
|
||||
|
||||
/* some special codewords, not sure what they all mean */
|
||||
@@ -29,6 +32,31 @@
|
||||
#define TABLE_9_BAND_END3 0x38F0B3Eh
|
||||
#define TABLE_9_BAND_END_LEN3 26
|
||||
|
||||
#define NB_VLC_TABLE_9 (71 + 3)
|
||||
#define NB_VLC_TABLE_18 (263 + 1)
|
||||
|
||||
static const uint32_t table_9_vlc_bits[NB_VLC_TABLE_9] = {
|
||||
0, 0x2, 0xc, 0x1a,
|
||||
0x1d, 0x1e, 0x39, 0x3e,
|
||||
0x37, 0x7e, 0x6c, 0xe2,
|
||||
0xfe, 0xdb, 0xe0, 0x1c3,
|
||||
0x1c6, 0x1ff, 0x1fe, 0x1b5,
|
||||
0x369, 0x385, 0x71d, 0x6d0,
|
||||
0x708, 0x71f, 0xe3d, 0xe39,
|
||||
0xe13, 0xe12, 0x1c71, 0x1b45,
|
||||
0x1b47, 0x3689, 0x38f2, 0x38e1,
|
||||
0x38e0, 0x38f1, 0x3688, 0x6d1b,
|
||||
0x71e0, 0x6d19, 0x71e7, 0xe3cd,
|
||||
0xda35, 0xda30, 0xe3c3, 0x1b469,
|
||||
0x1b462, 0x1c798, 0x1b463, 0x1c799,
|
||||
0x38f08, 0x38f09, 0x38f0a, 0x6d1a0,
|
||||
0x6d1a3, 0x6d1a1, 0xda345, 0xda344,
|
||||
0xe3c2d, 0xe3c2f, 0xe3c2e, 0x38f0b2,
|
||||
0x71e160, 0x71e162, 0x71e166, 0x71e161,
|
||||
0xe3c2ce, 0xe3c2c6, 0xe3c2c7, 0x1C7859E,
|
||||
0x38F0B3F, 0x38F0B3E,
|
||||
};
|
||||
|
||||
static const uint8_t table_9_vlc_len[NB_VLC_TABLE_9] = {
|
||||
1, 2, 4, 5, 5, 5, 6, 6,
|
||||
6, 7, 7, 8, 8, 8, 8, 9,
|
||||
@@ -42,19 +70,6 @@ static const uint8_t table_9_vlc_len[NB_VLC_TABLE_9] = {
|
||||
26, 26,
|
||||
};
|
||||
|
||||
static const uint32_t table_9_vlc_bits[NB_VLC_TABLE_9] = {
|
||||
0, 0x2, 0xc, 0x1a, 0x1d, 0x1e, 0x39, 0x3e,
|
||||
0x37, 0x7e, 0x6c, 0xe2, 0xfe, 0xdb, 0xe0, 0x1c3,
|
||||
0x1c6, 0x1ff, 0x1fe, 0x1b5, 0x369, 0x385, 0x71d, 0x6d0,
|
||||
0x708, 0x71f, 0xe3d, 0xe39, 0xe13, 0xe12, 0x1c71, 0x1b45,
|
||||
0x1b47, 0x3689, 0x38f2, 0x38e1, 0x38e0, 0x38f1, 0x3688, 0x6d1b,
|
||||
0x71e0, 0x6d19, 0x71e7, 0xe3cd, 0xda35, 0xda30, 0xe3c3, 0x1b469,
|
||||
0x1b462, 0x1c798, 0x1b463, 0x1c799, 0x38f08, 0x38f09, 0x38f0a, 0x6d1a0,
|
||||
0x6d1a3, 0x6d1a1, 0xda345, 0xda344, 0xe3c2d, 0xe3c2f, 0xe3c2e, 0x38f0b2,
|
||||
0x71e160, 0x71e162, 0x71e166, 0x71e161, 0xe3c2ce, 0xe3c2c6, 0xe3c2c7, 0x1C7859E,
|
||||
0x38F0B3F, 0x38F0B3E,
|
||||
};
|
||||
|
||||
static const uint16_t table_9_vlc_run[NB_VLC_TABLE_9] = {
|
||||
1, 1, 1, 1, 12, 1, 32, 160,
|
||||
1, 1, 1, 320, 1, 1, 80, 120,
|
||||
@@ -82,39 +97,72 @@ static const uint8_t table_9_vlc_level[NB_VLC_TABLE_9] = {
|
||||
};
|
||||
|
||||
static const uint32_t table_18_vlc_bits[NB_VLC_TABLE_18] = {
|
||||
0, 0x2, 0x7, 0x19, 0x30, 0x36, 0x6f, 0x63,
|
||||
0x69, 0x6b, 0xd1, 0xd4, 0xdc, 0x189, 0x18a, 0x1a0,
|
||||
0x1ab, 0x377, 0x310, 0x316, 0x343, 0x354, 0x375, 0x623,
|
||||
0x684, 0x685, 0x6ab, 0x6ec, 0xddb, 0xc5c, 0xc5e, 0xc44,
|
||||
0xd55, 0xdd1, 0xdd3, 0x1bb5, 0x188b, 0x18bb, 0x18bf, 0x1aa8,
|
||||
0x1ba0, 0x1ba5, 0x1ba4, 0x3115, 0x3175, 0x317d, 0x3553, 0x3768,
|
||||
0x6e87, 0x6ed3, 0x62e8, 0x62f8, 0x6228, 0x6aa4, 0x6e85, 0xc453,
|
||||
0xc5d3, 0xc5f3, 0xdda4, 0xdd08, 0xdd0c, 0x1bb4b, 0x1bb4a, 0x18ba5,
|
||||
0x18be5, 0x1aa95, 0x1aa97, 0x188a4, 0x1ba13, 0x31748, 0x317c8, 0x35528,
|
||||
0x3552c, 0x37424, 0x37434, 0x37436, 0x62294, 0x62e92, 0x62f92, 0x6aa52,
|
||||
0x6aa5a, 0x6e86a, 0x6e86e, 0x6e84a, 0xc452a, 0xc5d27, 0xc5f26, 0xd54a6,
|
||||
0xd54b6, 0xdd096, 0xdd0d6, 0xdd0de, 0x188a56, 0x18ba4d, 0x18be4e, 0x18be4f,
|
||||
0x1aa96e, 0x1ba12e, 0x1ba12f, 0x1ba1af, 0x1ba1bf, 0x37435d, 0x37437d, 0x317498,
|
||||
0x35529c, 0x35529d, 0x3552de, 0x3552df, 0x62e933, 0x62295d, 0x6aa53d, 0x6aa53f,
|
||||
0x6aa53e, 0x6e86b9, 0x6e86f8, 0xd54a79, 0xc5d265, 0xc452b8, 0xdd0d71, 0xd54a78,
|
||||
0xdd0d70, 0xdd0df2, 0xdd0df3, 0x188a5f6, 0x188a5f5, 0x188a5f4, 0x188a5f3, 0x188a5f2,
|
||||
0x188a5f1, 0x188a5f0, 0x188a5ef, 0x188a5ee, 0x188a5ed, 0x188a5aa, 0x188a5e3, 0x188a5df,
|
||||
0x188a589, 0x188a5dd, 0x188a578, 0x188a5e0, 0x188a588, 0x188a5d6, 0x188a5db, 0x188a5e1,
|
||||
0x188a587, 0x188a59a, 0x188a5c4, 0x188a5ec, 0x188a586, 0x188a573, 0x188a59c, 0x188a5c8,
|
||||
0x188a5fb, 0x188a5a1, 0x188a5eb, 0x188a5a8, 0x188a584, 0x188a5d2, 0x188a599, 0x188a598,
|
||||
0x188a583, 0x18ba4c9, 0x188a5d0, 0x188a594, 0x188a582, 0x188a5cb, 0x188a5d8, 0x188a5e7,
|
||||
0x188a581, 0x188a5ea, 0x188a5a9, 0x188a5a6, 0x188a580, 0x188a5a0, 0x188a59d, 0x188a5c3,
|
||||
0x188a57f, 0x188a5c0, 0x188a5de, 0x188a5d4, 0x188a57e, 0x188a5c2, 0x188a592, 0x188a5cd,
|
||||
0x188a57d, 0x188a5a3, 0x188a5e8, 0x188a5a2, 0x188a57c, 0x188a58e, 0x188a5b3, 0x188a5b2,
|
||||
0x188a5b1, 0x188a5b0, 0x188a5af, 0x188a5ae, 0x188a5ad, 0x188a5ac, 0x188a5ab, 0x188a5da,
|
||||
0x188a5e4, 0x188a5e5, 0x188a5d9, 0x188a5b5, 0x188a5bc, 0x188a5bd, 0x188a5e9, 0x188a5cc,
|
||||
0x188a585, 0x188a5d3, 0x188a5e2, 0x188a595, 0x188a596, 0x188a5b8, 0x188a590, 0x188a5c9,
|
||||
0x188a5a4, 0x188a5e6, 0x188a5a5, 0x188a5ce, 0x188a5bf, 0x188a572, 0x188a59b, 0x188a5be,
|
||||
0x188a5c7, 0x188a5ca, 0x188a5d5, 0x188a57b, 0x188a58d, 0x188a58c, 0x188a58b, 0x188a58a,
|
||||
0x18ba4c8, 0x188a5c5, 0x188a5fa, 0x188a5bb, 0x188a5c1, 0x188a5cf, 0x188a5b9, 0x188a5b6,
|
||||
0x188a597, 0x188a5fe, 0x188a5d7, 0x188a5ba, 0x188a591, 0x188a5c6, 0x188a5dc, 0x188a57a,
|
||||
0x188a59f, 0x188a5f9, 0x188a5b4, 0x188a5a7, 0x188a58f, 0x188a5fd, 0x188a5b7, 0x188a593,
|
||||
0x188a59e, 0x188a5f8, 0x188a5ff, 0x188a5fc, 0x188a579, 0x188a5f7, 0x3114ba2, 0x3114ba3,
|
||||
0, 0x2, 0x7, 0x19,
|
||||
0x30, 0x36, 0x6f, 0x63,
|
||||
0x69, 0x6b, 0xd1, 0xd4,
|
||||
0xdc, 0x189, 0x18a, 0x1a0,
|
||||
0x1ab, 0x377, 0x310, 0x316,
|
||||
0x343, 0x354, 0x375, 0x623,
|
||||
0x684, 0x685, 0x6ab, 0x6ec,
|
||||
0xddb, 0xc5c, 0xc5e, 0xc44,
|
||||
0xd55, 0xdd1, 0xdd3, 0x1bb5,
|
||||
0x188b, 0x18bb, 0x18bf, 0x1aa8,
|
||||
0x1ba0, 0x1ba5, 0x1ba4, 0x3115,
|
||||
0x3175, 0x317d, 0x3553, 0x3768,
|
||||
0x6e87, 0x6ed3, 0x62e8, 0x62f8,
|
||||
0x6228, 0x6aa4, 0x6e85, 0xc453,
|
||||
0xc5d3, 0xc5f3, 0xdda4, 0xdd08,
|
||||
0xdd0c, 0x1bb4b, 0x1bb4a, 0x18ba5,
|
||||
0x18be5, 0x1aa95, 0x1aa97, 0x188a4,
|
||||
0x1ba13, 0x31748, 0x317c8, 0x35528,
|
||||
0x3552c, 0x37424, 0x37434, 0x37436,
|
||||
0x62294, 0x62e92, 0x62f92, 0x6aa52,
|
||||
0x6aa5a, 0x6e86a, 0x6e86e, 0x6e84a,
|
||||
0xc452a, 0xc5d27, 0xc5f26, 0xd54a6,
|
||||
0xd54b6, 0xdd096, 0xdd0d6, 0xdd0de,
|
||||
0x188a56, 0x18ba4d, 0x18be4e, 0x18be4f,
|
||||
0x1aa96e, 0x1ba12e, 0x1ba12f, 0x1ba1af,
|
||||
0x1ba1bf, 0x37435d, 0x37437d, 0x317498,
|
||||
0x35529c, 0x35529d, 0x3552de, 0x3552df,
|
||||
0x62e933, 0x62295d, 0x6aa53d, 0x6aa53f,
|
||||
0x6aa53e, 0x6e86b9, 0x6e86f8, 0xd54a79,
|
||||
0xc5d265, 0xc452b8, 0xdd0d71, 0xd54a78,
|
||||
0xdd0d70, 0xdd0df2, 0xdd0df3, 0x188a5f6,
|
||||
0x188a5f5, 0x188a5f4, 0x188a5f3, 0x188a5f2,
|
||||
0x188a5f1, 0x188a5f0, 0x188a5ef, 0x188a5ee,
|
||||
0x188a5ed, 0x188a5aa, 0x188a5e3, 0x188a5df,
|
||||
0x188a589, 0x188a5dd, 0x188a578, 0x188a5e0,
|
||||
0x188a588, 0x188a5d6, 0x188a5db, 0x188a5e1,
|
||||
0x188a587, 0x188a59a, 0x188a5c4, 0x188a5ec,
|
||||
0x188a586, 0x188a573, 0x188a59c, 0x188a5c8,
|
||||
0x188a5fb, 0x188a5a1, 0x188a5eb, 0x188a5a8,
|
||||
0x188a584, 0x188a5d2, 0x188a599, 0x188a598,
|
||||
0x188a583, 0x18ba4c9, 0x188a5d0, 0x188a594,
|
||||
0x188a582, 0x188a5cb, 0x188a5d8, 0x188a5e7,
|
||||
0x188a581, 0x188a5ea, 0x188a5a9, 0x188a5a6,
|
||||
0x188a580, 0x188a5a0, 0x188a59d, 0x188a5c3,
|
||||
0x188a57f, 0x188a5c0, 0x188a5de, 0x188a5d4,
|
||||
0x188a57e, 0x188a5c2, 0x188a592, 0x188a5cd,
|
||||
0x188a57d, 0x188a5a3, 0x188a5e8, 0x188a5a2,
|
||||
0x188a57c, 0x188a58e, 0x188a5b3, 0x188a5b2,
|
||||
0x188a5b1, 0x188a5b0, 0x188a5af, 0x188a5ae,
|
||||
0x188a5ad, 0x188a5ac, 0x188a5ab, 0x188a5da,
|
||||
0x188a5e4, 0x188a5e5, 0x188a5d9, 0x188a5b5,
|
||||
0x188a5bc, 0x188a5bd, 0x188a5e9, 0x188a5cc,
|
||||
0x188a585, 0x188a5d3, 0x188a5e2, 0x188a595,
|
||||
0x188a596, 0x188a5b8, 0x188a590, 0x188a5c9,
|
||||
0x188a5a4, 0x188a5e6, 0x188a5a5, 0x188a5ce,
|
||||
0x188a5bf, 0x188a572, 0x188a59b, 0x188a5be,
|
||||
0x188a5c7, 0x188a5ca, 0x188a5d5, 0x188a57b,
|
||||
0x188a58d, 0x188a58c, 0x188a58b, 0x188a58a,
|
||||
0x18ba4c8, 0x188a5c5, 0x188a5fa, 0x188a5bb,
|
||||
0x188a5c1, 0x188a5cf, 0x188a5b9, 0x188a5b6,
|
||||
0x188a597, 0x188a5fe, 0x188a5d7, 0x188a5ba,
|
||||
0x188a591, 0x188a5c6, 0x188a5dc, 0x188a57a,
|
||||
0x188a59f, 0x188a5f9, 0x188a5b4, 0x188a5a7,
|
||||
0x188a58f, 0x188a5fd, 0x188a5b7, 0x188a593,
|
||||
0x188a59e, 0x188a5f8, 0x188a5ff, 0x188a5fc,
|
||||
0x188a579, 0x188a5f7, 0x3114ba2, 0x3114ba3,
|
||||
};
|
||||
|
||||
static const uint8_t table_18_vlc_len[NB_VLC_TABLE_18] = {
|
||||
@@ -154,39 +202,39 @@ static const uint8_t table_18_vlc_len[NB_VLC_TABLE_18] = {
|
||||
};
|
||||
|
||||
static const uint16_t table_18_vlc_run[NB_VLC_TABLE_18] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
12, 1, 20, 1, 1, 1, 32, 1,
|
||||
1, 1, 1, 1, 60, 1, 1, 1,
|
||||
1, 100, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 180, 1,
|
||||
1, 320, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 2,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
12, 1, 20, 1, 1, 1, 32, 1,
|
||||
1, 1, 1, 1, 60, 1, 1, 1,
|
||||
1, 100, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 180, 1,
|
||||
1, 320, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 2,
|
||||
};
|
||||
|
||||
static const uint8_t table_18_vlc_level[NB_VLC_TABLE_18] = {
|
||||
|
||||
+465
-644
File diff suppressed because it is too large
Load Diff
+30
-26
@@ -25,10 +25,10 @@
|
||||
*/
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "bytestream.h"
|
||||
#include "get_bits.h"
|
||||
#include "idctdsp.h"
|
||||
#include "internal.h"
|
||||
#include "get_bits.h"
|
||||
#include "bytestream.h"
|
||||
|
||||
#define NUM_DC_CODES 127
|
||||
#define NUM_AC_CODES 103
|
||||
@@ -129,6 +129,7 @@ typedef struct CLVContext {
|
||||
int luma_dc_quant, chroma_dc_quant, ac_quant;
|
||||
DECLARE_ALIGNED(16, int16_t, block)[64];
|
||||
int top_dc[3], left_dc[4];
|
||||
int iframes_warning;
|
||||
} CLVContext;
|
||||
|
||||
static inline int decode_block(CLVContext *ctx, int16_t *blk, int has_ac,
|
||||
@@ -179,12 +180,12 @@ static inline int decode_block(CLVContext *ctx, int16_t *blk, int has_ac,
|
||||
}
|
||||
|
||||
#define DCT_TEMPLATE(blk, step, bias, shift, dshift, OP) \
|
||||
const int t0 = OP( 2841 * blk[1 * step] + 565 * blk[7 * step]); \
|
||||
const int t1 = OP( 565 * blk[1 * step] - 2841 * blk[7 * step]); \
|
||||
const int t2 = OP( 1609 * blk[5 * step] + 2408 * blk[3 * step]); \
|
||||
const int t3 = OP( 2408 * blk[5 * step] - 1609 * blk[3 * step]); \
|
||||
const int t4 = OP( 1108 * blk[2 * step] - 2676 * blk[6 * step]); \
|
||||
const int t5 = OP( 2676 * blk[2 * step] + 1108 * blk[6 * step]); \
|
||||
const int t0 = OP(2841 * blk[1 * step] + 565 * blk[7 * step]); \
|
||||
const int t1 = OP( 565 * blk[1 * step] - 2841 * blk[7 * step]); \
|
||||
const int t2 = OP(1609 * blk[5 * step] + 2408 * blk[3 * step]); \
|
||||
const int t3 = OP(2408 * blk[5 * step] - 1609 * blk[3 * step]); \
|
||||
const int t4 = OP(1108 * blk[2 * step] - 2676 * blk[6 * step]); \
|
||||
const int t5 = OP(2676 * blk[2 * step] + 1108 * blk[6 * step]); \
|
||||
const int t6 = ((blk[0 * step] + blk[4 * step]) * (1 << dshift)) + bias; \
|
||||
const int t7 = ((blk[0 * step] - blk[4 * step]) * (1 << dshift)) + bias; \
|
||||
const int t8 = t0 + t2; \
|
||||
@@ -225,9 +226,7 @@ static void clv_dct(int16_t *block)
|
||||
|
||||
static int decode_mb(CLVContext *c, int x, int y)
|
||||
{
|
||||
int i;
|
||||
int has_ac[6];
|
||||
int off;
|
||||
int i, has_ac[6], off;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
has_ac[i] = get_bits1(&c->gb);
|
||||
@@ -247,7 +246,8 @@ static int decode_mb(CLVContext *c, int x, int y)
|
||||
clv_dct(c->block);
|
||||
if (i == 2)
|
||||
off += c->pic->linesize[0] * 8;
|
||||
c->idsp.put_pixels_clamped(c->block, c->pic->data[0] + off + (i & 1) * 8,
|
||||
c->idsp.put_pixels_clamped(c->block,
|
||||
c->pic->data[0] + off + (i & 1) * 8,
|
||||
c->pic->linesize[0]);
|
||||
}
|
||||
|
||||
@@ -279,12 +279,11 @@ static int clv_decode_frame(AVCodecContext *avctx, void *data,
|
||||
CLVContext *c = avctx->priv_data;
|
||||
GetByteContext gb;
|
||||
uint32_t frame_type;
|
||||
int i, j;
|
||||
int ret;
|
||||
int i, j, ret;
|
||||
int mb_ret = 0;
|
||||
|
||||
bytestream2_init(&gb, buf, buf_size);
|
||||
if (avctx->codec_tag == MKTAG('C','L','V','1')) {
|
||||
if (avctx->codec_tag == MKTAG('C', 'L', 'V', '1')) {
|
||||
int skip = bytestream2_get_byte(&gb);
|
||||
bytestream2_skip(&gb, (skip + 1) * 8);
|
||||
}
|
||||
@@ -301,7 +300,8 @@ static int clv_decode_frame(AVCodecContext *avctx, void *data,
|
||||
return ret;
|
||||
|
||||
c->pic->key_frame = frame_type & 0x20 ? 1 : 0;
|
||||
c->pic->pict_type = frame_type & 0x20 ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
|
||||
c->pic->pict_type = frame_type & 0x20 ? AV_PICTURE_TYPE_I
|
||||
: AV_PICTURE_TYPE_P;
|
||||
|
||||
bytestream2_get_be32(&gb); // frame size;
|
||||
c->ac_quant = bytestream2_get_byte(&gb);
|
||||
@@ -309,7 +309,7 @@ static int clv_decode_frame(AVCodecContext *avctx, void *data,
|
||||
c->chroma_dc_quant = 32;
|
||||
|
||||
if ((ret = init_get_bits8(&c->gb, buf + bytestream2_tell(&gb),
|
||||
(buf_size - bytestream2_tell(&gb)))) < 0)
|
||||
buf_size - bytestream2_tell(&gb))) < 0)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
@@ -330,6 +330,10 @@ static int clv_decode_frame(AVCodecContext *avctx, void *data,
|
||||
|
||||
*got_frame = 1;
|
||||
} else {
|
||||
if (!c->iframes_warning)
|
||||
avpriv_report_missing_feature(avctx, "Non-I-frames in Clearvideo");
|
||||
c->iframes_warning = 1;
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
|
||||
return mb_ret < 0 ? mb_ret : buf_size;
|
||||
@@ -337,20 +341,19 @@ static int clv_decode_frame(AVCodecContext *avctx, void *data,
|
||||
|
||||
static av_cold int clv_decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
CLVContext * const c = avctx->priv_data;
|
||||
CLVContext *const c = avctx->priv_data;
|
||||
int ret;
|
||||
|
||||
c->avctx = avctx;
|
||||
|
||||
avctx->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
|
||||
c->pic = av_frame_alloc();
|
||||
c->avctx = avctx;
|
||||
c->mb_width = FFALIGN(avctx->width, 16) >> 4;
|
||||
c->mb_height = FFALIGN(avctx->height, 16) >> 4;
|
||||
c->iframes_warning = 0;
|
||||
c->pic = av_frame_alloc();
|
||||
if (!c->pic)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
c->mb_width = FFALIGN(avctx->width, 16) >> 4;
|
||||
c->mb_height = FFALIGN(avctx->height, 16) >> 4;
|
||||
|
||||
ff_idctdsp_init(&c->idsp, avctx);
|
||||
ret = init_vlc(&c->dc_vlc, 9, NUM_DC_CODES,
|
||||
clv_dc_bits, 1, 1,
|
||||
@@ -373,7 +376,7 @@ static av_cold int clv_decode_init(AVCodecContext *avctx)
|
||||
|
||||
static av_cold int clv_decode_end(AVCodecContext *avctx)
|
||||
{
|
||||
CLVContext * const c = avctx->priv_data;
|
||||
CLVContext *const c = avctx->priv_data;
|
||||
|
||||
av_frame_free(&c->pic);
|
||||
|
||||
@@ -385,6 +388,7 @@ static av_cold int clv_decode_end(AVCodecContext *avctx)
|
||||
|
||||
AVCodec ff_clearvideo_decoder = {
|
||||
.name = "clearvideo",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Iterated Systems ClearVideo"),
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_CLEARVIDEO,
|
||||
.priv_data_size = sizeof(CLVContext),
|
||||
@@ -392,5 +396,5 @@ AVCodec ff_clearvideo_decoder = {
|
||||
.close = clv_decode_end,
|
||||
.decode = clv_decode_frame,
|
||||
.capabilities = AV_CODEC_CAP_DR1,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Iterated Systems ClearVideo"),
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
|
||||
};
|
||||
|
||||
+1
-1
@@ -153,7 +153,7 @@ static int cng_decode_frame(AVCodecContext *avctx, void *data,
|
||||
return ret;
|
||||
buf_out = (int16_t *)frame->data[0];
|
||||
for (i = 0; i < avctx->frame_size; i++)
|
||||
buf_out[i] = p->filter_out[i + p->order];
|
||||
buf_out[i] = av_clip_int16(p->filter_out[i + p->order]);
|
||||
memcpy(p->filter_out, p->filter_out + avctx->frame_size,
|
||||
p->order * sizeof(*p->filter_out));
|
||||
|
||||
|
||||
+7
-18
@@ -46,15 +46,6 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_REORDER,
|
||||
.profiles = NULL_IF_CONFIG_SMALL(ff_mpeg2_video_profiles),
|
||||
},
|
||||
#if FF_API_XVMC
|
||||
{
|
||||
.id = AV_CODEC_ID_MPEG2VIDEO_XVMC,
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.name = "mpegvideo_xvmc",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("MPEG-1/2 video XvMC (X-Video Motion Compensation)"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
#endif /* FF_API_XVMC */
|
||||
{
|
||||
.id = AV_CODEC_ID_H261,
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
@@ -2499,15 +2490,6 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.long_name = NULL_IF_CONFIG_SMALL("ATRAC3 (Adaptive TRansform Acoustic Coding 3)"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
#if FF_API_VOXWARE
|
||||
{
|
||||
.id = AV_CODEC_ID_VOXWARE,
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.name = "voxware",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Voxware RT29 Metasound"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.id = AV_CODEC_ID_APE,
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
@@ -2877,6 +2859,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.long_name = NULL_IF_CONFIG_SMALL("ADPCM MTAF"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_APTX,
|
||||
.type = AVMEDIA_TYPE_AUDIO,
|
||||
.name = "aptx",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("aptX (Audio Processing Technology for Bluetooth)"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
|
||||
/* subtitle codecs */
|
||||
{
|
||||
|
||||
@@ -786,8 +786,9 @@ static int crystalhd_receive_frame(AVCodecContext *avctx, AVFrame *frame)
|
||||
.receive_frame = crystalhd_receive_frame, \
|
||||
.flush = flush, \
|
||||
.bsfs = bsf_name, \
|
||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \
|
||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
|
||||
.pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUYV422, AV_PIX_FMT_NONE}, \
|
||||
.wrapper_name = "crystalhd", \
|
||||
};
|
||||
|
||||
#if CONFIG_H264_CRYSTALHD_DECODER
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "decode.h"
|
||||
#include "hwaccel.h"
|
||||
#include "internal.h"
|
||||
|
||||
typedef struct CuvidContext
|
||||
@@ -835,7 +836,7 @@ static av_cold int cuvid_decode_init(AVCodecContext *avctx)
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = cuvid_load_functions(&ctx->cvdl);
|
||||
ret = cuvid_load_functions(&ctx->cvdl, avctx);
|
||||
if (ret < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Failed loading nvcuvid.\n");
|
||||
goto error;
|
||||
@@ -1094,6 +1095,19 @@ static const AVOption options[] = {
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static const AVCodecHWConfigInternal *cuvid_hw_configs[] = {
|
||||
&(const AVCodecHWConfigInternal) {
|
||||
.public = {
|
||||
.pix_fmt = AV_PIX_FMT_CUDA,
|
||||
.methods = AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX |
|
||||
AV_CODEC_HW_CONFIG_METHOD_INTERNAL,
|
||||
.device_type = AV_HWDEVICE_TYPE_CUDA
|
||||
},
|
||||
.hwaccel = NULL,
|
||||
},
|
||||
NULL
|
||||
};
|
||||
|
||||
#define DEFINE_CUVID_CODEC(x, X) \
|
||||
static const AVClass x##_cuvid_class = { \
|
||||
.class_name = #x "_cuvid", \
|
||||
@@ -1101,12 +1115,6 @@ static const AVOption options[] = {
|
||||
.option = options, \
|
||||
.version = LIBAVUTIL_VERSION_INT, \
|
||||
}; \
|
||||
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"), \
|
||||
@@ -1119,12 +1127,14 @@ static const AVOption options[] = {
|
||||
.decode = cuvid_decode_frame, \
|
||||
.receive_frame = cuvid_output_frame, \
|
||||
.flush = cuvid_flush, \
|
||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING, \
|
||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
|
||||
.pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_CUDA, \
|
||||
AV_PIX_FMT_NV12, \
|
||||
AV_PIX_FMT_P010, \
|
||||
AV_PIX_FMT_P016, \
|
||||
AV_PIX_FMT_NONE }, \
|
||||
.hw_configs = cuvid_hw_configs, \
|
||||
.wrapper_name = "cuvid", \
|
||||
};
|
||||
|
||||
#if CONFIG_HEVC_CUVID_DECODER
|
||||
+9
-4
@@ -146,12 +146,17 @@ int ff_dca_parse_core_frame_header(DCACoreFrameHeader *h, GetBitContext *gb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int avpriv_dca_parse_core_frame_header(DCACoreFrameHeader *h, uint8_t *buf, int size)
|
||||
int avpriv_dca_parse_core_frame_header(DCACoreFrameHeader *h, const uint8_t *buf, int size)
|
||||
{
|
||||
GetBitContext gb;
|
||||
int ret;
|
||||
|
||||
if (init_get_bits8(&gb, buf, size) < 0)
|
||||
return DCA_PARSE_ERROR_INVALIDDATA;
|
||||
ret = init_get_bits8(&gb, buf, size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ff_dca_parse_core_frame_header(h, &gb);
|
||||
if (ff_dca_parse_core_frame_header(h, &gb) < 0)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+13
-5
@@ -29,10 +29,10 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include "libavutil/common.h"
|
||||
#include "libavutil/internal.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
|
||||
#include "get_bits.h"
|
||||
#include "internal.h"
|
||||
|
||||
#define DCA_CORE_FRAME_HEADER_SIZE 18
|
||||
|
||||
@@ -46,7 +46,6 @@ enum DCAParseError {
|
||||
DCA_PARSE_ERROR_RESERVED_BIT = -7,
|
||||
DCA_PARSE_ERROR_LFE_FLAG = -8,
|
||||
DCA_PARSE_ERROR_PCM_RES = -9,
|
||||
DCA_PARSE_ERROR_INVALIDDATA = -10,
|
||||
};
|
||||
|
||||
typedef struct DCACoreFrameHeader {
|
||||
@@ -196,7 +195,7 @@ enum DCADownMixType {
|
||||
DCA_DMIX_TYPE_COUNT
|
||||
};
|
||||
|
||||
extern av_export const uint32_t avpriv_dca_sample_rates[16];
|
||||
extern av_export_avcodec const uint32_t avpriv_dca_sample_rates[16];
|
||||
|
||||
extern const uint32_t ff_dca_sampling_freqs[16];
|
||||
extern const uint8_t ff_dca_freq_ranges[16];
|
||||
@@ -211,10 +210,19 @@ int avpriv_dca_convert_bitstream(const uint8_t *src, int src_size, uint8_t *dst,
|
||||
|
||||
/**
|
||||
* Parse and validate core frame header
|
||||
* @param[out] h Pointer to struct where header info is written.
|
||||
* @param[in] buf Pointer to the data buffer
|
||||
* @param[in] size Size of the data buffer
|
||||
* @return 0 on success, negative AVERROR code on failure
|
||||
*/
|
||||
int avpriv_dca_parse_core_frame_header(DCACoreFrameHeader *h, const uint8_t *buf, int size);
|
||||
|
||||
/**
|
||||
* Parse and validate core frame header
|
||||
* @param[out] h Pointer to struct where header info is written.
|
||||
* @param[in] gbc BitContext containing the first 120 bits of the frame.
|
||||
* @return 0 on success, negative DCA_PARSE_ERROR_ code on failure
|
||||
*/
|
||||
int avpriv_dca_parse_core_frame_header(DCACoreFrameHeader *h, uint8_t *buf, int size);
|
||||
|
||||
int ff_dca_parse_core_frame_header(DCACoreFrameHeader *h, GetBitContext *gb);
|
||||
|
||||
#endif /* AVCODEC_DCA_H */
|
||||
|
||||
+172
-214
@@ -21,6 +21,9 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define FFT_FLOAT 0
|
||||
#define FFT_FIXED_32 1
|
||||
|
||||
#include "libavutil/avassert.h"
|
||||
#include "libavutil/channel_layout.h"
|
||||
#include "libavutil/common.h"
|
||||
@@ -33,6 +36,7 @@
|
||||
#include "dca_core.h"
|
||||
#include "dcadata.h"
|
||||
#include "dcaenc.h"
|
||||
#include "fft.h"
|
||||
#include "internal.h"
|
||||
#include "mathops.h"
|
||||
#include "put_bits.h"
|
||||
@@ -48,6 +52,8 @@
|
||||
#define SUBBAND_SAMPLES (SUBFRAMES * SUBSUBFRAMES * 8)
|
||||
#define AUBANDS 25
|
||||
|
||||
#define COS_T(x) (c->cos_table[(x) & 2047])
|
||||
|
||||
typedef struct CompressionOptions {
|
||||
int adpcm_mode;
|
||||
} CompressionOptions;
|
||||
@@ -56,6 +62,7 @@ typedef struct DCAEncContext {
|
||||
AVClass *class;
|
||||
PutBitContext pb;
|
||||
DCAADPCMEncContext adpcm_ctx;
|
||||
FFTContext mdct;
|
||||
CompressionOptions options;
|
||||
int frame_size;
|
||||
int frame_bits;
|
||||
@@ -92,15 +99,15 @@ typedef struct DCAEncContext {
|
||||
int32_t worst_noise_ever;
|
||||
int consumed_bits;
|
||||
int consumed_adpcm_bits; ///< Number of bits to transmit ADPCM related info
|
||||
} DCAEncContext;
|
||||
|
||||
static int32_t cos_table[2048];
|
||||
static int32_t band_interpolation[2][512];
|
||||
static int32_t band_spectrum[2][8];
|
||||
static int32_t auf[9][AUBANDS][256];
|
||||
static int32_t cb_to_add[256];
|
||||
static int32_t cb_to_level[2048];
|
||||
static int32_t lfe_fir_64i[512];
|
||||
int32_t cos_table[2048];
|
||||
int32_t band_interpolation_tab[2][512];
|
||||
int32_t band_spectrum_tab[2][8];
|
||||
int32_t auf[9][AUBANDS][256];
|
||||
int32_t cb_to_add[256];
|
||||
int32_t cb_to_level[2048];
|
||||
int32_t lfe_fir_64i[512];
|
||||
} DCAEncContext;
|
||||
|
||||
/* Transfer function of outer and middle ear, Hz -> dB */
|
||||
static double hom(double f)
|
||||
@@ -153,15 +160,16 @@ static int encode_init(AVCodecContext *avctx)
|
||||
{
|
||||
DCAEncContext *c = avctx->priv_data;
|
||||
uint64_t layout = avctx->channel_layout;
|
||||
int i, j, min_frame_bits;
|
||||
int i, j, k, min_frame_bits;
|
||||
int ret;
|
||||
|
||||
if (subband_bufer_alloc(c))
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
c->fullband_channels = c->channels = avctx->channels;
|
||||
c->lfe_channel = (avctx->channels == 3 || avctx->channels == 6);
|
||||
c->band_interpolation = band_interpolation[1];
|
||||
c->band_spectrum = band_spectrum[1];
|
||||
c->band_interpolation = c->band_interpolation_tab[1];
|
||||
c->band_spectrum = c->band_spectrum_tab[1];
|
||||
c->worst_quantization_noise = -2047;
|
||||
c->worst_noise_ever = -2047;
|
||||
c->consumed_adpcm_bits = 0;
|
||||
@@ -231,93 +239,79 @@ static int encode_init(AVCodecContext *avctx)
|
||||
|
||||
avctx->frame_size = 32 * SUBBAND_SAMPLES;
|
||||
|
||||
if (!cos_table[0]) {
|
||||
int j, k;
|
||||
if ((ret = ff_mdct_init(&c->mdct, 9, 0, 1.0)) < 0)
|
||||
return ret;
|
||||
|
||||
cos_table[0] = 0x7fffffff;
|
||||
cos_table[512] = 0;
|
||||
cos_table[1024] = -cos_table[0];
|
||||
for (i = 1; i < 512; i++) {
|
||||
cos_table[i] = (int32_t)(0x7fffffff * cos(M_PI * i / 1024));
|
||||
cos_table[1024-i] = -cos_table[i];
|
||||
cos_table[1024+i] = -cos_table[i];
|
||||
cos_table[2048-i] = cos_table[i];
|
||||
}
|
||||
for (i = 0; i < 2048; i++) {
|
||||
cb_to_level[i] = (int32_t)(0x7fffffff * ff_exp10(-0.005 * i));
|
||||
}
|
||||
/* Init all tables */
|
||||
c->cos_table[0] = 0x7fffffff;
|
||||
c->cos_table[512] = 0;
|
||||
c->cos_table[1024] = -c->cos_table[0];
|
||||
for (i = 1; i < 512; i++) {
|
||||
c->cos_table[i] = (int32_t)(0x7fffffff * cos(M_PI * i / 1024));
|
||||
c->cos_table[1024-i] = -c->cos_table[i];
|
||||
c->cos_table[1024+i] = -c->cos_table[i];
|
||||
c->cos_table[2048-i] = +c->cos_table[i];
|
||||
}
|
||||
|
||||
for (k = 0; k < 32; k++) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
lfe_fir_64i[64 * j + k] = (int32_t)(0xffffff800000ULL * ff_dca_lfe_fir_64[8 * k + j]);
|
||||
lfe_fir_64i[64 * (7-j) + (63 - k)] = (int32_t)(0xffffff800000ULL * ff_dca_lfe_fir_64[8 * k + j]);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 2048; i++)
|
||||
c->cb_to_level[i] = (int32_t)(0x7fffffff * ff_exp10(-0.005 * i));
|
||||
|
||||
for (i = 0; i < 512; i++) {
|
||||
band_interpolation[0][i] = (int32_t)(0x1000000000ULL * ff_dca_fir_32bands_perfect[i]);
|
||||
band_interpolation[1][i] = (int32_t)(0x1000000000ULL * ff_dca_fir_32bands_nonperfect[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
for (j = 0; j < AUBANDS; j++) {
|
||||
for (k = 0; k < 256; k++) {
|
||||
double freq = sample_rates[i] * (k + 0.5) / 512;
|
||||
|
||||
auf[i][j][k] = (int32_t)(10 * (hom(freq) + gammafilter(j, freq)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
double add = 1 + ff_exp10(-0.01 * i);
|
||||
cb_to_add[i] = (int32_t)(100 * log10(add));
|
||||
}
|
||||
for (k = 0; k < 32; k++) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
double accum = 0;
|
||||
for (i = 0; i < 512; i++) {
|
||||
double reconst = ff_dca_fir_32bands_perfect[i] * ((i & 64) ? (-1) : 1);
|
||||
accum += reconst * cos(2 * M_PI * (i + 0.5 - 256) * (j + 0.5) / 512);
|
||||
}
|
||||
band_spectrum[0][j] = (int32_t)(200 * log10(accum));
|
||||
}
|
||||
for (j = 0; j < 8; j++) {
|
||||
double accum = 0;
|
||||
for (i = 0; i < 512; i++) {
|
||||
double reconst = ff_dca_fir_32bands_nonperfect[i] * ((i & 64) ? (-1) : 1);
|
||||
accum += reconst * cos(2 * M_PI * (i + 0.5 - 256) * (j + 0.5) / 512);
|
||||
}
|
||||
band_spectrum[1][j] = (int32_t)(200 * log10(accum));
|
||||
c->lfe_fir_64i[64 * j + k] = (int32_t)(0xffffff800000ULL * ff_dca_lfe_fir_64[8 * k + j]);
|
||||
c->lfe_fir_64i[64 * (7-j) + (63 - k)] = (int32_t)(0xffffff800000ULL * ff_dca_lfe_fir_64[8 * k + j]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 512; i++) {
|
||||
c->band_interpolation_tab[0][i] = (int32_t)(0x1000000000ULL * ff_dca_fir_32bands_perfect[i]);
|
||||
c->band_interpolation_tab[1][i] = (int32_t)(0x1000000000ULL * ff_dca_fir_32bands_nonperfect[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
for (j = 0; j < AUBANDS; j++) {
|
||||
for (k = 0; k < 256; k++) {
|
||||
double freq = sample_rates[i] * (k + 0.5) / 512;
|
||||
|
||||
c->auf[i][j][k] = (int32_t)(10 * (hom(freq) + gammafilter(j, freq)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
double add = 1 + ff_exp10(-0.01 * i);
|
||||
c->cb_to_add[i] = (int32_t)(100 * log10(add));
|
||||
}
|
||||
for (j = 0; j < 8; j++) {
|
||||
double accum = 0;
|
||||
for (i = 0; i < 512; i++) {
|
||||
double reconst = ff_dca_fir_32bands_perfect[i] * ((i & 64) ? (-1) : 1);
|
||||
accum += reconst * cos(2 * M_PI * (i + 0.5 - 256) * (j + 0.5) / 512);
|
||||
}
|
||||
c->band_spectrum_tab[0][j] = (int32_t)(200 * log10(accum));
|
||||
}
|
||||
for (j = 0; j < 8; j++) {
|
||||
double accum = 0;
|
||||
for (i = 0; i < 512; i++) {
|
||||
double reconst = ff_dca_fir_32bands_nonperfect[i] * ((i & 64) ? (-1) : 1);
|
||||
accum += reconst * cos(2 * M_PI * (i + 0.5 - 256) * (j + 0.5) / 512);
|
||||
}
|
||||
c->band_spectrum_tab[1][j] = (int32_t)(200 * log10(accum));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static av_cold int encode_close(AVCodecContext *avctx)
|
||||
{
|
||||
if (avctx->priv_data) {
|
||||
DCAEncContext *c = avctx->priv_data;
|
||||
subband_bufer_free(c);
|
||||
ff_dcaadpcm_free(&c->adpcm_ctx);
|
||||
}
|
||||
DCAEncContext *c = avctx->priv_data;
|
||||
ff_mdct_end(&c->mdct);
|
||||
subband_bufer_free(c);
|
||||
ff_dcaadpcm_free(&c->adpcm_ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int32_t cos_t(int x)
|
||||
{
|
||||
return cos_table[x & 2047];
|
||||
}
|
||||
|
||||
static inline int32_t sin_t(int x)
|
||||
{
|
||||
return cos_t(x - 512);
|
||||
}
|
||||
|
||||
static inline int32_t half32(int32_t a)
|
||||
{
|
||||
return (a + 1) >> 1;
|
||||
}
|
||||
|
||||
static void subband_transform(DCAEncContext *c, const int32_t *input)
|
||||
{
|
||||
int ch, subs, i, k, j;
|
||||
@@ -353,7 +347,7 @@ static void subband_transform(DCAEncContext *c, const int32_t *input)
|
||||
resp = 0;
|
||||
for (i = 16; i < 48; i++) {
|
||||
int s = (2 * band + 1) * (2 * (i + 16) + 1);
|
||||
resp += mul32(accum[i], cos_t(s << 3)) >> 3;
|
||||
resp += mul32(accum[i], COS_T(s << 3)) >> 3;
|
||||
}
|
||||
|
||||
c->subband[ch][band][subs] = ((band + 1) & 2) ? -resp : resp;
|
||||
@@ -384,9 +378,9 @@ static void lfe_downsample(DCAEncContext *c, const int32_t *input)
|
||||
accum = 0;
|
||||
|
||||
for (i = hist_start, j = 0; i < 512; i++, j++)
|
||||
accum += mul32(hist[i], lfe_fir_64i[j]);
|
||||
accum += mul32(hist[i], c->lfe_fir_64i[j]);
|
||||
for (i = 0; i < hist_start; i++, j++)
|
||||
accum += mul32(hist[i], lfe_fir_64i[j]);
|
||||
accum += mul32(hist[i], c->lfe_fir_64i[j]);
|
||||
|
||||
c->downsampled_lfe[lfes] = accum;
|
||||
|
||||
@@ -398,131 +392,72 @@ static void lfe_downsample(DCAEncContext *c, const int32_t *input)
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int32_t re;
|
||||
int32_t im;
|
||||
} cplx32;
|
||||
|
||||
static void fft(const int32_t in[2 * 256], cplx32 out[256])
|
||||
static int32_t get_cb(DCAEncContext *c, int32_t in)
|
||||
{
|
||||
cplx32 buf[256], rin[256], rout[256];
|
||||
int i, j, k, l;
|
||||
int i, res = 0;
|
||||
in = FFABS(in);
|
||||
|
||||
/* do two transforms in parallel */
|
||||
for (i = 0; i < 256; i++) {
|
||||
/* Apply the Hann window */
|
||||
rin[i].re = mul32(in[2 * i], 0x3fffffff - (cos_t(8 * i + 2) >> 1));
|
||||
rin[i].im = mul32(in[2 * i + 1], 0x3fffffff - (cos_t(8 * i + 6) >> 1));
|
||||
}
|
||||
/* pre-rotation */
|
||||
for (i = 0; i < 256; i++) {
|
||||
buf[i].re = mul32(cos_t(4 * i + 2), rin[i].re)
|
||||
- mul32(sin_t(4 * i + 2), rin[i].im);
|
||||
buf[i].im = mul32(cos_t(4 * i + 2), rin[i].im)
|
||||
+ mul32(sin_t(4 * i + 2), rin[i].re);
|
||||
}
|
||||
|
||||
for (j = 256, l = 1; j != 1; j >>= 1, l <<= 1) {
|
||||
for (k = 0; k < 256; k += j) {
|
||||
for (i = k; i < k + j / 2; i++) {
|
||||
cplx32 sum, diff;
|
||||
int t = 8 * l * i;
|
||||
|
||||
sum.re = buf[i].re + buf[i + j / 2].re;
|
||||
sum.im = buf[i].im + buf[i + j / 2].im;
|
||||
|
||||
diff.re = buf[i].re - buf[i + j / 2].re;
|
||||
diff.im = buf[i].im - buf[i + j / 2].im;
|
||||
|
||||
buf[i].re = half32(sum.re);
|
||||
buf[i].im = half32(sum.im);
|
||||
|
||||
buf[i + j / 2].re = mul32(diff.re, cos_t(t))
|
||||
- mul32(diff.im, sin_t(t));
|
||||
buf[i + j / 2].im = mul32(diff.im, cos_t(t))
|
||||
+ mul32(diff.re, sin_t(t));
|
||||
}
|
||||
}
|
||||
}
|
||||
/* post-rotation */
|
||||
for (i = 0; i < 256; i++) {
|
||||
int b = ff_reverse[i];
|
||||
rout[i].re = mul32(buf[b].re, cos_t(4 * i))
|
||||
- mul32(buf[b].im, sin_t(4 * i));
|
||||
rout[i].im = mul32(buf[b].im, cos_t(4 * i))
|
||||
+ mul32(buf[b].re, sin_t(4 * i));
|
||||
}
|
||||
for (i = 0; i < 256; i++) {
|
||||
/* separate the results of the two transforms */
|
||||
cplx32 o1, o2;
|
||||
|
||||
o1.re = rout[i].re - rout[255 - i].re;
|
||||
o1.im = rout[i].im + rout[255 - i].im;
|
||||
|
||||
o2.re = rout[i].im - rout[255 - i].im;
|
||||
o2.im = -rout[i].re - rout[255 - i].re;
|
||||
|
||||
/* combine them into one long transform */
|
||||
out[i].re = mul32( o1.re + o2.re, cos_t(2 * i + 1))
|
||||
+ mul32( o1.im - o2.im, sin_t(2 * i + 1));
|
||||
out[i].im = mul32( o1.im + o2.im, cos_t(2 * i + 1))
|
||||
+ mul32(-o1.re + o2.re, sin_t(2 * i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t get_cb(int32_t in)
|
||||
{
|
||||
int i, res;
|
||||
|
||||
res = 0;
|
||||
if (in < 0)
|
||||
in = -in;
|
||||
for (i = 1024; i > 0; i >>= 1) {
|
||||
if (cb_to_level[i + res] >= in)
|
||||
if (c->cb_to_level[i + res] >= in)
|
||||
res += i;
|
||||
}
|
||||
return -res;
|
||||
}
|
||||
|
||||
static int32_t add_cb(int32_t a, int32_t b)
|
||||
static int32_t add_cb(DCAEncContext *c, int32_t a, int32_t b)
|
||||
{
|
||||
if (a < b)
|
||||
FFSWAP(int32_t, a, b);
|
||||
|
||||
if (a - b >= 256)
|
||||
return a;
|
||||
return a + cb_to_add[a - b];
|
||||
return a + c->cb_to_add[a - b];
|
||||
}
|
||||
|
||||
static void adjust_jnd(int samplerate_index,
|
||||
static void calc_power(DCAEncContext *c,
|
||||
const int32_t in[2 * 256], int32_t power[256])
|
||||
{
|
||||
int i;
|
||||
LOCAL_ALIGNED_32(int32_t, data, [512]);
|
||||
LOCAL_ALIGNED_32(int32_t, coeff, [256]);
|
||||
|
||||
for (i = 0; i < 512; i++)
|
||||
data[i] = norm__(mul32(in[i], 0x3fffffff - (COS_T(4 * i + 2) >> 1)), 4);
|
||||
|
||||
c->mdct.mdct_calc(&c->mdct, coeff, data);
|
||||
for (i = 0; i < 256; i++) {
|
||||
const int32_t cb = get_cb(c, coeff[i]);
|
||||
power[i] = add_cb(c, cb, cb);
|
||||
}
|
||||
}
|
||||
|
||||
static void adjust_jnd(DCAEncContext *c,
|
||||
const int32_t in[512], int32_t out_cb[256])
|
||||
{
|
||||
int32_t power[256];
|
||||
cplx32 out[256];
|
||||
int32_t out_cb_unnorm[256];
|
||||
int32_t denom;
|
||||
const int32_t ca_cb = -1114;
|
||||
const int32_t cs_cb = 928;
|
||||
const int samplerate_index = c->samplerate_index;
|
||||
int i, j;
|
||||
|
||||
fft(in, out);
|
||||
calc_power(c, in, power);
|
||||
|
||||
for (j = 0; j < 256; j++) {
|
||||
power[j] = add_cb(get_cb(out[j].re), get_cb(out[j].im));
|
||||
for (j = 0; j < 256; j++)
|
||||
out_cb_unnorm[j] = -2047; /* and can only grow */
|
||||
}
|
||||
|
||||
for (i = 0; i < AUBANDS; i++) {
|
||||
denom = ca_cb; /* and can only grow */
|
||||
for (j = 0; j < 256; j++)
|
||||
denom = add_cb(denom, power[j] + auf[samplerate_index][i][j]);
|
||||
denom = add_cb(c, denom, power[j] + c->auf[samplerate_index][i][j]);
|
||||
for (j = 0; j < 256; j++)
|
||||
out_cb_unnorm[j] = add_cb(out_cb_unnorm[j],
|
||||
-denom + auf[samplerate_index][i][j]);
|
||||
out_cb_unnorm[j] = add_cb(c, out_cb_unnorm[j],
|
||||
-denom + c->auf[samplerate_index][i][j]);
|
||||
}
|
||||
|
||||
for (j = 0; j < 256; j++)
|
||||
out_cb[j] = add_cb(out_cb[j], -out_cb_unnorm[j] - ca_cb - cs_cb);
|
||||
out_cb[j] = add_cb(c, out_cb[j], -out_cb_unnorm[j] - ca_cb - cs_cb);
|
||||
}
|
||||
|
||||
typedef void (*walk_band_t)(DCAEncContext *c, int band1, int band2, int f,
|
||||
@@ -586,7 +521,7 @@ static void calc_masking(DCAEncContext *c, const int32_t *input)
|
||||
data[i] = c->history[ch][k];
|
||||
for (k -= 512; i < 512; i++, k++)
|
||||
data[i] = input[k * c->channels + chi];
|
||||
adjust_jnd(c->samplerate_index, data, c->masking_curve_cb[ssf]);
|
||||
adjust_jnd(c, data, c->masking_curve_cb[ssf]);
|
||||
}
|
||||
for (i = 0; i < 256; i++) {
|
||||
int32_t m = 2048;
|
||||
@@ -604,16 +539,16 @@ static void calc_masking(DCAEncContext *c, const int32_t *input)
|
||||
}
|
||||
}
|
||||
|
||||
static inline int32_t find_peak(const int32_t *in, int len) {
|
||||
static inline int32_t find_peak(DCAEncContext *c, const int32_t *in, int len)
|
||||
{
|
||||
int sample;
|
||||
int32_t m = 0;
|
||||
for (sample = 0; sample < len; sample++) {
|
||||
int32_t s = abs(in[sample]);
|
||||
if (m < s) {
|
||||
if (m < s)
|
||||
m = s;
|
||||
}
|
||||
}
|
||||
return get_cb(m);
|
||||
return get_cb(c, m);
|
||||
}
|
||||
|
||||
static void find_peaks(DCAEncContext *c)
|
||||
@@ -621,14 +556,13 @@ static void find_peaks(DCAEncContext *c)
|
||||
int band, ch;
|
||||
|
||||
for (ch = 0; ch < c->fullband_channels; ch++) {
|
||||
for (band = 0; band < 32; band++) {
|
||||
c->peak_cb[ch][band] = find_peak(c->subband[ch][band], SUBBAND_SAMPLES);
|
||||
}
|
||||
for (band = 0; band < 32; band++)
|
||||
c->peak_cb[ch][band] = find_peak(c, c->subband[ch][band],
|
||||
SUBBAND_SAMPLES);
|
||||
}
|
||||
|
||||
if (c->lfe_channel) {
|
||||
c->lfe_peak_cb = find_peak(c->downsampled_lfe, DCA_LFE_SAMPLES);
|
||||
}
|
||||
if (c->lfe_channel)
|
||||
c->lfe_peak_cb = find_peak(c, c->downsampled_lfe, DCA_LFE_SAMPLES);
|
||||
}
|
||||
|
||||
static void adpcm_analysis(DCAEncContext *c)
|
||||
@@ -642,11 +576,12 @@ static void adpcm_analysis(DCAEncContext *c)
|
||||
for (ch = 0; ch < c->fullband_channels; ch++) {
|
||||
for (band = 0; band < 32; band++) {
|
||||
samples = c->subband[ch][band] - DCA_ADPCM_COEFFS;
|
||||
pred_vq_id = ff_dcaadpcm_subband_analysis(&c->adpcm_ctx, samples, SUBBAND_SAMPLES, estimated_diff);
|
||||
pred_vq_id = ff_dcaadpcm_subband_analysis(&c->adpcm_ctx, samples,
|
||||
SUBBAND_SAMPLES, estimated_diff);
|
||||
if (pred_vq_id >= 0) {
|
||||
c->prediction_mode[ch][band] = pred_vq_id;
|
||||
c->consumed_adpcm_bits += 12; //12 bits to transmit prediction vq index
|
||||
c->diff_peak_cb[ch][band] = find_peak(estimated_diff, 16);
|
||||
c->diff_peak_cb[ch][band] = find_peak(c, estimated_diff, 16);
|
||||
} else {
|
||||
c->prediction_mode[ch][band] = -1;
|
||||
}
|
||||
@@ -658,7 +593,7 @@ static const int snr_fudge = 128;
|
||||
#define USED_1ABITS 1
|
||||
#define USED_26ABITS 4
|
||||
|
||||
static inline int32_t get_step_size(const DCAEncContext *c, int ch, int band)
|
||||
static inline int32_t get_step_size(DCAEncContext *c, int ch, int band)
|
||||
{
|
||||
int32_t step_size;
|
||||
|
||||
@@ -670,7 +605,8 @@ static inline int32_t get_step_size(const DCAEncContext *c, int ch, int band)
|
||||
return step_size;
|
||||
}
|
||||
|
||||
static int calc_one_scale(int32_t peak_cb, int abits, softfloat *quant)
|
||||
static int calc_one_scale(DCAEncContext *c, int32_t peak_cb, int abits,
|
||||
softfloat *quant)
|
||||
{
|
||||
int32_t peak;
|
||||
int our_nscale, try_remove;
|
||||
@@ -680,7 +616,7 @@ static int calc_one_scale(int32_t peak_cb, int abits, softfloat *quant)
|
||||
av_assert0(peak_cb >= -2047);
|
||||
|
||||
our_nscale = 127;
|
||||
peak = cb_to_level[-peak_cb];
|
||||
peak = c->cb_to_level[-peak_cb];
|
||||
|
||||
for (try_remove = 64; try_remove > 0; try_remove >>= 1) {
|
||||
if (scalefactor_inv[our_nscale - try_remove].e + stepsize_inv[abits].e <= 17)
|
||||
@@ -706,15 +642,17 @@ static inline void quantize_adpcm_subband(DCAEncContext *c, int ch, int band)
|
||||
{
|
||||
int32_t step_size;
|
||||
int32_t diff_peak_cb = c->diff_peak_cb[ch][band];
|
||||
c->scale_factor[ch][band] = calc_one_scale(diff_peak_cb,
|
||||
c->scale_factor[ch][band] = calc_one_scale(c, diff_peak_cb,
|
||||
c->abits[ch][band],
|
||||
&c->quant[ch][band]);
|
||||
|
||||
step_size = get_step_size(c, ch, band);
|
||||
ff_dcaadpcm_do_real(c->prediction_mode[ch][band],
|
||||
c->quant[ch][band], ff_dca_scale_factor_quant7[c->scale_factor[ch][band]], step_size,
|
||||
c->adpcm_history[ch][band], c->subband[ch][band], c->adpcm_history[ch][band]+4, c->quantized[ch][band],
|
||||
SUBBAND_SAMPLES, cb_to_level[-diff_peak_cb]);
|
||||
c->quant[ch][band],
|
||||
ff_dca_scale_factor_quant7[c->scale_factor[ch][band]],
|
||||
step_size, c->adpcm_history[ch][band], c->subband[ch][band],
|
||||
c->adpcm_history[ch][band] + 4, c->quantized[ch][band],
|
||||
SUBBAND_SAMPLES, c->cb_to_level[-diff_peak_cb]);
|
||||
}
|
||||
|
||||
static void quantize_adpcm(DCAEncContext *c)
|
||||
@@ -731,21 +669,31 @@ static void quantize_pcm(DCAEncContext *c)
|
||||
{
|
||||
int sample, band, ch;
|
||||
|
||||
for (ch = 0; ch < c->fullband_channels; ch++)
|
||||
for (band = 0; band < 32; band++)
|
||||
if (c->prediction_mode[ch][band] == -1)
|
||||
for (sample = 0; sample < SUBBAND_SAMPLES; sample++)
|
||||
c->quantized[ch][band][sample] = quantize_value(c->subband[ch][band][sample], c->quant[ch][band]);
|
||||
for (ch = 0; ch < c->fullband_channels; ch++) {
|
||||
for (band = 0; band < 32; band++) {
|
||||
if (c->prediction_mode[ch][band] == -1) {
|
||||
for (sample = 0; sample < SUBBAND_SAMPLES; sample++) {
|
||||
int32_t val = quantize_value(c->subband[ch][band][sample],
|
||||
c->quant[ch][band]);
|
||||
c->quantized[ch][band][sample] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void accumulate_huff_bit_consumption(int abits, int32_t *quantized, uint32_t *result)
|
||||
static void accumulate_huff_bit_consumption(int abits, int32_t *quantized,
|
||||
uint32_t *result)
|
||||
{
|
||||
uint8_t sel, id = abits - 1;
|
||||
for (sel = 0; sel < ff_dca_quant_index_group_size[id]; sel++)
|
||||
result[sel] += ff_dca_vlc_calc_quant_bits(quantized, SUBBAND_SAMPLES, sel, id);
|
||||
result[sel] += ff_dca_vlc_calc_quant_bits(quantized, SUBBAND_SAMPLES,
|
||||
sel, id);
|
||||
}
|
||||
|
||||
static uint32_t set_best_code(uint32_t vlc_bits[DCA_CODE_BOOKS][7], uint32_t clc_bits[DCA_CODE_BOOKS], int32_t res[DCA_CODE_BOOKS])
|
||||
static uint32_t set_best_code(uint32_t vlc_bits[DCA_CODE_BOOKS][7],
|
||||
uint32_t clc_bits[DCA_CODE_BOOKS],
|
||||
int32_t res[DCA_CODE_BOOKS])
|
||||
{
|
||||
uint8_t i, sel;
|
||||
uint32_t best_sel_bits[DCA_CODE_BOOKS];
|
||||
@@ -784,7 +732,8 @@ static uint32_t set_best_code(uint32_t vlc_bits[DCA_CODE_BOOKS][7], uint32_t clc
|
||||
return bits;
|
||||
}
|
||||
|
||||
static uint32_t set_best_abits_code(int abits[DCAENC_SUBBANDS], int bands, int32_t *res)
|
||||
static uint32_t set_best_abits_code(int abits[DCAENC_SUBBANDS], int bands,
|
||||
int32_t *res)
|
||||
{
|
||||
uint8_t i;
|
||||
uint32_t t;
|
||||
@@ -845,7 +794,8 @@ static int init_quantization_noise(DCAEncContext *c, int noise, int forbid_zero)
|
||||
ret &= ~(USED_26ABITS | USED_1ABITS);
|
||||
}
|
||||
}
|
||||
c->consumed_bits += set_best_abits_code(c->abits[ch], 32, &c->bit_allocation_sel[ch]);
|
||||
c->consumed_bits += set_best_abits_code(c->abits[ch], 32,
|
||||
&c->bit_allocation_sel[ch]);
|
||||
}
|
||||
|
||||
/* Recalc scale_factor each time to get bits consumption in case of Huffman coding.
|
||||
@@ -854,7 +804,7 @@ static int init_quantization_noise(DCAEncContext *c, int noise, int forbid_zero)
|
||||
for (ch = 0; ch < c->fullband_channels; ch++) {
|
||||
for (band = 0; band < 32; band++) {
|
||||
if (c->prediction_mode[ch][band] == -1) {
|
||||
c->scale_factor[ch][band] = calc_one_scale(c->peak_cb[ch][band],
|
||||
c->scale_factor[ch][band] = calc_one_scale(c, c->peak_cb[ch][band],
|
||||
c->abits[ch][band],
|
||||
&c->quant[ch][band]);
|
||||
}
|
||||
@@ -868,7 +818,9 @@ static int init_quantization_noise(DCAEncContext *c, int noise, int forbid_zero)
|
||||
for (ch = 0; ch < c->fullband_channels; ch++) {
|
||||
for (band = 0; band < 32; band++) {
|
||||
if (c->abits[ch][band] && c->abits[ch][band] <= DCA_CODE_BOOKS) {
|
||||
accumulate_huff_bit_consumption(c->abits[ch][band], c->quantized[ch][band], huff_bit_count_accum[ch][c->abits[ch][band] - 1]);
|
||||
accumulate_huff_bit_consumption(c->abits[ch][band],
|
||||
c->quantized[ch][band],
|
||||
huff_bit_count_accum[ch][c->abits[ch][band] - 1]);
|
||||
clc_bit_count_accum[ch][c->abits[ch][band] - 1] += bit_consumption[c->abits[ch][band]];
|
||||
} else {
|
||||
bits_counter += bit_consumption[c->abits[ch][band]];
|
||||
@@ -877,7 +829,9 @@ static int init_quantization_noise(DCAEncContext *c, int noise, int forbid_zero)
|
||||
}
|
||||
|
||||
for (ch = 0; ch < c->fullband_channels; ch++) {
|
||||
bits_counter += set_best_code(huff_bit_count_accum[ch], clc_bit_count_accum[ch], c->quant_index_sel[ch]);
|
||||
bits_counter += set_best_code(huff_bit_count_accum[ch],
|
||||
clc_bit_count_accum[ch],
|
||||
c->quant_index_sel[ch]);
|
||||
}
|
||||
|
||||
c->consumed_bits += bits_counter;
|
||||
@@ -954,7 +908,8 @@ static void fill_in_adpcm_bufer(DCAEncContext *c)
|
||||
step_size = get_step_size(c, ch, band);
|
||||
|
||||
ff_dca_core_dequantize(c->adpcm_history[ch][band],
|
||||
c->quantized[ch][band]+12, step_size, ff_dca_scale_factor_quant7[c->scale_factor[ch][band]], 0, 4);
|
||||
c->quantized[ch][band]+12, step_size,
|
||||
ff_dca_scale_factor_quant7[c->scale_factor[ch][band]], 0, 4);
|
||||
} else {
|
||||
AV_COPY128U(c->adpcm_history[ch][band], c->adpcm_history[ch][band]+4);
|
||||
}
|
||||
@@ -977,7 +932,7 @@ static void fill_in_adpcm_bufer(DCAEncContext *c)
|
||||
static void calc_lfe_scales(DCAEncContext *c)
|
||||
{
|
||||
if (c->lfe_channel)
|
||||
c->lfe_scale_factor = calc_one_scale(c->lfe_peak_cb, 11, &c->lfe_quant);
|
||||
c->lfe_scale_factor = calc_one_scale(c, c->lfe_peak_cb, 11, &c->lfe_quant);
|
||||
}
|
||||
|
||||
static void put_frame_header(DCAEncContext *c)
|
||||
@@ -1118,7 +1073,8 @@ static void put_subframe_samples(DCAEncContext *c, int ss, int band, int ch)
|
||||
sel = c->quant_index_sel[ch][c->abits[ch][band] - 1];
|
||||
// Huffman codes
|
||||
if (sel < ff_dca_quant_index_group_size[c->abits[ch][band] - 1]) {
|
||||
ff_dca_vlc_enc_quant(&c->pb, &c->quantized[ch][band][ss * 8], 8, sel, c->abits[ch][band] - 1);
|
||||
ff_dca_vlc_enc_quant(&c->pb, &c->quantized[ch][band][ss * 8], 8,
|
||||
sel, c->abits[ch][band] - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1171,7 +1127,8 @@ static void put_subframe(DCAEncContext *c, int subframe)
|
||||
put_bits(&c->pb, 5, c->abits[ch][band]);
|
||||
}
|
||||
} else {
|
||||
ff_dca_vlc_enc_alloc(&c->pb, c->abits[ch], DCAENC_SUBBANDS, c->bit_allocation_sel[ch]);
|
||||
ff_dca_vlc_enc_alloc(&c->pb, c->abits[ch], DCAENC_SUBBANDS,
|
||||
c->bit_allocation_sel[ch]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1287,6 +1244,7 @@ AVCodec ff_dca_encoder = {
|
||||
.close = encode_close,
|
||||
.encode2 = encode_frame,
|
||||
.capabilities = AV_CODEC_CAP_EXPERIMENTAL,
|
||||
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
|
||||
.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S32,
|
||||
AV_SAMPLE_FMT_NONE },
|
||||
.supported_samplerates = sample_rates,
|
||||
|
||||
+364
-142
@@ -40,6 +40,7 @@
|
||||
#include "avcodec.h"
|
||||
#include "bytestream.h"
|
||||
#include "decode.h"
|
||||
#include "hwaccel.h"
|
||||
#include "internal.h"
|
||||
#include "thread.h"
|
||||
|
||||
@@ -369,8 +370,7 @@ static int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame)
|
||||
DecodeSimpleContext *ds = &avci->ds;
|
||||
AVPacket *pkt = ds->in_pkt;
|
||||
// copy to ensure we do not change pkt
|
||||
AVPacket tmp;
|
||||
int got_frame, actual_got_frame, did_split;
|
||||
int got_frame, actual_got_frame;
|
||||
int ret;
|
||||
|
||||
if (!pkt->data && !avci->draining) {
|
||||
@@ -390,31 +390,12 @@ static int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame)
|
||||
avctx->active_thread_type & FF_THREAD_FRAME))
|
||||
return AVERROR_EOF;
|
||||
|
||||
tmp = *pkt;
|
||||
#if FF_API_MERGE_SD
|
||||
FF_DISABLE_DEPRECATION_WARNINGS
|
||||
did_split = avci->compat_decode_partial_size ?
|
||||
ff_packet_split_and_drop_side_data(&tmp) :
|
||||
av_packet_split_side_data(&tmp);
|
||||
|
||||
if (did_split) {
|
||||
ret = extract_packet_props(avctx->internal, &tmp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = apply_param_change(avctx, &tmp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
FF_ENABLE_DEPRECATION_WARNINGS
|
||||
#endif
|
||||
|
||||
got_frame = 0;
|
||||
|
||||
if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) {
|
||||
ret = ff_thread_decode_frame(avctx, frame, &got_frame, &tmp);
|
||||
ret = ff_thread_decode_frame(avctx, frame, &got_frame, pkt);
|
||||
} else {
|
||||
ret = avctx->codec->decode(avctx, frame, &got_frame, &tmp);
|
||||
ret = avctx->codec->decode(avctx, frame, &got_frame, pkt);
|
||||
|
||||
if (!(avctx->codec->caps_internal & FF_CODEC_CAP_SETS_PKT_DTS))
|
||||
frame->pkt_dts = pkt->dts;
|
||||
@@ -544,13 +525,6 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
}
|
||||
}
|
||||
}
|
||||
#if FF_API_MERGE_SD
|
||||
if (did_split) {
|
||||
av_packet_free_side_data(&tmp);
|
||||
if(ret == tmp.size)
|
||||
ret = pkt->size;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (avctx->codec->type == AVMEDIA_TYPE_AUDIO &&
|
||||
!avci->showed_multi_packet_warning &&
|
||||
@@ -640,6 +614,28 @@ static int decode_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
|
||||
if (ret == AVERROR_EOF)
|
||||
avci->draining_done = 1;
|
||||
|
||||
if (!ret) {
|
||||
/* the only case where decode data is not set should be decoders
|
||||
* that do not call ff_get_buffer() */
|
||||
av_assert0((frame->private_ref && frame->private_ref->size == sizeof(FrameDecodeData)) ||
|
||||
!(avctx->codec->capabilities & AV_CODEC_CAP_DR1));
|
||||
|
||||
if (frame->private_ref) {
|
||||
FrameDecodeData *fdd = (FrameDecodeData*)frame->private_ref->data;
|
||||
|
||||
if (fdd->post_process) {
|
||||
ret = fdd->post_process(avctx, frame);
|
||||
if (ret < 0) {
|
||||
av_frame_unref(frame);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free the per-frame decode data */
|
||||
av_buffer_unref(&frame->private_ref);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -753,6 +749,11 @@ static int compat_decode(AVCodecContext *avctx, AVFrame *frame,
|
||||
|
||||
av_assert0(avci->compat_decode_consumed == 0);
|
||||
|
||||
if (avci->draining_done && pkt && pkt->size != 0) {
|
||||
av_log(avctx, AV_LOG_WARNING, "Got unexpected packet after EOF\n");
|
||||
avcodec_flush_buffers(avctx);
|
||||
}
|
||||
|
||||
*got_frame = 0;
|
||||
avci->compat_decode = 1;
|
||||
|
||||
@@ -999,7 +1000,6 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
|
||||
AVPacket *avpkt)
|
||||
{
|
||||
int i, ret = 0;
|
||||
AVCodecInternal *avci = avctx->internal;
|
||||
|
||||
if (!avpkt->data && avpkt->size) {
|
||||
av_log(avctx, AV_LOG_ERROR, "invalid packet: NULL data, size != 0\n");
|
||||
@@ -1016,29 +1016,9 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
|
||||
get_subtitle_defaults(sub);
|
||||
|
||||
if ((avctx->codec->capabilities & AV_CODEC_CAP_DELAY) || avpkt->size) {
|
||||
AVPacket pkt_recoded;
|
||||
AVPacket tmp = *avpkt;
|
||||
#if FF_API_MERGE_SD
|
||||
FF_DISABLE_DEPRECATION_WARNINGS
|
||||
int did_split = avci->compat_decode_partial_size ?
|
||||
ff_packet_split_and_drop_side_data(&tmp) :
|
||||
av_packet_split_side_data(&tmp);
|
||||
//apply_param_change(avctx, &tmp);
|
||||
AVPacket pkt_recoded = *avpkt;
|
||||
|
||||
if (did_split) {
|
||||
/* FFMIN() prevents overflow in case the packet wasn't allocated with
|
||||
* proper padding.
|
||||
* If the side data is smaller than the buffer padding size, the
|
||||
* remaining bytes should have already been filled with zeros by the
|
||||
* original packet allocation anyway. */
|
||||
memset(tmp.data + tmp.size, 0,
|
||||
FFMIN(avpkt->size - tmp.size, AV_INPUT_BUFFER_PADDING_SIZE));
|
||||
}
|
||||
FF_ENABLE_DEPRECATION_WARNINGS
|
||||
#endif
|
||||
|
||||
pkt_recoded = tmp;
|
||||
ret = recode_subtitle(avctx, &pkt_recoded, &tmp);
|
||||
ret = recode_subtitle(avctx, &pkt_recoded, avpkt);
|
||||
if (ret < 0) {
|
||||
*got_sub_ptr = 0;
|
||||
} else {
|
||||
@@ -1087,7 +1067,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp.data != pkt_recoded.data) { // did we recode?
|
||||
if (avpkt->data != pkt_recoded.data) { // did we recode?
|
||||
/* prevent from destroying side data from original packet */
|
||||
pkt_recoded.side_data = NULL;
|
||||
pkt_recoded.side_data_elems = 0;
|
||||
@@ -1096,14 +1076,6 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
}
|
||||
}
|
||||
|
||||
#if FF_API_MERGE_SD
|
||||
if (did_split) {
|
||||
av_packet_free_side_data(&tmp);
|
||||
if(ret == tmp.size)
|
||||
ret = avpkt->size;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (*got_sub_ptr)
|
||||
avctx->frame_number++;
|
||||
}
|
||||
@@ -1111,84 +1083,228 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int is_hwaccel_pix_fmt(enum AVPixelFormat pix_fmt)
|
||||
enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *avctx,
|
||||
const enum AVPixelFormat *fmt)
|
||||
{
|
||||
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
|
||||
return desc->flags & AV_PIX_FMT_FLAG_HWACCEL;
|
||||
}
|
||||
const AVPixFmtDescriptor *desc;
|
||||
const AVCodecHWConfig *config;
|
||||
int i, n;
|
||||
|
||||
enum AVPixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum AVPixelFormat *fmt)
|
||||
{
|
||||
while (*fmt != AV_PIX_FMT_NONE && is_hwaccel_pix_fmt(*fmt))
|
||||
++fmt;
|
||||
return fmt[0];
|
||||
}
|
||||
// If a device was supplied when the codec was opened, assume that the
|
||||
// user wants to use it.
|
||||
if (avctx->hw_device_ctx && avctx->codec->hw_configs) {
|
||||
AVHWDeviceContext *device_ctx =
|
||||
(AVHWDeviceContext*)avctx->hw_device_ctx->data;
|
||||
for (i = 0;; i++) {
|
||||
config = &avctx->codec->hw_configs[i]->public;
|
||||
if (!config)
|
||||
break;
|
||||
if (!(config->methods &
|
||||
AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX))
|
||||
continue;
|
||||
if (device_ctx->type != config->device_type)
|
||||
continue;
|
||||
for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++) {
|
||||
if (config->pix_fmt == fmt[n])
|
||||
return fmt[n];
|
||||
}
|
||||
}
|
||||
}
|
||||
// No device or other setup, so we have to choose from things which
|
||||
// don't any other external information.
|
||||
|
||||
static AVHWAccel *find_hwaccel(enum AVCodecID codec_id,
|
||||
enum AVPixelFormat pix_fmt)
|
||||
{
|
||||
AVHWAccel *hwaccel = NULL;
|
||||
// If the last element of the list is a software format, choose it
|
||||
// (this should be best software format if any exist).
|
||||
for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++);
|
||||
desc = av_pix_fmt_desc_get(fmt[n - 1]);
|
||||
if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
|
||||
return fmt[n - 1];
|
||||
|
||||
while ((hwaccel = av_hwaccel_next(hwaccel)))
|
||||
if (hwaccel->id == codec_id
|
||||
&& hwaccel->pix_fmt == pix_fmt)
|
||||
return hwaccel;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int setup_hwaccel(AVCodecContext *avctx,
|
||||
const enum AVPixelFormat fmt,
|
||||
const char *name)
|
||||
{
|
||||
AVHWAccel *hwa = find_hwaccel(avctx->codec_id, fmt);
|
||||
int ret = 0;
|
||||
|
||||
if (!hwa) {
|
||||
av_log(avctx, AV_LOG_ERROR,
|
||||
"Could not find an AVHWAccel for the pixel format: %s",
|
||||
name);
|
||||
return AVERROR(ENOENT);
|
||||
// Finally, traverse the list in order and choose the first entry
|
||||
// with no external dependencies (if there is no hardware configuration
|
||||
// information available then this just picks the first entry).
|
||||
for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++) {
|
||||
for (i = 0;; i++) {
|
||||
config = avcodec_get_hw_config(avctx->codec, i);
|
||||
if (!config)
|
||||
break;
|
||||
if (config->pix_fmt == fmt[n])
|
||||
break;
|
||||
}
|
||||
if (!config) {
|
||||
// No specific config available, so the decoder must be able
|
||||
// to handle this format without any additional setup.
|
||||
return fmt[n];
|
||||
}
|
||||
if (config->methods & AV_CODEC_HW_CONFIG_METHOD_INTERNAL) {
|
||||
// Usable with only internal setup.
|
||||
return fmt[n];
|
||||
}
|
||||
}
|
||||
|
||||
if (hwa->capabilities & AV_HWACCEL_CODEC_CAP_EXPERIMENTAL &&
|
||||
// Nothing is usable, give up.
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx,
|
||||
enum AVHWDeviceType dev_type)
|
||||
{
|
||||
AVHWDeviceContext *device_ctx;
|
||||
AVHWFramesContext *frames_ctx;
|
||||
int ret;
|
||||
|
||||
if (!avctx->hwaccel)
|
||||
return AVERROR(ENOSYS);
|
||||
|
||||
if (avctx->hw_frames_ctx)
|
||||
return 0;
|
||||
if (!avctx->hw_device_ctx) {
|
||||
av_log(avctx, AV_LOG_ERROR, "A hardware frames or device context is "
|
||||
"required for hardware accelerated decoding.\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
device_ctx = (AVHWDeviceContext *)avctx->hw_device_ctx->data;
|
||||
if (device_ctx->type != dev_type) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Device type %s expected for hardware "
|
||||
"decoding, but got %s.\n", av_hwdevice_get_type_name(dev_type),
|
||||
av_hwdevice_get_type_name(device_ctx->type));
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
ret = avcodec_get_hw_frames_parameters(avctx,
|
||||
avctx->hw_device_ctx,
|
||||
avctx->hwaccel->pix_fmt,
|
||||
&avctx->hw_frames_ctx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
|
||||
|
||||
|
||||
if (frames_ctx->initial_pool_size) {
|
||||
// We guarantee 4 base work surfaces. The function above guarantees 1
|
||||
// (the absolute minimum), so add the missing count.
|
||||
frames_ctx->initial_pool_size += 3;
|
||||
|
||||
// Add an additional surface per thread is frame threading is enabled.
|
||||
if (avctx->active_thread_type & FF_THREAD_FRAME)
|
||||
frames_ctx->initial_pool_size += avctx->thread_count;
|
||||
}
|
||||
|
||||
ret = av_hwframe_ctx_init(avctx->hw_frames_ctx);
|
||||
if (ret < 0) {
|
||||
av_buffer_unref(&avctx->hw_frames_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int avcodec_get_hw_frames_parameters(AVCodecContext *avctx,
|
||||
AVBufferRef *device_ref,
|
||||
enum AVPixelFormat hw_pix_fmt,
|
||||
AVBufferRef **out_frames_ref)
|
||||
{
|
||||
AVBufferRef *frames_ref = NULL;
|
||||
const AVCodecHWConfigInternal *hw_config;
|
||||
const AVHWAccel *hwa;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0;; i++) {
|
||||
hw_config = avctx->codec->hw_configs[i];
|
||||
if (!hw_config)
|
||||
return AVERROR(ENOENT);
|
||||
if (hw_config->public.pix_fmt == hw_pix_fmt)
|
||||
break;
|
||||
}
|
||||
|
||||
hwa = hw_config->hwaccel;
|
||||
if (!hwa || !hwa->frame_params)
|
||||
return AVERROR(ENOENT);
|
||||
|
||||
frames_ref = av_hwframe_ctx_alloc(device_ref);
|
||||
if (!frames_ref)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
ret = hwa->frame_params(avctx, frames_ref);
|
||||
if (ret >= 0) {
|
||||
*out_frames_ref = frames_ref;
|
||||
} else {
|
||||
av_buffer_unref(&frames_ref);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hwaccel_init(AVCodecContext *avctx,
|
||||
const AVCodecHWConfigInternal *hw_config)
|
||||
{
|
||||
const AVHWAccel *hwaccel;
|
||||
int err;
|
||||
|
||||
hwaccel = hw_config->hwaccel;
|
||||
if (hwaccel->capabilities & AV_HWACCEL_CODEC_CAP_EXPERIMENTAL &&
|
||||
avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
|
||||
av_log(avctx, AV_LOG_WARNING, "Ignoring experimental hwaccel: %s\n",
|
||||
hwa->name);
|
||||
hwaccel->name);
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
|
||||
if (hwa->priv_data_size) {
|
||||
avctx->internal->hwaccel_priv_data = av_mallocz(hwa->priv_data_size);
|
||||
if (hwaccel->priv_data_size) {
|
||||
avctx->internal->hwaccel_priv_data =
|
||||
av_mallocz(hwaccel->priv_data_size);
|
||||
if (!avctx->internal->hwaccel_priv_data)
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
avctx->hwaccel = hwa;
|
||||
if (hwa->init) {
|
||||
ret = hwa->init(avctx);
|
||||
if (ret < 0) {
|
||||
avctx->hwaccel = hwaccel;
|
||||
if (hwaccel->init) {
|
||||
err = hwaccel->init(avctx);
|
||||
if (err < 0) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Failed setup for format %s: "
|
||||
"hwaccel initialisation returned error.\n",
|
||||
av_get_pix_fmt_name(hw_config->public.pix_fmt));
|
||||
av_freep(&avctx->internal->hwaccel_priv_data);
|
||||
avctx->hwaccel = NULL;
|
||||
return ret;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hwaccel_uninit(AVCodecContext *avctx)
|
||||
{
|
||||
if (avctx->hwaccel && avctx->hwaccel->uninit)
|
||||
avctx->hwaccel->uninit(avctx);
|
||||
|
||||
av_freep(&avctx->internal->hwaccel_priv_data);
|
||||
|
||||
avctx->hwaccel = NULL;
|
||||
|
||||
av_buffer_unref(&avctx->hw_frames_ctx);
|
||||
}
|
||||
|
||||
int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
|
||||
{
|
||||
const AVPixFmtDescriptor *desc;
|
||||
enum AVPixelFormat *choices;
|
||||
enum AVPixelFormat ret;
|
||||
unsigned n = 0;
|
||||
|
||||
while (fmt[n] != AV_PIX_FMT_NONE)
|
||||
++n;
|
||||
enum AVPixelFormat ret, user_choice;
|
||||
const AVCodecHWConfigInternal *hw_config;
|
||||
const AVCodecHWConfig *config;
|
||||
int i, n, err;
|
||||
|
||||
// Find end of list.
|
||||
for (n = 0; fmt[n] != AV_PIX_FMT_NONE; n++);
|
||||
// Must contain at least one entry.
|
||||
av_assert0(n >= 1);
|
||||
avctx->sw_pix_fmt = fmt[n - 1];
|
||||
av_assert2(!is_hwaccel_pix_fmt(avctx->sw_pix_fmt));
|
||||
// If a software format is available, it must be the last entry.
|
||||
desc = av_pix_fmt_desc_get(fmt[n - 1]);
|
||||
if (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
|
||||
// No software format is available.
|
||||
} else {
|
||||
avctx->sw_pix_fmt = fmt[n - 1];
|
||||
}
|
||||
|
||||
choices = av_malloc_array(n + 1, sizeof(*choices));
|
||||
if (!choices)
|
||||
@@ -1197,48 +1313,108 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt)
|
||||
memcpy(choices, fmt, (n + 1) * sizeof(*choices));
|
||||
|
||||
for (;;) {
|
||||
if (avctx->hwaccel && avctx->hwaccel->uninit)
|
||||
avctx->hwaccel->uninit(avctx);
|
||||
av_freep(&avctx->internal->hwaccel_priv_data);
|
||||
avctx->hwaccel = NULL;
|
||||
// Remove the previous hwaccel, if there was one.
|
||||
hwaccel_uninit(avctx);
|
||||
|
||||
av_buffer_unref(&avctx->hw_frames_ctx);
|
||||
|
||||
ret = avctx->get_format(avctx, choices);
|
||||
|
||||
desc = av_pix_fmt_desc_get(ret);
|
||||
if (!desc) {
|
||||
user_choice = avctx->get_format(avctx, choices);
|
||||
if (user_choice == AV_PIX_FMT_NONE) {
|
||||
// Explicitly chose nothing, give up.
|
||||
ret = AV_PIX_FMT_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
|
||||
desc = av_pix_fmt_desc_get(user_choice);
|
||||
if (!desc) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Invalid format returned by "
|
||||
"get_format() callback.\n");
|
||||
ret = AV_PIX_FMT_NONE;
|
||||
break;
|
||||
#if FF_API_CAP_VDPAU
|
||||
if (avctx->codec->capabilities&AV_CODEC_CAP_HWACCEL_VDPAU)
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
av_log(avctx, AV_LOG_DEBUG, "Format %s chosen by get_format().\n",
|
||||
desc->name);
|
||||
|
||||
if (avctx->hw_frames_ctx) {
|
||||
AVHWFramesContext *hw_frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
|
||||
if (hw_frames_ctx->format != ret) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Format returned from get_buffer() "
|
||||
"does not match the format of provided AVHWFramesContext\n");
|
||||
ret = AV_PIX_FMT_NONE;
|
||||
for (i = 0; i < n; i++) {
|
||||
if (choices[i] == user_choice)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == n) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Invalid return from get_format(): "
|
||||
"%s not in possible list.\n", desc->name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!setup_hwaccel(avctx, ret, desc->name))
|
||||
if (avctx->codec->hw_configs) {
|
||||
for (i = 0;; i++) {
|
||||
hw_config = avctx->codec->hw_configs[i];
|
||||
if (!hw_config)
|
||||
break;
|
||||
if (hw_config->public.pix_fmt == user_choice)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
hw_config = NULL;
|
||||
}
|
||||
|
||||
if (!hw_config) {
|
||||
// No config available, so no extra setup required.
|
||||
ret = user_choice;
|
||||
break;
|
||||
}
|
||||
config = &hw_config->public;
|
||||
|
||||
/* Remove failed hwaccel from choices */
|
||||
for (n = 0; choices[n] != ret; n++)
|
||||
av_assert0(choices[n] != AV_PIX_FMT_NONE);
|
||||
if (config->methods &
|
||||
AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX &&
|
||||
avctx->hw_frames_ctx) {
|
||||
const AVHWFramesContext *frames_ctx =
|
||||
(AVHWFramesContext*)avctx->hw_frames_ctx->data;
|
||||
if (frames_ctx->format != user_choice) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Invalid setup for format %s: "
|
||||
"does not match the format of the provided frames "
|
||||
"context.\n", desc->name);
|
||||
goto try_again;
|
||||
}
|
||||
} else if (config->methods &
|
||||
AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&
|
||||
avctx->hw_device_ctx) {
|
||||
const AVHWDeviceContext *device_ctx =
|
||||
(AVHWDeviceContext*)avctx->hw_device_ctx->data;
|
||||
if (device_ctx->type != config->device_type) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Invalid setup for format %s: "
|
||||
"does not match the type of the provided device "
|
||||
"context.\n", desc->name);
|
||||
goto try_again;
|
||||
}
|
||||
} else if (config->methods &
|
||||
AV_CODEC_HW_CONFIG_METHOD_INTERNAL) {
|
||||
// Internal-only setup, no additional configuration.
|
||||
} else if (config->methods &
|
||||
AV_CODEC_HW_CONFIG_METHOD_AD_HOC) {
|
||||
// Some ad-hoc configuration we can't see and can't check.
|
||||
} else {
|
||||
av_log(avctx, AV_LOG_ERROR, "Invalid setup for format %s: "
|
||||
"missing configuration.\n", desc->name);
|
||||
goto try_again;
|
||||
}
|
||||
if (hw_config->hwaccel) {
|
||||
av_log(avctx, AV_LOG_DEBUG, "Format %s requires hwaccel "
|
||||
"initialisation.\n", desc->name);
|
||||
err = hwaccel_init(avctx, hw_config);
|
||||
if (err < 0)
|
||||
goto try_again;
|
||||
}
|
||||
ret = user_choice;
|
||||
break;
|
||||
|
||||
do
|
||||
choices[n] = choices[n + 1];
|
||||
while (choices[n++] != AV_PIX_FMT_NONE);
|
||||
try_again:
|
||||
av_log(avctx, AV_LOG_DEBUG, "Format %s not usable, retrying "
|
||||
"get_format() without it.\n", desc->name);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (choices[i] == user_choice)
|
||||
break;
|
||||
}
|
||||
for (; i + 1 < n; i++)
|
||||
choices[i] = choices[i + 1];
|
||||
--n;
|
||||
}
|
||||
|
||||
av_freep(&choices);
|
||||
@@ -1612,6 +1788,43 @@ static void validate_avframe_allocation(AVCodecContext *avctx, AVFrame *frame)
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_data_free(void *opaque, uint8_t *data)
|
||||
{
|
||||
FrameDecodeData *fdd = (FrameDecodeData*)data;
|
||||
|
||||
if (fdd->post_process_opaque_free)
|
||||
fdd->post_process_opaque_free(fdd->post_process_opaque);
|
||||
|
||||
if (fdd->hwaccel_priv_free)
|
||||
fdd->hwaccel_priv_free(fdd->hwaccel_priv);
|
||||
|
||||
av_freep(&fdd);
|
||||
}
|
||||
|
||||
int ff_attach_decode_data(AVFrame *frame)
|
||||
{
|
||||
AVBufferRef *fdd_buf;
|
||||
FrameDecodeData *fdd;
|
||||
|
||||
av_assert1(!frame->private_ref);
|
||||
av_buffer_unref(&frame->private_ref);
|
||||
|
||||
fdd = av_mallocz(sizeof(*fdd));
|
||||
if (!fdd)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
fdd_buf = av_buffer_create((uint8_t*)fdd, sizeof(*fdd), decode_data_free,
|
||||
NULL, AV_BUFFER_FLAG_READONLY);
|
||||
if (!fdd_buf) {
|
||||
av_freep(&fdd);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
|
||||
frame->private_ref = fdd_buf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags)
|
||||
{
|
||||
const AVHWAccel *hwaccel = avctx->hwaccel;
|
||||
@@ -1648,8 +1861,14 @@ static int get_buffer_internal(AVCodecContext *avctx, AVFrame *frame, int flags)
|
||||
avctx->sw_pix_fmt = avctx->pix_fmt;
|
||||
|
||||
ret = avctx->get_buffer2(avctx, frame, flags);
|
||||
if (ret >= 0)
|
||||
validate_avframe_allocation(avctx, frame);
|
||||
if (ret < 0)
|
||||
goto end;
|
||||
|
||||
validate_avframe_allocation(avctx, frame);
|
||||
|
||||
ret = ff_attach_decode_data(frame);
|
||||
if (ret < 0)
|
||||
goto end;
|
||||
|
||||
end:
|
||||
if (avctx->codec_type == AVMEDIA_TYPE_VIDEO && !override_dimensions &&
|
||||
@@ -1658,6 +1877,9 @@ end:
|
||||
frame->height = avctx->height;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
av_frame_unref(frame);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,38 @@
|
||||
#ifndef AVCODEC_DECODE_H
|
||||
#define AVCODEC_DECODE_H
|
||||
|
||||
#include "libavutil/buffer.h"
|
||||
#include "libavutil/frame.h"
|
||||
#include "libavutil/hwcontext.h"
|
||||
|
||||
#include "avcodec.h"
|
||||
|
||||
/**
|
||||
* This struct stores per-frame lavc-internal data and is attached to it via
|
||||
* private_ref.
|
||||
*/
|
||||
typedef struct FrameDecodeData {
|
||||
/**
|
||||
* The callback to perform some delayed processing on the frame right
|
||||
* before it is returned to the caller.
|
||||
*
|
||||
* @note This code is called at some unspecified point after the frame is
|
||||
* returned from the decoder's decode/receive_frame call. Therefore it cannot rely
|
||||
* on AVCodecContext being in any specific state, so it does not get to
|
||||
* access AVCodecContext directly at all. All the state it needs must be
|
||||
* stored in the post_process_opaque object.
|
||||
*/
|
||||
int (*post_process)(void *logctx, AVFrame *frame);
|
||||
void *post_process_opaque;
|
||||
void (*post_process_opaque_free)(void *opaque);
|
||||
|
||||
/**
|
||||
* Per-frame private data for hwaccels.
|
||||
*/
|
||||
void *hwaccel_priv;
|
||||
void (*hwaccel_priv_free)(void *priv);
|
||||
} FrameDecodeData;
|
||||
|
||||
/**
|
||||
* Called by decoders to get the next packet for decoding.
|
||||
*
|
||||
@@ -36,4 +66,14 @@ int ff_decode_get_packet(AVCodecContext *avctx, AVPacket *pkt);
|
||||
|
||||
void ff_decode_bsfs_uninit(AVCodecContext *avctx);
|
||||
|
||||
/**
|
||||
* Make sure avctx.hw_frames_ctx is set. If it's not set, the function will
|
||||
* try to allocate it from hw_device_ctx. If that is not possible, an error
|
||||
* message is printed, and an error code is returned.
|
||||
*/
|
||||
int ff_decode_get_hw_frames_ctx(AVCodecContext *avctx,
|
||||
enum AVHWDeviceType dev_type);
|
||||
|
||||
int ff_attach_decode_data(AVFrame *frame);
|
||||
|
||||
#endif /* AVCODEC_DECODE_H */
|
||||
|
||||
+3
-1
@@ -149,6 +149,8 @@ static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height
|
||||
int mask = 0x10000, bitbuf = 0;
|
||||
int i, v, offset, count, segments;
|
||||
|
||||
if ((width | height) & 1)
|
||||
return AVERROR_INVALIDDATA;
|
||||
segments = bytestream2_get_le16(gb);
|
||||
while (segments--) {
|
||||
if (bytestream2_get_bytes_left(gb) < 2)
|
||||
@@ -176,7 +178,7 @@ static int decode_dds1(GetByteContext *gb, uint8_t *frame, int width, int height
|
||||
return AVERROR_INVALIDDATA;
|
||||
frame += v;
|
||||
} else {
|
||||
if (frame_end - frame < width + 4)
|
||||
if (width < 4 || frame_end - frame < width + 4)
|
||||
return AVERROR_INVALIDDATA;
|
||||
frame[0] = frame[1] =
|
||||
frame[width] = frame[width + 1] = bytestream2_get_byte(gb);
|
||||
|
||||
+5
-1
@@ -147,6 +147,7 @@ static int parse_source_parameters(AVDiracSeqHeader *dsh, GetBitContext *gb,
|
||||
unsigned luma_depth = 8, luma_offset = 16;
|
||||
int idx;
|
||||
int chroma_x_shift, chroma_y_shift;
|
||||
int ret;
|
||||
|
||||
/* [DIRAC_STD] 10.3.2 Frame size. frame_size(video_params) */
|
||||
/* [DIRAC_STD] custom_dimensions_flag */
|
||||
@@ -269,7 +270,10 @@ static int parse_source_parameters(AVDiracSeqHeader *dsh, GetBitContext *gb,
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
dsh->pix_fmt = dirac_pix_fmt[dsh->chroma_format][dsh->pixel_range_index-2];
|
||||
avcodec_get_chroma_sub_sample(dsh->pix_fmt, &chroma_x_shift, &chroma_y_shift);
|
||||
ret = av_pix_fmt_get_chroma_sub_sample(dsh->pix_fmt, &chroma_x_shift, &chroma_y_shift);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((dsh->width % (1<<chroma_x_shift)) || (dsh->height % (1<<chroma_y_shift))) {
|
||||
if (log_ctx)
|
||||
av_log(log_ctx, AV_LOG_ERROR, "Dimensions must be an integer multiple of the chroma subsampling\n");
|
||||
|
||||
+10
-10
@@ -99,34 +99,34 @@ void ff_spatial_idwt_slice2(DWTContext *d, int y);
|
||||
(b1 + ((int)(b0 + (unsigned)(b2) + 1) >> 1))
|
||||
|
||||
#define COMPOSE_DD97iH0(b0, b1, b2, b3, b4)\
|
||||
(b2 + ((int)(-b0 + 9U*b1 + 9U*b3 - b4 + 8) >> 4))
|
||||
(int)(((unsigned)(b2) + ((int)(-b0 + 9U*b1 + 9U*b3 - b4 + 8) >> 4)))
|
||||
|
||||
#define COMPOSE_DD137iL0(b0, b1, b2, b3, b4)\
|
||||
(b2 - ((-b0 + 9*b1 + 9*b3 - b4 + 16) >> 5))
|
||||
(int)(((unsigned)(b2) - ((int)(-b0 + 9U*b1 + 9U*b3 - b4 + 16) >> 5)))
|
||||
|
||||
#define COMPOSE_HAARiL0(b0, b1)\
|
||||
(b0 - ((b1 + 1) >> 1))
|
||||
((int)(b0 - (unsigned)((int)(b1 + 1U) >> 1)))
|
||||
|
||||
#define COMPOSE_HAARiH0(b0, b1)\
|
||||
(b0 + b1)
|
||||
((int)(b0 + (unsigned)(b1)))
|
||||
|
||||
#define COMPOSE_FIDELITYiL0(b0, b1, b2, b3, b4, b5, b6, b7, b8)\
|
||||
(b4 - ((int)(-8*(b0+(unsigned)b8) + 21*(b1+(unsigned)b7) - 46*(b2+(unsigned)b6) + 161*(b3+(unsigned)b5) + 128) >> 8))
|
||||
((unsigned)b4 - ((int)(-8*(b0+(unsigned)b8) + 21*(b1+(unsigned)b7) - 46*(b2+(unsigned)b6) + 161*(b3+(unsigned)b5) + 128) >> 8))
|
||||
|
||||
#define COMPOSE_FIDELITYiH0(b0, b1, b2, b3, b4, b5, b6, b7, b8)\
|
||||
(b4 + ((int)(-2*(b0+(unsigned)b8) + 10*(b1+(unsigned)b7) - 25*(b2+(unsigned)b6) + 81*(b3+(unsigned)b5) + 128) >> 8))
|
||||
((unsigned)b4 + ((int)(-2*(b0+(unsigned)b8) + 10*(b1+(unsigned)b7) - 25*(b2+(unsigned)b6) + 81*(b3+(unsigned)b5) + 128) >> 8))
|
||||
|
||||
#define COMPOSE_DAUB97iL1(b0, b1, b2)\
|
||||
(b1 - ((int)(1817*(b0 + (unsigned)b2) + 2048) >> 12))
|
||||
((unsigned)(b1) - ((int)(1817*(b0 + (unsigned)b2) + 2048) >> 12))
|
||||
|
||||
#define COMPOSE_DAUB97iH1(b0, b1, b2)\
|
||||
(b1 - ((int)( 113*(b0 + (unsigned)b2) + 64) >> 7))
|
||||
((unsigned)(b1) - ((int)( 113*(b0 + (unsigned)b2) + 64) >> 7))
|
||||
|
||||
#define COMPOSE_DAUB97iL0(b0, b1, b2)\
|
||||
(b1 + ((int)( 217*(b0 + (unsigned)b2) + 2048) >> 12))
|
||||
((unsigned)(b1) + ((int)( 217*(b0 + (unsigned)b2) + 2048) >> 12))
|
||||
|
||||
#define COMPOSE_DAUB97iH0(b0, b1, b2)\
|
||||
(b1 + ((int)(6497*(b0 + (unsigned)b2) + 2048) >> 12))
|
||||
((unsigned)(b1) + ((int)(6497*(b0 + (unsigned)b2) + 2048) >> 12))
|
||||
|
||||
|
||||
#endif /* AVCODEC_DWT_H */
|
||||
|
||||
+15
-7
@@ -26,6 +26,7 @@
|
||||
* @author Marco Gerards <marco@gnu.org>, David Conrad, Jordi Ortiz <nenjordi@gmail.com>
|
||||
*/
|
||||
|
||||
#include "libavutil/pixdesc.h"
|
||||
#include "libavutil/thread.h"
|
||||
#include "avcodec.h"
|
||||
#include "get_bits.h"
|
||||
@@ -508,16 +509,16 @@ static inline void codeblock(DiracContext *s, SubBand *b,
|
||||
}
|
||||
|
||||
if (s->codeblock_mode && !(s->old_delta_quant && blockcnt_one)) {
|
||||
int quant = b->quant;
|
||||
int quant;
|
||||
if (is_arith)
|
||||
quant += dirac_get_arith_int(c, CTX_DELTA_Q_F, CTX_DELTA_Q_DATA);
|
||||
quant = dirac_get_arith_int(c, CTX_DELTA_Q_F, CTX_DELTA_Q_DATA);
|
||||
else
|
||||
quant += dirac_get_se_golomb(gb);
|
||||
if (quant < 0) {
|
||||
quant = dirac_get_se_golomb(gb);
|
||||
if (quant > INT_MAX - b->quant || b->quant + quant < 0) {
|
||||
av_log(s->avctx, AV_LOG_ERROR, "Invalid quant\n");
|
||||
return;
|
||||
}
|
||||
b->quant = quant;
|
||||
b->quant += quant;
|
||||
}
|
||||
|
||||
if (b->quant > (DIRAC_MAX_QUANT_INDEX - 1)) {
|
||||
@@ -1927,7 +1928,10 @@ static int get_buffer_with_edge(AVCodecContext *avctx, AVFrame *f, int flags)
|
||||
{
|
||||
int ret, i;
|
||||
int chroma_x_shift, chroma_y_shift;
|
||||
avcodec_get_chroma_sub_sample(avctx->pix_fmt, &chroma_x_shift, &chroma_y_shift);
|
||||
ret = av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt, &chroma_x_shift,
|
||||
&chroma_y_shift);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
f->width = avctx->width + 2 * EDGE_WIDTH;
|
||||
f->height = avctx->height + 2 * EDGE_WIDTH + 2;
|
||||
@@ -2126,7 +2130,11 @@ static int dirac_decode_data_unit(AVCodecContext *avctx, const uint8_t *buf, int
|
||||
|
||||
s->pshift = s->bit_depth > 8;
|
||||
|
||||
avcodec_get_chroma_sub_sample(avctx->pix_fmt, &s->chroma_x_shift, &s->chroma_y_shift);
|
||||
ret = av_pix_fmt_get_chroma_sub_sample(avctx->pix_fmt,
|
||||
&s->chroma_x_shift,
|
||||
&s->chroma_y_shift);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = alloc_sequence_buffers(s);
|
||||
if (ret < 0)
|
||||
|
||||
@@ -159,10 +159,10 @@ static void put_signed_rect_clamped_ ## PX ## bit_c(uint8_t *_dst, int dst_strid
|
||||
int32_t *src = (int32_t *)_src; \
|
||||
for (y = 0; y < height; y++) { \
|
||||
for (x = 0; x < width; x+=4) { \
|
||||
dst[x ] = av_clip_uintp2(src[x ] + (1 << (PX - 1)), PX); \
|
||||
dst[x+1] = av_clip_uintp2(src[x+1] + (1 << (PX - 1)), PX); \
|
||||
dst[x+2] = av_clip_uintp2(src[x+2] + (1 << (PX - 1)), PX); \
|
||||
dst[x+3] = av_clip_uintp2(src[x+3] + (1 << (PX - 1)), PX); \
|
||||
dst[x ] = av_clip_uintp2(src[x ] + (1U << (PX - 1)), PX); \
|
||||
dst[x+1] = av_clip_uintp2(src[x+1] + (1U << (PX - 1)), PX); \
|
||||
dst[x+2] = av_clip_uintp2(src[x+2] + (1U << (PX - 1)), PX); \
|
||||
dst[x+3] = av_clip_uintp2(src[x+3] + (1U << (PX - 1)), PX); \
|
||||
} \
|
||||
dst += dst_stride >> 1; \
|
||||
src += src_stride >> 2; \
|
||||
|
||||
+19
-38
@@ -939,96 +939,84 @@ const CIDEntry ff_dnxhd_cid_table[] = {
|
||||
dnxhd_1235_dc_codes, dnxhd_1235_dc_bits,
|
||||
dnxhd_1235_ac_codes, dnxhd_1235_ac_bits, dnxhd_1235_ac_info,
|
||||
dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1235_run,
|
||||
{ 175, 185, 365, 440 },
|
||||
{ { 24000, 1001 }, { 25, 1 }, { 50, 1 }, { 60000, 1001 } } },
|
||||
{ 175, 185, 365, 440 } },
|
||||
{ 1237, 1920, 1080, 606208, 606208,
|
||||
0, 4, 8, 3,
|
||||
dnxhd_1237_luma_weight, dnxhd_1237_chroma_weight,
|
||||
dnxhd_1237_dc_codes, dnxhd_1237_dc_bits,
|
||||
dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_info,
|
||||
dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run,
|
||||
{ 115, 120, 145, 240, 290 },
|
||||
{ { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } },
|
||||
{ 115, 120, 145, 240, 290 } },
|
||||
{ 1238, 1920, 1080, 917504, 917504,
|
||||
0, 4, 8, 4,
|
||||
dnxhd_1238_luma_weight, dnxhd_1238_chroma_weight,
|
||||
dnxhd_1237_dc_codes, dnxhd_1237_dc_bits,
|
||||
dnxhd_1238_ac_codes, dnxhd_1238_ac_bits, dnxhd_1238_ac_info,
|
||||
dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1238_run,
|
||||
{ 175, 185, 220, 365, 440 },
|
||||
{ { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } },
|
||||
{ 175, 185, 220, 365, 440 } },
|
||||
{ 1241, 1920, 1080, 917504, 458752,
|
||||
DNXHD_INTERLACED, 6, 10, 4,
|
||||
dnxhd_1241_luma_weight, dnxhd_1241_chroma_weight,
|
||||
dnxhd_1235_dc_codes, dnxhd_1235_dc_bits,
|
||||
dnxhd_1235_ac_codes, dnxhd_1235_ac_bits, dnxhd_1235_ac_info,
|
||||
dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1235_run,
|
||||
{ 185, 220 },
|
||||
{ { 25, 1 }, { 30000, 1001 } } },
|
||||
{ 185, 220 } },
|
||||
{ 1242, 1920, 1080, 606208, 303104,
|
||||
DNXHD_INTERLACED, 4, 8, 3,
|
||||
dnxhd_1242_luma_weight, dnxhd_1242_chroma_weight,
|
||||
dnxhd_1237_dc_codes, dnxhd_1237_dc_bits,
|
||||
dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_info,
|
||||
dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run,
|
||||
{ 120, 145 },
|
||||
{ { 25, 1 }, { 30000, 1001 } } },
|
||||
{ 120, 145 } },
|
||||
{ 1243, 1920, 1080, 917504, 458752,
|
||||
DNXHD_INTERLACED, 4, 8, 4,
|
||||
dnxhd_1243_luma_weight, dnxhd_1243_chroma_weight,
|
||||
dnxhd_1237_dc_codes, dnxhd_1237_dc_bits,
|
||||
dnxhd_1238_ac_codes, dnxhd_1238_ac_bits, dnxhd_1238_ac_info,
|
||||
dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1238_run,
|
||||
{ 185, 220 },
|
||||
{ { 25, 1 }, { 30000, 1001 } } },
|
||||
{ 185, 220 } },
|
||||
{ 1244, 1440, 1080, 606208, 303104,
|
||||
DNXHD_INTERLACED, 4, 8, 3,
|
||||
dnxhd_1260_luma_weight, dnxhd_1260_chroma_weight,
|
||||
dnxhd_1237_dc_codes, dnxhd_1237_dc_bits,
|
||||
dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_info,
|
||||
dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run,
|
||||
{ 120, 145 },
|
||||
{ { 25, 1 }, { 30000, 1001 } } },
|
||||
{ 120, 145 } },
|
||||
{ 1250, 1280, 720, 458752, 458752,
|
||||
0, 6, 10, 4,
|
||||
dnxhd_1250_luma_weight, dnxhd_1250_chroma_weight,
|
||||
dnxhd_1235_dc_codes, dnxhd_1235_dc_bits,
|
||||
dnxhd_1250_ac_codes, dnxhd_1250_ac_bits, dnxhd_1250_ac_info,
|
||||
dnxhd_1250_run_codes, dnxhd_1250_run_bits, dnxhd_1250_run,
|
||||
{ 90, 90, 180, 220 },
|
||||
{ { 24000, 1001 }, { 25, 1 }, { 50, 1 }, { 60000, 1001 } } },
|
||||
{ 90, 180, 220 } },
|
||||
{ 1251, 1280, 720, 458752, 458752,
|
||||
0, 4, 8, 4,
|
||||
dnxhd_1251_luma_weight, dnxhd_1251_chroma_weight,
|
||||
dnxhd_1237_dc_codes, dnxhd_1237_dc_bits,
|
||||
dnxhd_1251_ac_codes, dnxhd_1251_ac_bits, dnxhd_1251_ac_info,
|
||||
dnxhd_1250_run_codes, dnxhd_1250_run_bits, dnxhd_1250_run,
|
||||
{ 90, 90, 110, 180, 220 },
|
||||
{ { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } },
|
||||
{ 90, 110, 180, 220 } },
|
||||
{ 1252, 1280, 720, 303104, 303104,
|
||||
0, 4, 8, 5,
|
||||
dnxhd_1252_luma_weight, dnxhd_1252_chroma_weight,
|
||||
dnxhd_1237_dc_codes, dnxhd_1237_dc_bits,
|
||||
dnxhd_1252_ac_codes, dnxhd_1252_ac_bits, dnxhd_1252_ac_info,
|
||||
dnxhd_1250_run_codes, dnxhd_1250_run_bits, dnxhd_1250_run,
|
||||
{ 60, 60, 75, 120, 145 },
|
||||
{ { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } },
|
||||
{ 60, 75, 120, 145 } },
|
||||
{ 1253, 1920, 1080, 188416, 188416,
|
||||
0, 4, 8, 3,
|
||||
dnxhd_1237_luma_weight, dnxhd_1237_chroma_weight,
|
||||
dnxhd_1237_dc_codes, dnxhd_1237_dc_bits,
|
||||
dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_info,
|
||||
dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run,
|
||||
{ 36, 36, 45, 75, 90 },
|
||||
{ { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } },
|
||||
{ 36, 45, 75, 90 } },
|
||||
{ 1256, 1920, 1080, 1835008, 1835008,
|
||||
DNXHD_444, 6, 10, 4,
|
||||
dnxhd_1235_luma_weight, dnxhd_1235_luma_weight,
|
||||
dnxhd_1235_dc_codes, dnxhd_1235_dc_bits,
|
||||
dnxhd_1235_ac_codes, dnxhd_1235_ac_bits, dnxhd_1235_ac_info,
|
||||
dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1235_run,
|
||||
{ 350, 390, 440, 730, 880 },
|
||||
{ { 24000, 1001 }, { 25, 1 }, { 30000, 1001 }, { 50, 1 }, { 60000, 1001 } } },
|
||||
{ 350, 390, 440, 730, 880 } },
|
||||
{ 1258, 960, 720, 212992, 212992,
|
||||
0, 4, 8, 5,
|
||||
dnxhd_1252_luma_weight, dnxhd_1252_chroma_weight,
|
||||
@@ -1056,35 +1044,35 @@ const CIDEntry ff_dnxhd_cid_table[] = {
|
||||
dnxhd_1235_dc_codes, dnxhd_1235_dc_bits,
|
||||
dnxhd_1235_ac_codes, dnxhd_1235_ac_bits, dnxhd_1235_ac_info,
|
||||
dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1235_run,
|
||||
{ 0 }, { { 0 } }, { 57344, 255} },
|
||||
{ 0 }, { 57344, 255} },
|
||||
{ 1271, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE,
|
||||
0, 6, DNXHD_VARIABLE, 4,
|
||||
dnxhd_1241_luma_weight, dnxhd_1241_chroma_weight,
|
||||
dnxhd_1235_dc_codes, dnxhd_1235_dc_bits,
|
||||
dnxhd_1235_ac_codes, dnxhd_1235_ac_bits, dnxhd_1235_ac_info,
|
||||
dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1235_run,
|
||||
{ 0 }, { { 0 } }, { 28672, 255} },
|
||||
{ 0 }, { 28672, 255} },
|
||||
{ 1272, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE,
|
||||
0, 4, 8, 4,
|
||||
dnxhd_1238_luma_weight, dnxhd_1238_chroma_weight,
|
||||
dnxhd_1237_dc_codes, dnxhd_1237_dc_bits,
|
||||
dnxhd_1238_ac_codes, dnxhd_1238_ac_bits, dnxhd_1238_ac_info,
|
||||
dnxhd_1235_run_codes, dnxhd_1235_run_bits, dnxhd_1238_run,
|
||||
{ 0 }, { { 0 } }, { 28672, 255} },
|
||||
{ 0 }, { 28672, 255} },
|
||||
{ 1273, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE,
|
||||
0, 4, 8, 3,
|
||||
dnxhd_1237_luma_weight, dnxhd_1237_chroma_weight,
|
||||
dnxhd_1237_dc_codes, dnxhd_1237_dc_bits,
|
||||
dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_info,
|
||||
dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run,
|
||||
{ 0 }, { { 0 } }, { 18944, 255} },
|
||||
{ 0 }, { 18944, 255} },
|
||||
{ 1274, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE, DNXHD_VARIABLE,
|
||||
0, 4, 8, 3,
|
||||
dnxhd_1237_luma_weight, dnxhd_1237_chroma_weight,
|
||||
dnxhd_1237_dc_codes, dnxhd_1237_dc_bits,
|
||||
dnxhd_1237_ac_codes, dnxhd_1237_ac_bits, dnxhd_1237_ac_info,
|
||||
dnxhd_1237_run_codes, dnxhd_1237_run_bits, dnxhd_1237_run,
|
||||
{ 0 }, { { 0 } }, { 5888, 255} },
|
||||
{ 0 }, { 5888, 255} },
|
||||
};
|
||||
|
||||
int ff_dnxhd_get_cid_table(int cid)
|
||||
@@ -1112,13 +1100,6 @@ int avpriv_dnxhd_get_interlaced(int cid)
|
||||
return ff_dnxhd_cid_table[i].flags & DNXHD_INTERLACED ? 1 : 0;
|
||||
}
|
||||
|
||||
#if LIBAVCODEC_VERSION_MAJOR < 58
|
||||
uint64_t avpriv_dnxhd_parse_header_prefix(const uint8_t *buf)
|
||||
{
|
||||
return ff_dnxhd_parse_header_prefix(buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int dnxhd_find_hr_cid(AVCodecContext *avctx)
|
||||
{
|
||||
switch (avctx->profile) {
|
||||
@@ -1175,9 +1156,9 @@ void ff_dnxhd_print_profiles(AVCodecContext *avctx, int loglevel)
|
||||
if (!cid->bit_rates[j])
|
||||
break;
|
||||
|
||||
av_log(avctx, loglevel, "Frame size: %dx%d%c; bitrate: %dMbps; pixel format: %s; framerate: %d/%d\n",
|
||||
av_log(avctx, loglevel, "Frame size: %dx%d%c; bitrate: %dMbps; pixel format: %s\n",
|
||||
cid->width, cid->height, cid->flags & DNXHD_INTERLACED ? 'i' : 'p', cid->bit_rates[j],
|
||||
cid->bit_depth == 10 ? "yuv422p10" : "yuv422p", cid->frame_rates[j].num, cid->frame_rates[j].den);
|
||||
cid->flags & DNXHD_444 ? "yuv444p10, gbrp10" : cid->bit_depth == 10 ? "yuv422p10" : "yuv422p");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,6 @@ typedef struct CIDEntry {
|
||||
const uint16_t *run_codes;
|
||||
const uint8_t *run_bits, *run;
|
||||
int bit_rates[5]; ///< Helper to choose variants, rounded to nearest 5Mb/s
|
||||
AVRational frame_rates[5];
|
||||
AVRational packet_scale;
|
||||
} CIDEntry;
|
||||
|
||||
@@ -106,8 +105,5 @@ static av_always_inline int ff_dnxhd_get_hr_frame_size(int cid, int w, int h)
|
||||
|
||||
int avpriv_dnxhd_get_frame_size(int cid);
|
||||
int avpriv_dnxhd_get_interlaced(int cid);
|
||||
#if LIBAVCODEC_VERSION_MAJOR < 58
|
||||
attribute_deprecated
|
||||
uint64_t avpriv_dnxhd_parse_header_prefix(const uint8_t *buf);
|
||||
#endif
|
||||
|
||||
#endif /* AVCODEC_DNXHDDATA_H */
|
||||
|
||||
@@ -93,7 +93,9 @@ static av_cold int dnxhd_decode_init(AVCodecContext *avctx)
|
||||
|
||||
ctx->avctx = avctx;
|
||||
ctx->cid = -1;
|
||||
avctx->colorspace = AVCOL_SPC_BT709;
|
||||
if (avctx->colorspace == AVCOL_SPC_UNSPECIFIED) {
|
||||
avctx->colorspace = AVCOL_SPC_BT709;
|
||||
}
|
||||
|
||||
avctx->coded_width = FFALIGN(avctx->width, 16);
|
||||
avctx->coded_height = FFALIGN(avctx->height, 16);
|
||||
@@ -381,6 +383,10 @@ static av_always_inline int dnxhd_decode_dct_block(const DNXHDContext *ctx,
|
||||
|
||||
UPDATE_CACHE(bs, &row->gb);
|
||||
GET_VLC(len, bs, &row->gb, ctx->dc_vlc.table, DNXHD_DC_VLC_BITS, 1);
|
||||
if (len < 0) {
|
||||
ret = len;
|
||||
goto error;
|
||||
}
|
||||
if (len) {
|
||||
level = GET_CACHE(bs, &row->gb);
|
||||
LAST_SKIP_BITS(bs, &row->gb, len);
|
||||
@@ -434,7 +440,7 @@ static av_always_inline int dnxhd_decode_dct_block(const DNXHDContext *ctx,
|
||||
GET_VLC(index1, bs, &row->gb, ctx->ac_vlc.table,
|
||||
DNXHD_VLC_BITS, 2);
|
||||
}
|
||||
|
||||
error:
|
||||
CLOSE_READER(bs, &row->gb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -490,12 +490,6 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx)
|
||||
else
|
||||
ctx->data_offset = 0x280;
|
||||
|
||||
#if FF_API_QUANT_BIAS
|
||||
FF_DISABLE_DEPRECATION_WARNINGS
|
||||
if (avctx->intra_quant_bias != FF_DEFAULT_QUANT_BIAS)
|
||||
ctx->intra_quant_bias = avctx->intra_quant_bias;
|
||||
FF_ENABLE_DEPRECATION_WARNINGS
|
||||
#endif
|
||||
// XXX tune lbias/cbias
|
||||
if ((ret = dnxhd_init_qmat(ctx, ctx->intra_quant_bias, 0)) < 0)
|
||||
return ret;
|
||||
|
||||
+5
-2
@@ -239,9 +239,9 @@ static void dvb_encode_rle8(uint8_t **pq,
|
||||
x += len;
|
||||
}
|
||||
/* end of line */
|
||||
// 00000000 00000000 end of 8-bit/pixel_code_string
|
||||
*q++ = 0x00;
|
||||
// 00000000 end of 8-bit/pixel_code_string
|
||||
*q++ = 0x00;
|
||||
*q++ = 0xf0;
|
||||
bitmap += linesize;
|
||||
}
|
||||
*pq = q;
|
||||
@@ -342,6 +342,9 @@ static int encode_dvb_subtitles(DVBSubtitleContext *s,
|
||||
} else if (h->rects[region_id]->nb_colors <= 16) {
|
||||
/* 4 bpp, standard encoding */
|
||||
bpp_index = 1;
|
||||
} else if (h->rects[region_id]->nb_colors <= 256) {
|
||||
/* 8 bpp, standard encoding */
|
||||
bpp_index = 2;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
+35
-16
@@ -96,6 +96,9 @@ typedef struct DVBSubRegion {
|
||||
int clut;
|
||||
int bgcolor;
|
||||
|
||||
uint8_t computed_clut[4*256];
|
||||
int has_computed_clut;
|
||||
|
||||
uint8_t *pbuf;
|
||||
int buf_size;
|
||||
int dirty;
|
||||
@@ -647,14 +650,14 @@ static int dvbsub_read_8bit_string(AVCodecContext *avctx,
|
||||
return pixels_read;
|
||||
}
|
||||
|
||||
static void compute_default_clut(AVSubtitleRect *rect, int w, int h)
|
||||
static void compute_default_clut(uint8_t *clut, AVSubtitleRect *rect, int w, int h)
|
||||
{
|
||||
uint8_t list[256] = {0};
|
||||
uint8_t list_inv[256];
|
||||
int counttab[256] = {0};
|
||||
int count, i, x, y;
|
||||
|
||||
#define V(x,y) rect->data[0][(x) + (y)*rect->linesize[0]]
|
||||
ptrdiff_t stride = rect->linesize[0];
|
||||
#define V(x,y) rect->data[0][(x) + (y)*stride]
|
||||
for (y = 0; y<h; y++) {
|
||||
for (x = 0; x<w; x++) {
|
||||
int v = V(x,y) + 1;
|
||||
@@ -665,7 +668,7 @@ static void compute_default_clut(AVSubtitleRect *rect, int w, int h)
|
||||
counttab[v-1] += !!((v!=vl) + (v!=vr) + (v!=vt) + (v!=vb));
|
||||
}
|
||||
}
|
||||
#define L(x,y) list[ rect->data[0][(x) + (y)*rect->linesize[0]] ]
|
||||
#define L(x,y) list[d[(x) + (y)*stride]]
|
||||
|
||||
for (i = 0; i<256; i++) {
|
||||
int scoretab[256] = {0};
|
||||
@@ -673,20 +676,24 @@ static void compute_default_clut(AVSubtitleRect *rect, int w, int h)
|
||||
int bestv = 0;
|
||||
for (y = 0; y<h; y++) {
|
||||
for (x = 0; x<w; x++) {
|
||||
int v = rect->data[0][x + y*rect->linesize[0]];
|
||||
uint8_t *d = &rect->data[0][x + y*stride];
|
||||
int v = *d;
|
||||
int l_m = list[v];
|
||||
int l_l = x ? L(x-1, y) : 1;
|
||||
int l_r = x+1<w ? L(x+1, y) : 1;
|
||||
int l_t = y ? L(x, y-1) : 1;
|
||||
int l_b = y+1<h ? L(x, y+1) : 1;
|
||||
int score;
|
||||
int l_l = x ? L(-1, 0) : 1;
|
||||
int l_r = x+1<w ? L( 1, 0) : 1;
|
||||
int l_t = y ? L( 0,-1) : 1;
|
||||
int l_b = y+1<h ? L( 0, 1) : 1;
|
||||
if (l_m)
|
||||
continue;
|
||||
scoretab[v] += l_l + l_r + l_t + l_b;
|
||||
score = 1024LL*scoretab[v] / counttab[v];
|
||||
}
|
||||
}
|
||||
for (x = 0; x < 256; x++) {
|
||||
if (scoretab[x]) {
|
||||
int score = 1024LL*scoretab[x] / counttab[x];
|
||||
if (score > bestscore) {
|
||||
bestscore = score;
|
||||
bestv = v;
|
||||
bestv = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -699,7 +706,7 @@ static void compute_default_clut(AVSubtitleRect *rect, int w, int h)
|
||||
count = FFMAX(i - 1, 1);
|
||||
for (i--; i>=0; i--) {
|
||||
int v = i*255/count;
|
||||
AV_WN32(rect->data[1] + 4*list_inv[i], RGBA(v/2,v,v/2,v));
|
||||
AV_WN32(clut + 4*list_inv[i], RGBA(v/2,v,v/2,v));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -749,8 +756,13 @@ static int save_subtitle_set(AVCodecContext *avctx, AVSubtitle *sub, int *got_ou
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for(i=0; i<sub->num_rects; i++)
|
||||
for (i = 0; i < sub->num_rects; i++) {
|
||||
sub->rects[i] = av_mallocz(sizeof(*sub->rects[i]));
|
||||
if (!sub->rects[i]) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
@@ -805,8 +817,14 @@ static int save_subtitle_set(AVCodecContext *avctx, AVSubtitle *sub, int *got_ou
|
||||
|
||||
memcpy(rect->data[0], region->pbuf, region->buf_size);
|
||||
|
||||
if ((clut == &default_clut && ctx->compute_clut == -1) || ctx->compute_clut == 1)
|
||||
compute_default_clut(rect, rect->w, rect->h);
|
||||
if ((clut == &default_clut && ctx->compute_clut == -1) || ctx->compute_clut == 1) {
|
||||
if (!region->has_computed_clut) {
|
||||
compute_default_clut(region->computed_clut, rect, rect->w, rect->h);
|
||||
region->has_computed_clut = 1;
|
||||
}
|
||||
|
||||
memcpy(rect->data[1], region->computed_clut, sizeof(region->computed_clut));
|
||||
}
|
||||
|
||||
#if FF_API_AVPICTURE
|
||||
FF_DISABLE_DEPRECATION_WARNINGS
|
||||
@@ -955,6 +973,7 @@ static void dvbsub_parse_pixel_data_block(AVCodecContext *avctx, DVBSubObjectDis
|
||||
}
|
||||
}
|
||||
|
||||
region->has_computed_clut = 0;
|
||||
}
|
||||
|
||||
static int dvbsub_parse_object_segment(AVCodecContext *avctx,
|
||||
|
||||
+24
-31
@@ -29,6 +29,7 @@
|
||||
#include "libavutil/time.h"
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "decode.h"
|
||||
#include "dxva2_internal.h"
|
||||
|
||||
/* define all the GUIDs used directly here,
|
||||
@@ -576,14 +577,20 @@ static void ff_dxva2_unlock(AVCodecContext *avctx)
|
||||
#endif
|
||||
}
|
||||
|
||||
// This must work before the decoder is created.
|
||||
// This somehow needs to be exported to the user.
|
||||
static void dxva_adjust_hwframes(AVCodecContext *avctx, AVHWFramesContext *frames_ctx)
|
||||
int ff_dxva2_common_frame_params(AVCodecContext *avctx,
|
||||
AVBufferRef *hw_frames_ctx)
|
||||
{
|
||||
FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
|
||||
AVHWFramesContext *frames_ctx = (AVHWFramesContext *)hw_frames_ctx->data;
|
||||
AVHWDeviceContext *device_ctx = frames_ctx->device_ctx;
|
||||
int surface_alignment, num_surfaces;
|
||||
|
||||
frames_ctx->format = sctx->pix_fmt;
|
||||
if (device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
|
||||
frames_ctx->format = AV_PIX_FMT_DXVA2_VLD;
|
||||
} else if (device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
|
||||
frames_ctx->format = AV_PIX_FMT_D3D11;
|
||||
} else {
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
/* decoding MPEG-2 requires additional alignment on some Intel GPUs,
|
||||
but it causes issues for H.264 on certain AMD GPUs..... */
|
||||
@@ -596,8 +603,8 @@ static void dxva_adjust_hwframes(AVCodecContext *avctx, AVHWFramesContext *frame
|
||||
else
|
||||
surface_alignment = 16;
|
||||
|
||||
/* 4 base work surfaces */
|
||||
num_surfaces = 4;
|
||||
/* 1 base work surface */
|
||||
num_surfaces = 1;
|
||||
|
||||
/* add surfaces based on number of possible refs */
|
||||
if (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_HEVC)
|
||||
@@ -633,12 +640,16 @@ static void dxva_adjust_hwframes(AVCodecContext *avctx, AVHWFramesContext *frame
|
||||
frames_hwctx->BindFlags |= D3D11_BIND_DECODER;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ff_dxva2_decode_init(AVCodecContext *avctx)
|
||||
{
|
||||
FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
|
||||
AVHWFramesContext *frames_ctx = NULL;
|
||||
AVHWFramesContext *frames_ctx;
|
||||
enum AVHWDeviceType dev_type = avctx->hwaccel->pix_fmt == AV_PIX_FMT_DXVA2_VLD
|
||||
? AV_HWDEVICE_TYPE_DXVA2 : AV_HWDEVICE_TYPE_D3D11VA;
|
||||
int ret = 0;
|
||||
|
||||
// Old API.
|
||||
@@ -648,32 +659,14 @@ int ff_dxva2_decode_init(AVCodecContext *avctx)
|
||||
// (avctx->pix_fmt is not updated yet at this point)
|
||||
sctx->pix_fmt = avctx->hwaccel->pix_fmt;
|
||||
|
||||
if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Either a hw_frames_ctx or a hw_device_ctx needs to be set for hardware decoding.\n");
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
|
||||
if (avctx->hw_frames_ctx) {
|
||||
frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
|
||||
} else {
|
||||
avctx->hw_frames_ctx = av_hwframe_ctx_alloc(avctx->hw_device_ctx);
|
||||
if (!avctx->hw_frames_ctx)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
|
||||
|
||||
dxva_adjust_hwframes(avctx, frames_ctx);
|
||||
|
||||
ret = av_hwframe_ctx_init(avctx->hw_frames_ctx);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
}
|
||||
ret = ff_decode_get_hw_frames_ctx(avctx, dev_type);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
|
||||
sctx->device_ctx = frames_ctx->device_ctx;
|
||||
|
||||
if (frames_ctx->format != sctx->pix_fmt ||
|
||||
!((sctx->pix_fmt == AV_PIX_FMT_D3D11 && CONFIG_D3D11VA) ||
|
||||
(sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD && CONFIG_DXVA2))) {
|
||||
if (frames_ctx->format != sctx->pix_fmt) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Invalid pixfmt for hwaccel!\n");
|
||||
ret = AVERROR(EINVAL);
|
||||
goto fail;
|
||||
|
||||
@@ -518,7 +518,7 @@ static int dxva2_h264_end_frame(AVCodecContext *avctx)
|
||||
}
|
||||
|
||||
#if CONFIG_H264_DXVA2_HWACCEL
|
||||
AVHWAccel ff_h264_dxva2_hwaccel = {
|
||||
const AVHWAccel ff_h264_dxva2_hwaccel = {
|
||||
.name = "h264_dxva2",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_H264,
|
||||
@@ -528,13 +528,14 @@ AVHWAccel ff_h264_dxva2_hwaccel = {
|
||||
.start_frame = dxva2_h264_start_frame,
|
||||
.decode_slice = dxva2_h264_decode_slice,
|
||||
.end_frame = dxva2_h264_end_frame,
|
||||
.frame_params = ff_dxva2_common_frame_params,
|
||||
.frame_priv_data_size = sizeof(struct dxva2_picture_context),
|
||||
.priv_data_size = sizeof(FFDXVASharedContext),
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_H264_D3D11VA_HWACCEL
|
||||
AVHWAccel ff_h264_d3d11va_hwaccel = {
|
||||
const AVHWAccel ff_h264_d3d11va_hwaccel = {
|
||||
.name = "h264_d3d11va",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_H264,
|
||||
@@ -544,13 +545,14 @@ AVHWAccel ff_h264_d3d11va_hwaccel = {
|
||||
.start_frame = dxva2_h264_start_frame,
|
||||
.decode_slice = dxva2_h264_decode_slice,
|
||||
.end_frame = dxva2_h264_end_frame,
|
||||
.frame_params = ff_dxva2_common_frame_params,
|
||||
.frame_priv_data_size = sizeof(struct dxva2_picture_context),
|
||||
.priv_data_size = sizeof(FFDXVASharedContext),
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_H264_D3D11VA2_HWACCEL
|
||||
AVHWAccel ff_h264_d3d11va2_hwaccel = {
|
||||
const AVHWAccel ff_h264_d3d11va2_hwaccel = {
|
||||
.name = "h264_d3d11va2",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_H264,
|
||||
@@ -560,6 +562,7 @@ AVHWAccel ff_h264_d3d11va2_hwaccel = {
|
||||
.start_frame = dxva2_h264_start_frame,
|
||||
.decode_slice = dxva2_h264_decode_slice,
|
||||
.end_frame = dxva2_h264_end_frame,
|
||||
.frame_params = ff_dxva2_common_frame_params,
|
||||
.frame_priv_data_size = sizeof(struct dxva2_picture_context),
|
||||
.priv_data_size = sizeof(FFDXVASharedContext),
|
||||
};
|
||||
|
||||
@@ -422,7 +422,7 @@ static int dxva2_hevc_end_frame(AVCodecContext *avctx)
|
||||
}
|
||||
|
||||
#if CONFIG_HEVC_DXVA2_HWACCEL
|
||||
AVHWAccel ff_hevc_dxva2_hwaccel = {
|
||||
const AVHWAccel ff_hevc_dxva2_hwaccel = {
|
||||
.name = "hevc_dxva2",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_HEVC,
|
||||
@@ -432,13 +432,14 @@ AVHWAccel ff_hevc_dxva2_hwaccel = {
|
||||
.start_frame = dxva2_hevc_start_frame,
|
||||
.decode_slice = dxva2_hevc_decode_slice,
|
||||
.end_frame = dxva2_hevc_end_frame,
|
||||
.frame_params = ff_dxva2_common_frame_params,
|
||||
.frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context),
|
||||
.priv_data_size = sizeof(FFDXVASharedContext),
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_HEVC_D3D11VA_HWACCEL
|
||||
AVHWAccel ff_hevc_d3d11va_hwaccel = {
|
||||
const AVHWAccel ff_hevc_d3d11va_hwaccel = {
|
||||
.name = "hevc_d3d11va",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_HEVC,
|
||||
@@ -448,13 +449,14 @@ AVHWAccel ff_hevc_d3d11va_hwaccel = {
|
||||
.start_frame = dxva2_hevc_start_frame,
|
||||
.decode_slice = dxva2_hevc_decode_slice,
|
||||
.end_frame = dxva2_hevc_end_frame,
|
||||
.frame_params = ff_dxva2_common_frame_params,
|
||||
.frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context),
|
||||
.priv_data_size = sizeof(FFDXVASharedContext),
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_HEVC_D3D11VA2_HWACCEL
|
||||
AVHWAccel ff_hevc_d3d11va2_hwaccel = {
|
||||
const AVHWAccel ff_hevc_d3d11va2_hwaccel = {
|
||||
.name = "hevc_d3d11va2",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_HEVC,
|
||||
@@ -464,6 +466,7 @@ AVHWAccel ff_hevc_d3d11va2_hwaccel = {
|
||||
.start_frame = dxva2_hevc_start_frame,
|
||||
.decode_slice = dxva2_hevc_decode_slice,
|
||||
.end_frame = dxva2_hevc_end_frame,
|
||||
.frame_params = ff_dxva2_common_frame_params,
|
||||
.frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context),
|
||||
.priv_data_size = sizeof(FFDXVASharedContext),
|
||||
};
|
||||
|
||||
@@ -156,6 +156,9 @@ int ff_dxva2_decode_init(AVCodecContext *avctx);
|
||||
|
||||
int ff_dxva2_decode_uninit(AVCodecContext *avctx);
|
||||
|
||||
int ff_dxva2_common_frame_params(AVCodecContext *avctx,
|
||||
AVBufferRef *hw_frames_ctx);
|
||||
|
||||
int ff_dxva2_is_d3d11(const AVCodecContext *avctx);
|
||||
|
||||
#endif /* AVCODEC_DXVA2_INTERNAL_H */
|
||||
|
||||
@@ -317,7 +317,7 @@ static int dxva2_mpeg2_end_frame(AVCodecContext *avctx)
|
||||
}
|
||||
|
||||
#if CONFIG_MPEG2_DXVA2_HWACCEL
|
||||
AVHWAccel ff_mpeg2_dxva2_hwaccel = {
|
||||
const AVHWAccel ff_mpeg2_dxva2_hwaccel = {
|
||||
.name = "mpeg2_dxva2",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_MPEG2VIDEO,
|
||||
@@ -327,13 +327,14 @@ AVHWAccel ff_mpeg2_dxva2_hwaccel = {
|
||||
.start_frame = dxva2_mpeg2_start_frame,
|
||||
.decode_slice = dxva2_mpeg2_decode_slice,
|
||||
.end_frame = dxva2_mpeg2_end_frame,
|
||||
.frame_params = ff_dxva2_common_frame_params,
|
||||
.frame_priv_data_size = sizeof(struct dxva2_picture_context),
|
||||
.priv_data_size = sizeof(FFDXVASharedContext),
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_MPEG2_D3D11VA_HWACCEL
|
||||
AVHWAccel ff_mpeg2_d3d11va_hwaccel = {
|
||||
const AVHWAccel ff_mpeg2_d3d11va_hwaccel = {
|
||||
.name = "mpeg2_d3d11va",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_MPEG2VIDEO,
|
||||
@@ -343,13 +344,14 @@ AVHWAccel ff_mpeg2_d3d11va_hwaccel = {
|
||||
.start_frame = dxva2_mpeg2_start_frame,
|
||||
.decode_slice = dxva2_mpeg2_decode_slice,
|
||||
.end_frame = dxva2_mpeg2_end_frame,
|
||||
.frame_params = ff_dxva2_common_frame_params,
|
||||
.frame_priv_data_size = sizeof(struct dxva2_picture_context),
|
||||
.priv_data_size = sizeof(FFDXVASharedContext),
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_MPEG2_D3D11VA2_HWACCEL
|
||||
AVHWAccel ff_mpeg2_d3d11va2_hwaccel = {
|
||||
const AVHWAccel ff_mpeg2_d3d11va2_hwaccel = {
|
||||
.name = "mpeg2_d3d11va2",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_MPEG2VIDEO,
|
||||
@@ -359,6 +361,7 @@ AVHWAccel ff_mpeg2_d3d11va2_hwaccel = {
|
||||
.start_frame = dxva2_mpeg2_start_frame,
|
||||
.decode_slice = dxva2_mpeg2_decode_slice,
|
||||
.end_frame = dxva2_mpeg2_end_frame,
|
||||
.frame_params = ff_dxva2_common_frame_params,
|
||||
.frame_priv_data_size = sizeof(struct dxva2_picture_context),
|
||||
.priv_data_size = sizeof(FFDXVASharedContext),
|
||||
};
|
||||
|
||||
+11
-6
@@ -378,7 +378,7 @@ static int dxva2_vc1_end_frame(AVCodecContext *avctx)
|
||||
}
|
||||
|
||||
#if CONFIG_WMV3_DXVA2_HWACCEL
|
||||
AVHWAccel ff_wmv3_dxva2_hwaccel = {
|
||||
const AVHWAccel ff_wmv3_dxva2_hwaccel = {
|
||||
.name = "wmv3_dxva2",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_WMV3,
|
||||
@@ -388,13 +388,14 @@ AVHWAccel ff_wmv3_dxva2_hwaccel = {
|
||||
.start_frame = dxva2_vc1_start_frame,
|
||||
.decode_slice = dxva2_vc1_decode_slice,
|
||||
.end_frame = dxva2_vc1_end_frame,
|
||||
.frame_params = ff_dxva2_common_frame_params,
|
||||
.frame_priv_data_size = sizeof(struct dxva2_picture_context),
|
||||
.priv_data_size = sizeof(FFDXVASharedContext),
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_VC1_DXVA2_HWACCEL
|
||||
AVHWAccel ff_vc1_dxva2_hwaccel = {
|
||||
const AVHWAccel ff_vc1_dxva2_hwaccel = {
|
||||
.name = "vc1_dxva2",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_VC1,
|
||||
@@ -404,13 +405,14 @@ AVHWAccel ff_vc1_dxva2_hwaccel = {
|
||||
.start_frame = dxva2_vc1_start_frame,
|
||||
.decode_slice = dxva2_vc1_decode_slice,
|
||||
.end_frame = dxva2_vc1_end_frame,
|
||||
.frame_params = ff_dxva2_common_frame_params,
|
||||
.frame_priv_data_size = sizeof(struct dxva2_picture_context),
|
||||
.priv_data_size = sizeof(FFDXVASharedContext),
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_WMV3_D3D11VA_HWACCEL
|
||||
AVHWAccel ff_wmv3_d3d11va_hwaccel = {
|
||||
const AVHWAccel ff_wmv3_d3d11va_hwaccel = {
|
||||
.name = "wmv3_d3d11va",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_WMV3,
|
||||
@@ -420,13 +422,14 @@ AVHWAccel ff_wmv3_d3d11va_hwaccel = {
|
||||
.start_frame = dxva2_vc1_start_frame,
|
||||
.decode_slice = dxva2_vc1_decode_slice,
|
||||
.end_frame = dxva2_vc1_end_frame,
|
||||
.frame_params = ff_dxva2_common_frame_params,
|
||||
.frame_priv_data_size = sizeof(struct dxva2_picture_context),
|
||||
.priv_data_size = sizeof(FFDXVASharedContext),
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_WMV3_D3D11VA2_HWACCEL
|
||||
AVHWAccel ff_wmv3_d3d11va2_hwaccel = {
|
||||
const AVHWAccel ff_wmv3_d3d11va2_hwaccel = {
|
||||
.name = "wmv3_d3d11va2",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_WMV3,
|
||||
@@ -436,13 +439,14 @@ AVHWAccel ff_wmv3_d3d11va2_hwaccel = {
|
||||
.start_frame = dxva2_vc1_start_frame,
|
||||
.decode_slice = dxva2_vc1_decode_slice,
|
||||
.end_frame = dxva2_vc1_end_frame,
|
||||
.frame_params = ff_dxva2_common_frame_params,
|
||||
.frame_priv_data_size = sizeof(struct dxva2_picture_context),
|
||||
.priv_data_size = sizeof(FFDXVASharedContext),
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_VC1_D3D11VA_HWACCEL
|
||||
AVHWAccel ff_vc1_d3d11va_hwaccel = {
|
||||
const AVHWAccel ff_vc1_d3d11va_hwaccel = {
|
||||
.name = "vc1_d3d11va",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_VC1,
|
||||
@@ -452,13 +456,14 @@ AVHWAccel ff_vc1_d3d11va_hwaccel = {
|
||||
.start_frame = dxva2_vc1_start_frame,
|
||||
.decode_slice = dxva2_vc1_decode_slice,
|
||||
.end_frame = dxva2_vc1_end_frame,
|
||||
.frame_params = ff_dxva2_common_frame_params,
|
||||
.frame_priv_data_size = sizeof(struct dxva2_picture_context),
|
||||
.priv_data_size = sizeof(FFDXVASharedContext),
|
||||
};
|
||||
#endif
|
||||
|
||||
#if CONFIG_VC1_D3D11VA2_HWACCEL
|
||||
AVHWAccel ff_vc1_d3d11va2_hwaccel = {
|
||||
const AVHWAccel ff_vc1_d3d11va2_hwaccel = {
|
||||
.name = "vc1_d3d11va2",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_VC1,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user