diff --git a/patches/chromium/.patches b/patches/chromium/.patches index 26a9523cc6eaf..572b23a68f77b 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -116,3 +116,4 @@ backport_1073409.patch backport_1074340.patch backport_1016278.patch backport_1042986.patch +enable_hevc_decodec.patch diff --git a/patches/chromium/enable_hevc_decodec.patch b/patches/chromium/enable_hevc_decodec.patch new file mode 100644 index 0000000000000..e5ba9c34b9d74 --- /dev/null +++ b/patches/chromium/enable_hevc_decodec.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "alex.liang" +Date: Fri, 31 Jul 2020 13:15:13 +0800 +Subject: enable_hevc_decodec.patch + +enable ffmpeg hevc decodec + +diff --git a/media/base/supported_types.cc b/media/base/supported_types.cc +index 19266cf96d85057af9165f4e72721d09ddb16cc0..e2a1c39a4fc04ec43202c2b4da2df4d109b01323 100644 +--- a/media/base/supported_types.cc ++++ b/media/base/supported_types.cc +@@ -282,6 +282,7 @@ bool IsDefaultSupportedVideoType(const VideoType& type) { + return IsColorSpaceSupported(type.color_space) && + IsVp9ProfileSupported(type.profile); + case kCodecH264: ++ case kCodecHEVC: + case kCodecVP8: + case kCodecTheora: + return true; +@@ -289,7 +290,6 @@ bool IsDefaultSupportedVideoType(const VideoType& type) { + case kUnknownVideoCodec: + case kCodecVC1: + case kCodecMPEG2: +- case kCodecHEVC: + case kCodecDolbyVision: + return false; + +diff --git a/media/media_options.gni b/media/media_options.gni +index 1d62f7f714a7b753a2ee69cd99f95c8a8cf9ed23..5116e5292377030c14d6a30f07fa77ee15486ad4 100644 +--- a/media/media_options.gni ++++ b/media/media_options.gni +@@ -74,7 +74,8 @@ declare_args() { + + # Enable HEVC/H265 demuxing. Actual decoding must be provided by the + # platform. Enabled by default for Chromecast. +- enable_platform_hevc = proprietary_codecs && is_chromecast ++ # enable_platform_hevc = proprietary_codecs && is_chromecast ++ enable_platform_hevc = true + + # Enable Dolby Vision demuxing. Enable by default for Chromecast. Actual + # decoding must be provided by the platform. Note some Dolby Vision profiles diff --git a/patches/ffmpeg/.patches b/patches/ffmpeg/.patches index 1441ee68bacc0..4f97a0c6871e2 100644 --- a/patches/ffmpeg/.patches +++ b/patches/ffmpeg/.patches @@ -1 +1,2 @@ backport_1065731.patch +enable_hevc_decodec.patch diff --git a/patches/ffmpeg/enable_hevc_decodec.patch b/patches/ffmpeg/enable_hevc_decodec.patch new file mode 100644 index 0000000000000..fca12e78f9139 --- /dev/null +++ b/patches/ffmpeg/enable_hevc_decodec.patch @@ -0,0 +1,5159 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: "alex.liang" +Date: Fri, 31 Jul 2020 13:34:29 +0800 +Subject: enable_hevc_decodec.patch + +enable ffmpeg hevc decodec + +diff --git a/chromium/config/Chrome/linux/x64/config.asm b/chromium/config/Chrome/linux/x64/config.asm +index ba9c53c6c64059d57c5169b90fe309b018a838e7..1e08f45dc87aa6773de4f54a305ad1f40e7403d3 100644 +--- a/chromium/config/Chrome/linux/x64/config.asm ++++ b/chromium/config/Chrome/linux/x64/config.asm +@@ -800,7 +800,7 @@ + %define CONFIG_H264_QSV_DECODER 0 + %define CONFIG_H264_RKMPP_DECODER 0 + %define CONFIG_HAP_DECODER 0 +-%define CONFIG_HEVC_DECODER 0 ++%define CONFIG_HEVC_DECODER 1 + %define CONFIG_HEVC_QSV_DECODER 0 + %define CONFIG_HEVC_RKMPP_DECODER 0 + %define CONFIG_HEVC_V4L2M2M_DECODER 0 +@@ -1533,7 +1533,7 @@ + %define CONFIG_H261_PARSER 0 + %define CONFIG_H263_PARSER 0 + %define CONFIG_H264_PARSER 1 +-%define CONFIG_HEVC_PARSER 0 ++%define CONFIG_HEVC_PARSER 1 + %define CONFIG_MJPEG_PARSER 0 + %define CONFIG_MLP_PARSER 0 + %define CONFIG_MPEG4VIDEO_PARSER 0 +@@ -2135,7 +2135,7 @@ + %define CONFIG_H263_DEMUXER 0 + %define CONFIG_H264_DEMUXER 0 + %define CONFIG_HCOM_DEMUXER 0 +-%define CONFIG_HEVC_DEMUXER 0 ++%define CONFIG_HEVC_DEMUXER 1 + %define CONFIG_HLS_DEMUXER 0 + %define CONFIG_HNM_DEMUXER 0 + %define CONFIG_ICO_DEMUXER 0 +diff --git a/chromium/config/Chrome/linux/x64/config.h b/chromium/config/Chrome/linux/x64/config.h +index d33f00244083d908509ce317a10c0c7b1d21afbb..f1236a8074defb0b21bdf95305be197f586049b6 100644 +--- a/chromium/config/Chrome/linux/x64/config.h ++++ b/chromium/config/Chrome/linux/x64/config.h +@@ -815,7 +815,7 @@ + #define CONFIG_H264_QSV_DECODER 0 + #define CONFIG_H264_RKMPP_DECODER 0 + #define CONFIG_HAP_DECODER 0 +-#define CONFIG_HEVC_DECODER 0 ++#define CONFIG_HEVC_DECODER 1 + #define CONFIG_HEVC_QSV_DECODER 0 + #define CONFIG_HEVC_RKMPP_DECODER 0 + #define CONFIG_HEVC_V4L2M2M_DECODER 0 +@@ -1548,7 +1548,7 @@ + #define CONFIG_H261_PARSER 0 + #define CONFIG_H263_PARSER 0 + #define CONFIG_H264_PARSER 1 +-#define CONFIG_HEVC_PARSER 0 ++#define CONFIG_HEVC_PARSER 1 + #define CONFIG_MJPEG_PARSER 0 + #define CONFIG_MLP_PARSER 0 + #define CONFIG_MPEG4VIDEO_PARSER 0 +@@ -2150,7 +2150,7 @@ + #define CONFIG_H263_DEMUXER 0 + #define CONFIG_H264_DEMUXER 0 + #define CONFIG_HCOM_DEMUXER 0 +-#define CONFIG_HEVC_DEMUXER 0 ++#define CONFIG_HEVC_DEMUXER 1 + #define CONFIG_HLS_DEMUXER 0 + #define CONFIG_HNM_DEMUXER 0 + #define CONFIG_ICO_DEMUXER 0 +diff --git a/chromium/config/Chrome/linux/x64/libavcodec/codec_list.c b/chromium/config/Chrome/linux/x64/libavcodec/codec_list.c +index 49f757b2d864eaf552ea0a64f11ca70b3bfaa094..5ca1e9958c2e23762a1dc06ab22587362e57f4f4 100644 +--- a/chromium/config/Chrome/linux/x64/libavcodec/codec_list.c ++++ b/chromium/config/Chrome/linux/x64/libavcodec/codec_list.c +@@ -17,4 +17,5 @@ static const AVCodec * const codec_list[] = { + &ff_pcm_s32le_decoder, + &ff_pcm_u8_decoder, + &ff_libopus_decoder, ++ &ff_hevc_decoder, + NULL }; +diff --git a/chromium/config/Chrome/linux/x64/libavcodec/parser_list.c b/chromium/config/Chrome/linux/x64/libavcodec/parser_list.c +index 50acddb28e5db32656e3cb79566cfee6a65f3070..1269282a87700a67682ff670a42ad15ce0df3fd2 100644 +--- a/chromium/config/Chrome/linux/x64/libavcodec/parser_list.c ++++ b/chromium/config/Chrome/linux/x64/libavcodec/parser_list.c +@@ -8,4 +8,5 @@ static const AVCodecParser * const parser_list[] = { + &ff_vp3_parser, + &ff_vp8_parser, + &ff_vp9_parser, ++ &ff_hevc_parser, + NULL }; +diff --git a/chromium/config/Chrome/linux/x64/libavformat/demuxer_list.c b/chromium/config/Chrome/linux/x64/libavformat/demuxer_list.c +index 920b22bfa7d9d14f9b996cf57d6be346730753e4..f5c1c391967f93bb421c72be0e471056e06bf1ca 100644 +--- a/chromium/config/Chrome/linux/x64/libavformat/demuxer_list.c ++++ b/chromium/config/Chrome/linux/x64/libavformat/demuxer_list.c +@@ -6,4 +6,5 @@ static const AVInputFormat * const demuxer_list[] = { + &ff_mp3_demuxer, + &ff_ogg_demuxer, + &ff_wav_demuxer, ++ &ff_hevc_demuxer, + NULL }; +diff --git a/chromium/config/Chrome/mac/x64/config.asm b/chromium/config/Chrome/mac/x64/config.asm +index 542108911876e3cdf1036a8744c1f49b18824b34..ef0db1832147ed860b3acf27e466cfaa19481373 100644 +--- a/chromium/config/Chrome/mac/x64/config.asm ++++ b/chromium/config/Chrome/mac/x64/config.asm +@@ -800,7 +800,7 @@ + %define CONFIG_H264_QSV_DECODER 0 + %define CONFIG_H264_RKMPP_DECODER 0 + %define CONFIG_HAP_DECODER 0 +-%define CONFIG_HEVC_DECODER 0 ++%define CONFIG_HEVC_DECODER 1 + %define CONFIG_HEVC_QSV_DECODER 0 + %define CONFIG_HEVC_RKMPP_DECODER 0 + %define CONFIG_HEVC_V4L2M2M_DECODER 0 +@@ -1533,7 +1533,7 @@ + %define CONFIG_H261_PARSER 0 + %define CONFIG_H263_PARSER 0 + %define CONFIG_H264_PARSER 1 +-%define CONFIG_HEVC_PARSER 0 ++%define CONFIG_HEVC_PARSER 1 + %define CONFIG_MJPEG_PARSER 0 + %define CONFIG_MLP_PARSER 0 + %define CONFIG_MPEG4VIDEO_PARSER 0 +@@ -2135,7 +2135,7 @@ + %define CONFIG_H263_DEMUXER 0 + %define CONFIG_H264_DEMUXER 0 + %define CONFIG_HCOM_DEMUXER 0 +-%define CONFIG_HEVC_DEMUXER 0 ++%define CONFIG_HEVC_DEMUXER 1 + %define CONFIG_HLS_DEMUXER 0 + %define CONFIG_HNM_DEMUXER 0 + %define CONFIG_ICO_DEMUXER 0 +diff --git a/chromium/config/Chrome/mac/x64/config.h b/chromium/config/Chrome/mac/x64/config.h +index 0c3378281df3588d3598332a8ea8709b03ef7965..a7baedcb2d22b3dc38c97532d3b3514165d75806 100644 +--- a/chromium/config/Chrome/mac/x64/config.h ++++ b/chromium/config/Chrome/mac/x64/config.h +@@ -815,7 +815,7 @@ + #define CONFIG_H264_QSV_DECODER 0 + #define CONFIG_H264_RKMPP_DECODER 0 + #define CONFIG_HAP_DECODER 0 +-#define CONFIG_HEVC_DECODER 0 ++#define CONFIG_HEVC_DECODER 1 + #define CONFIG_HEVC_QSV_DECODER 0 + #define CONFIG_HEVC_RKMPP_DECODER 0 + #define CONFIG_HEVC_V4L2M2M_DECODER 0 +@@ -1548,7 +1548,7 @@ + #define CONFIG_H261_PARSER 0 + #define CONFIG_H263_PARSER 0 + #define CONFIG_H264_PARSER 1 +-#define CONFIG_HEVC_PARSER 0 ++#define CONFIG_HEVC_PARSER 1 + #define CONFIG_MJPEG_PARSER 0 + #define CONFIG_MLP_PARSER 0 + #define CONFIG_MPEG4VIDEO_PARSER 0 +@@ -2150,7 +2150,7 @@ + #define CONFIG_H263_DEMUXER 0 + #define CONFIG_H264_DEMUXER 0 + #define CONFIG_HCOM_DEMUXER 0 +-#define CONFIG_HEVC_DEMUXER 0 ++#define CONFIG_HEVC_DEMUXER 1 + #define CONFIG_HLS_DEMUXER 0 + #define CONFIG_HNM_DEMUXER 0 + #define CONFIG_ICO_DEMUXER 0 +diff --git a/chromium/config/Chrome/mac/x64/libavcodec/codec_list.c b/chromium/config/Chrome/mac/x64/libavcodec/codec_list.c +index 49f757b2d864eaf552ea0a64f11ca70b3bfaa094..5ca1e9958c2e23762a1dc06ab22587362e57f4f4 100644 +--- a/chromium/config/Chrome/mac/x64/libavcodec/codec_list.c ++++ b/chromium/config/Chrome/mac/x64/libavcodec/codec_list.c +@@ -17,4 +17,5 @@ static const AVCodec * const codec_list[] = { + &ff_pcm_s32le_decoder, + &ff_pcm_u8_decoder, + &ff_libopus_decoder, ++ &ff_hevc_decoder, + NULL }; +diff --git a/chromium/config/Chrome/mac/x64/libavcodec/parser_list.c b/chromium/config/Chrome/mac/x64/libavcodec/parser_list.c +index 50acddb28e5db32656e3cb79566cfee6a65f3070..1269282a87700a67682ff670a42ad15ce0df3fd2 100644 +--- a/chromium/config/Chrome/mac/x64/libavcodec/parser_list.c ++++ b/chromium/config/Chrome/mac/x64/libavcodec/parser_list.c +@@ -8,4 +8,5 @@ static const AVCodecParser * const parser_list[] = { + &ff_vp3_parser, + &ff_vp8_parser, + &ff_vp9_parser, ++ &ff_hevc_parser, + NULL }; +diff --git a/chromium/config/Chrome/mac/x64/libavformat/demuxer_list.c b/chromium/config/Chrome/mac/x64/libavformat/demuxer_list.c +index 920b22bfa7d9d14f9b996cf57d6be346730753e4..f5c1c391967f93bb421c72be0e471056e06bf1ca 100644 +--- a/chromium/config/Chrome/mac/x64/libavformat/demuxer_list.c ++++ b/chromium/config/Chrome/mac/x64/libavformat/demuxer_list.c +@@ -6,4 +6,5 @@ static const AVInputFormat * const demuxer_list[] = { + &ff_mp3_demuxer, + &ff_ogg_demuxer, + &ff_wav_demuxer, ++ &ff_hevc_demuxer, + NULL }; +diff --git a/chromium/config/Chrome/win/ia32/config.asm b/chromium/config/Chrome/win/ia32/config.asm +index a721d93cb4e321d4f8c44e6656542eb801015285..0904c145eb712bc822fb974575e7ccaa35ff6610 100644 +--- a/chromium/config/Chrome/win/ia32/config.asm ++++ b/chromium/config/Chrome/win/ia32/config.asm +@@ -800,7 +800,7 @@ + %define CONFIG_H264_QSV_DECODER 0 + %define CONFIG_H264_RKMPP_DECODER 0 + %define CONFIG_HAP_DECODER 0 +-%define CONFIG_HEVC_DECODER 0 ++%define CONFIG_HEVC_DECODER 1 + %define CONFIG_HEVC_QSV_DECODER 0 + %define CONFIG_HEVC_RKMPP_DECODER 0 + %define CONFIG_HEVC_V4L2M2M_DECODER 0 +@@ -1533,7 +1533,7 @@ + %define CONFIG_H261_PARSER 0 + %define CONFIG_H263_PARSER 0 + %define CONFIG_H264_PARSER 1 +-%define CONFIG_HEVC_PARSER 0 ++%define CONFIG_HEVC_PARSER 1 + %define CONFIG_MJPEG_PARSER 0 + %define CONFIG_MLP_PARSER 0 + %define CONFIG_MPEG4VIDEO_PARSER 0 +@@ -2135,7 +2135,7 @@ + %define CONFIG_H263_DEMUXER 0 + %define CONFIG_H264_DEMUXER 0 + %define CONFIG_HCOM_DEMUXER 0 +-%define CONFIG_HEVC_DEMUXER 0 ++%define CONFIG_HEVC_DEMUXER 1 + %define CONFIG_HLS_DEMUXER 0 + %define CONFIG_HNM_DEMUXER 0 + %define CONFIG_ICO_DEMUXER 0 +diff --git a/chromium/config/Chrome/win/ia32/config.h b/chromium/config/Chrome/win/ia32/config.h +index 77da4d1abacaaeced2528aab9779924fcbd0a96b..973456b955731556b715f85777258682a3cc8b61 100644 +--- a/chromium/config/Chrome/win/ia32/config.h ++++ b/chromium/config/Chrome/win/ia32/config.h +@@ -815,7 +815,7 @@ + #define CONFIG_H264_QSV_DECODER 0 + #define CONFIG_H264_RKMPP_DECODER 0 + #define CONFIG_HAP_DECODER 0 +-#define CONFIG_HEVC_DECODER 0 ++#define CONFIG_HEVC_DECODER 1 + #define CONFIG_HEVC_QSV_DECODER 0 + #define CONFIG_HEVC_RKMPP_DECODER 0 + #define CONFIG_HEVC_V4L2M2M_DECODER 0 +@@ -1548,7 +1548,7 @@ + #define CONFIG_H261_PARSER 0 + #define CONFIG_H263_PARSER 0 + #define CONFIG_H264_PARSER 1 +-#define CONFIG_HEVC_PARSER 0 ++#define CONFIG_HEVC_PARSER 1 + #define CONFIG_MJPEG_PARSER 0 + #define CONFIG_MLP_PARSER 0 + #define CONFIG_MPEG4VIDEO_PARSER 0 +@@ -2150,7 +2150,7 @@ + #define CONFIG_H263_DEMUXER 0 + #define CONFIG_H264_DEMUXER 0 + #define CONFIG_HCOM_DEMUXER 0 +-#define CONFIG_HEVC_DEMUXER 0 ++#define CONFIG_HEVC_DEMUXER 1 + #define CONFIG_HLS_DEMUXER 0 + #define CONFIG_HNM_DEMUXER 0 + #define CONFIG_ICO_DEMUXER 0 +diff --git a/chromium/config/Chrome/win/ia32/libavcodec/codec_list.c b/chromium/config/Chrome/win/ia32/libavcodec/codec_list.c +index 49f757b2d864eaf552ea0a64f11ca70b3bfaa094..5ca1e9958c2e23762a1dc06ab22587362e57f4f4 100644 +--- a/chromium/config/Chrome/win/ia32/libavcodec/codec_list.c ++++ b/chromium/config/Chrome/win/ia32/libavcodec/codec_list.c +@@ -17,4 +17,5 @@ static const AVCodec * const codec_list[] = { + &ff_pcm_s32le_decoder, + &ff_pcm_u8_decoder, + &ff_libopus_decoder, ++ &ff_hevc_decoder, + NULL }; +diff --git a/chromium/config/Chrome/win/ia32/libavcodec/parser_list.c b/chromium/config/Chrome/win/ia32/libavcodec/parser_list.c +index 50acddb28e5db32656e3cb79566cfee6a65f3070..1269282a87700a67682ff670a42ad15ce0df3fd2 100644 +--- a/chromium/config/Chrome/win/ia32/libavcodec/parser_list.c ++++ b/chromium/config/Chrome/win/ia32/libavcodec/parser_list.c +@@ -8,4 +8,5 @@ static const AVCodecParser * const parser_list[] = { + &ff_vp3_parser, + &ff_vp8_parser, + &ff_vp9_parser, ++ &ff_hevc_parser, + NULL }; +diff --git a/chromium/config/Chrome/win/ia32/libavformat/demuxer_list.c b/chromium/config/Chrome/win/ia32/libavformat/demuxer_list.c +index 920b22bfa7d9d14f9b996cf57d6be346730753e4..f5c1c391967f93bb421c72be0e471056e06bf1ca 100644 +--- a/chromium/config/Chrome/win/ia32/libavformat/demuxer_list.c ++++ b/chromium/config/Chrome/win/ia32/libavformat/demuxer_list.c +@@ -6,4 +6,5 @@ static const AVInputFormat * const demuxer_list[] = { + &ff_mp3_demuxer, + &ff_ogg_demuxer, + &ff_wav_demuxer, ++ &ff_hevc_demuxer, + NULL }; +diff --git a/chromium/config/Chrome/win/x64/config.asm b/chromium/config/Chrome/win/x64/config.asm +index f63c0f3c6ca4d3102c17c2a76de1e23c9e7df633..84a707eb5b8b3cced7c8777c2d2a20eaa1d7d982 100644 +--- a/chromium/config/Chrome/win/x64/config.asm ++++ b/chromium/config/Chrome/win/x64/config.asm +@@ -800,7 +800,7 @@ + %define CONFIG_H264_QSV_DECODER 0 + %define CONFIG_H264_RKMPP_DECODER 0 + %define CONFIG_HAP_DECODER 0 +-%define CONFIG_HEVC_DECODER 0 ++%define CONFIG_HEVC_DECODER 1 + %define CONFIG_HEVC_QSV_DECODER 0 + %define CONFIG_HEVC_RKMPP_DECODER 0 + %define CONFIG_HEVC_V4L2M2M_DECODER 0 +@@ -1533,7 +1533,7 @@ + %define CONFIG_H261_PARSER 0 + %define CONFIG_H263_PARSER 0 + %define CONFIG_H264_PARSER 1 +-%define CONFIG_HEVC_PARSER 0 ++%define CONFIG_HEVC_PARSER 1 + %define CONFIG_MJPEG_PARSER 0 + %define CONFIG_MLP_PARSER 0 + %define CONFIG_MPEG4VIDEO_PARSER 0 +@@ -2135,7 +2135,7 @@ + %define CONFIG_H263_DEMUXER 0 + %define CONFIG_H264_DEMUXER 0 + %define CONFIG_HCOM_DEMUXER 0 +-%define CONFIG_HEVC_DEMUXER 0 ++%define CONFIG_HEVC_DEMUXER 1 + %define CONFIG_HLS_DEMUXER 0 + %define CONFIG_HNM_DEMUXER 0 + %define CONFIG_ICO_DEMUXER 0 +diff --git a/chromium/config/Chrome/win/x64/config.h b/chromium/config/Chrome/win/x64/config.h +index b8dd95d498c549e10ebe5c6e0a2ea6b08c5b723d..fdaee4ed1b39e7958887dcbf960fb7c672d0e5c1 100644 +--- a/chromium/config/Chrome/win/x64/config.h ++++ b/chromium/config/Chrome/win/x64/config.h +@@ -815,7 +815,7 @@ + #define CONFIG_H264_QSV_DECODER 0 + #define CONFIG_H264_RKMPP_DECODER 0 + #define CONFIG_HAP_DECODER 0 +-#define CONFIG_HEVC_DECODER 0 ++#define CONFIG_HEVC_DECODER 1 + #define CONFIG_HEVC_QSV_DECODER 0 + #define CONFIG_HEVC_RKMPP_DECODER 0 + #define CONFIG_HEVC_V4L2M2M_DECODER 0 +@@ -1548,7 +1548,7 @@ + #define CONFIG_H261_PARSER 0 + #define CONFIG_H263_PARSER 0 + #define CONFIG_H264_PARSER 1 +-#define CONFIG_HEVC_PARSER 0 ++#define CONFIG_HEVC_PARSER 1 + #define CONFIG_MJPEG_PARSER 0 + #define CONFIG_MLP_PARSER 0 + #define CONFIG_MPEG4VIDEO_PARSER 0 +@@ -2150,7 +2150,7 @@ + #define CONFIG_H263_DEMUXER 0 + #define CONFIG_H264_DEMUXER 0 + #define CONFIG_HCOM_DEMUXER 0 +-#define CONFIG_HEVC_DEMUXER 0 ++#define CONFIG_HEVC_DEMUXER 1 + #define CONFIG_HLS_DEMUXER 0 + #define CONFIG_HNM_DEMUXER 0 + #define CONFIG_ICO_DEMUXER 0 +diff --git a/chromium/config/Chrome/win/x64/libavcodec/codec_list.c b/chromium/config/Chrome/win/x64/libavcodec/codec_list.c +index 49f757b2d864eaf552ea0a64f11ca70b3bfaa094..5ca1e9958c2e23762a1dc06ab22587362e57f4f4 100644 +--- a/chromium/config/Chrome/win/x64/libavcodec/codec_list.c ++++ b/chromium/config/Chrome/win/x64/libavcodec/codec_list.c +@@ -17,4 +17,5 @@ static const AVCodec * const codec_list[] = { + &ff_pcm_s32le_decoder, + &ff_pcm_u8_decoder, + &ff_libopus_decoder, ++ &ff_hevc_decoder, + NULL }; +diff --git a/chromium/config/Chrome/win/x64/libavcodec/parser_list.c b/chromium/config/Chrome/win/x64/libavcodec/parser_list.c +index 50acddb28e5db32656e3cb79566cfee6a65f3070..1269282a87700a67682ff670a42ad15ce0df3fd2 100644 +--- a/chromium/config/Chrome/win/x64/libavcodec/parser_list.c ++++ b/chromium/config/Chrome/win/x64/libavcodec/parser_list.c +@@ -8,4 +8,5 @@ static const AVCodecParser * const parser_list[] = { + &ff_vp3_parser, + &ff_vp8_parser, + &ff_vp9_parser, ++ &ff_hevc_parser, + NULL }; +diff --git a/chromium/config/Chrome/win/x64/libavformat/demuxer_list.c b/chromium/config/Chrome/win/x64/libavformat/demuxer_list.c +index 920b22bfa7d9d14f9b996cf57d6be346730753e4..f5c1c391967f93bb421c72be0e471056e06bf1ca 100644 +--- a/chromium/config/Chrome/win/x64/libavformat/demuxer_list.c ++++ b/chromium/config/Chrome/win/x64/libavformat/demuxer_list.c +@@ -6,4 +6,5 @@ static const AVInputFormat * const demuxer_list[] = { + &ff_mp3_demuxer, + &ff_ogg_demuxer, + &ff_wav_demuxer, ++ &ff_hevc_demuxer, + NULL }; +diff --git a/ffmpeg_generated.gni b/ffmpeg_generated.gni +index 95ea9081537c68bae03675e454387a3a933bc32d..23e013ba62ebe8d9b59db2640b40482cbfde7be4 100644 +--- a/ffmpeg_generated.gni ++++ b/ffmpeg_generated.gni +@@ -206,6 +206,35 @@ if ((is_mac) || (is_win) || (use_linux_config)) { + "libavcodec/vp8.c", + "libavcodec/vp8_parser.c", + ] ++ ffmpeg_c_sources += [ ++ "libavcodec/bswapdsp.c", ++ "libavcodec/autorename_libavcodec_hevcdec.c", ++ "libavcodec/hevc_cabac.c", ++ "libavcodec/hevc_data.c", ++ "libavcodec/hevc_filter.c", ++ "libavcodec/hevc_mvs.c", ++ "libavcodec/hevc_parse.c", ++ "libavcodec/hevc_parser.c", ++ "libavcodec/hevc_ps.c", ++ "libavcodec/hevc_refs.c", ++ "libavcodec/hevc_sei.c", ++ "libavcodec/hevcdsp.c", ++ "libavcodec/hevcpred.c", ++ "libavcodec/x86/bswapdsp_init.c", ++ "libavcodec/x86/hevcdsp_init.c", ++ "libavformat/avc.c", ++ "libavformat/autorename_libavformat_hevc.c", ++ "libavformat/hevcdec.c", ++ ] ++ ffmpeg_asm_sources += [ ++ "libavcodec/x86/bswapdsp.asm", ++ "libavcodec/x86/hevc_deblock.asm", ++ "libavcodec/x86/hevc_idct.asm", ++ "libavcodec/x86/hevc_mc.asm", ++ "libavcodec/x86/hevc_add_res.asm", ++ "libavcodec/x86/hevc_sao.asm", ++ "libavcodec/x86/hevc_sao_10bit.asm", ++ ] + } + + if ((current_cpu == "x64" && ffmpeg_branding == "Chrome") || (is_android && current_cpu == "arm" && arm_use_neon && ffmpeg_branding == "Chrome") || (is_android && current_cpu == "arm64" && ffmpeg_branding == "Chrome") || (is_android && current_cpu == "x86" && ffmpeg_branding == "Chrome") || (is_win && ffmpeg_branding == "Chrome") || (use_linux_config && ffmpeg_branding == "Chrome") || (use_linux_config && ffmpeg_branding == "ChromeOS")) { +diff --git a/libavcodec/autorename_libavcodec_hevcdec.c b/libavcodec/autorename_libavcodec_hevcdec.c +new file mode 100644 +index 0000000000000000000000000000000000000000..c74881e814be2a7ddb3db3e16b6cd4955b22e19c +--- /dev/null ++++ b/libavcodec/autorename_libavcodec_hevcdec.c +@@ -0,0 +1,3605 @@ ++/* ++ * HEVC video Decoder ++ * ++ * Copyright (C) 2012 - 2013 Guillaume Martres ++ * Copyright (C) 2012 - 2013 Mickael Raulet ++ * Copyright (C) 2012 - 2013 Gildas Cocherel ++ * Copyright (C) 2012 - 2013 Wassim Hamidouche ++ * ++ * 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/attributes.h" ++#include "libavutil/common.h" ++#include "libavutil/display.h" ++#include "libavutil/internal.h" ++#include "libavutil/mastering_display_metadata.h" ++#include "libavutil/md5.h" ++#include "libavutil/opt.h" ++#include "libavutil/pixdesc.h" ++#include "libavutil/stereo3d.h" ++ ++#include "bswapdsp.h" ++#include "bytestream.h" ++#include "cabac_functions.h" ++#include "golomb.h" ++#include "hevc.h" ++#include "hevc_data.h" ++#include "hevc_parse.h" ++#include "hevcdec.h" ++#include "hwaccel.h" ++#include "profiles.h" ++ ++const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12] = 4, [16] = 5, [24] = 6, [32] = 7, [48] = 8, [64] = 9 }; ++ ++/** ++ * NOTE: Each function hls_foo correspond to the function foo in the ++ * specification (HLS stands for High Level Syntax). ++ */ ++ ++/** ++ * Section 5.7 ++ */ ++ ++/* free everything allocated by pic_arrays_init() */ ++static void pic_arrays_free(HEVCContext *s) ++{ ++ av_freep(&s->sao); ++ av_freep(&s->deblock); ++ ++ av_freep(&s->skip_flag); ++ av_freep(&s->tab_ct_depth); ++ ++ av_freep(&s->tab_ipm); ++ av_freep(&s->cbf_luma); ++ av_freep(&s->is_pcm); ++ ++ av_freep(&s->qp_y_tab); ++ av_freep(&s->tab_slice_address); ++ av_freep(&s->filter_slice_edges); ++ ++ av_freep(&s->horizontal_bs); ++ av_freep(&s->vertical_bs); ++ ++ av_freep(&s->sh.entry_point_offset); ++ av_freep(&s->sh.size); ++ av_freep(&s->sh.offset); ++ ++ av_buffer_pool_uninit(&s->tab_mvf_pool); ++ av_buffer_pool_uninit(&s->rpl_tab_pool); ++} ++ ++/* allocate arrays that depend on frame dimensions */ ++static int pic_arrays_init(HEVCContext *s, const HEVCSPS *sps) ++{ ++ int log2_min_cb_size = sps->log2_min_cb_size; ++ int width = sps->width; ++ int height = sps->height; ++ int pic_size_in_ctb = ((width >> log2_min_cb_size) + 1) * ++ ((height >> log2_min_cb_size) + 1); ++ int ctb_count = sps->ctb_width * sps->ctb_height; ++ int min_pu_size = sps->min_pu_width * sps->min_pu_height; ++ ++ s->bs_width = (width >> 2) + 1; ++ s->bs_height = (height >> 2) + 1; ++ ++ s->sao = av_mallocz_array(ctb_count, sizeof(*s->sao)); ++ s->deblock = av_mallocz_array(ctb_count, sizeof(*s->deblock)); ++ if (!s->sao || !s->deblock) ++ goto fail; ++ ++ s->skip_flag = av_malloc_array(sps->min_cb_height, sps->min_cb_width); ++ s->tab_ct_depth = av_malloc_array(sps->min_cb_height, sps->min_cb_width); ++ if (!s->skip_flag || !s->tab_ct_depth) ++ goto fail; ++ ++ s->cbf_luma = av_malloc_array(sps->min_tb_width, sps->min_tb_height); ++ s->tab_ipm = av_mallocz(min_pu_size); ++ s->is_pcm = av_malloc_array(sps->min_pu_width + 1, sps->min_pu_height + 1); ++ if (!s->tab_ipm || !s->cbf_luma || !s->is_pcm) ++ goto fail; ++ ++ s->filter_slice_edges = av_mallocz(ctb_count); ++ s->tab_slice_address = av_malloc_array(pic_size_in_ctb, ++ sizeof(*s->tab_slice_address)); ++ s->qp_y_tab = av_malloc_array(pic_size_in_ctb, ++ sizeof(*s->qp_y_tab)); ++ if (!s->qp_y_tab || !s->filter_slice_edges || !s->tab_slice_address) ++ goto fail; ++ ++ s->horizontal_bs = av_mallocz_array(s->bs_width, s->bs_height); ++ s->vertical_bs = av_mallocz_array(s->bs_width, s->bs_height); ++ if (!s->horizontal_bs || !s->vertical_bs) ++ goto fail; ++ ++ s->tab_mvf_pool = av_buffer_pool_init(min_pu_size * sizeof(MvField), ++ av_buffer_allocz); ++ s->rpl_tab_pool = av_buffer_pool_init(ctb_count * sizeof(RefPicListTab), ++ av_buffer_allocz); ++ if (!s->tab_mvf_pool || !s->rpl_tab_pool) ++ goto fail; ++ ++ return 0; ++ ++fail: ++ pic_arrays_free(s); ++ return AVERROR(ENOMEM); ++} ++ ++static int pred_weight_table(HEVCContext *s, GetBitContext *gb) ++{ ++ int i = 0; ++ int j = 0; ++ uint8_t luma_weight_l0_flag[16]; ++ uint8_t chroma_weight_l0_flag[16]; ++ uint8_t luma_weight_l1_flag[16]; ++ uint8_t chroma_weight_l1_flag[16]; ++ int luma_log2_weight_denom; ++ ++ luma_log2_weight_denom = get_ue_golomb_long(gb); ++ if (luma_log2_weight_denom < 0 || luma_log2_weight_denom > 7) { ++ av_log(s->avctx, AV_LOG_ERROR, "luma_log2_weight_denom %d is invalid\n", luma_log2_weight_denom); ++ return AVERROR_INVALIDDATA; ++ } ++ s->sh.luma_log2_weight_denom = av_clip_uintp2(luma_log2_weight_denom, 3); ++ if (s->ps.sps->chroma_format_idc != 0) { ++ int64_t chroma_log2_weight_denom = luma_log2_weight_denom + (int64_t)get_se_golomb(gb); ++ if (chroma_log2_weight_denom < 0 || chroma_log2_weight_denom > 7) { ++ av_log(s->avctx, AV_LOG_ERROR, "chroma_log2_weight_denom %"PRId64" is invalid\n", chroma_log2_weight_denom); ++ return AVERROR_INVALIDDATA; ++ } ++ s->sh.chroma_log2_weight_denom = chroma_log2_weight_denom; ++ } ++ ++ for (i = 0; i < s->sh.nb_refs[L0]; i++) { ++ luma_weight_l0_flag[i] = get_bits1(gb); ++ if (!luma_weight_l0_flag[i]) { ++ s->sh.luma_weight_l0[i] = 1 << s->sh.luma_log2_weight_denom; ++ s->sh.luma_offset_l0[i] = 0; ++ } ++ } ++ if (s->ps.sps->chroma_format_idc != 0) { ++ for (i = 0; i < s->sh.nb_refs[L0]; i++) ++ chroma_weight_l0_flag[i] = get_bits1(gb); ++ } else { ++ for (i = 0; i < s->sh.nb_refs[L0]; i++) ++ chroma_weight_l0_flag[i] = 0; ++ } ++ for (i = 0; i < s->sh.nb_refs[L0]; i++) { ++ if (luma_weight_l0_flag[i]) { ++ int delta_luma_weight_l0 = get_se_golomb(gb); ++ if ((int8_t)delta_luma_weight_l0 != delta_luma_weight_l0) ++ return AVERROR_INVALIDDATA; ++ s->sh.luma_weight_l0[i] = (1 << s->sh.luma_log2_weight_denom) + delta_luma_weight_l0; ++ s->sh.luma_offset_l0[i] = get_se_golomb(gb); ++ } ++ if (chroma_weight_l0_flag[i]) { ++ for (j = 0; j < 2; j++) { ++ int delta_chroma_weight_l0 = get_se_golomb(gb); ++ int delta_chroma_offset_l0 = get_se_golomb(gb); ++ ++ if ( (int8_t)delta_chroma_weight_l0 != delta_chroma_weight_l0 ++ || delta_chroma_offset_l0 < -(1<<17) || delta_chroma_offset_l0 > (1<<17)) { ++ return AVERROR_INVALIDDATA; ++ } ++ ++ s->sh.chroma_weight_l0[i][j] = (1 << s->sh.chroma_log2_weight_denom) + delta_chroma_weight_l0; ++ s->sh.chroma_offset_l0[i][j] = av_clip((delta_chroma_offset_l0 - ((128 * s->sh.chroma_weight_l0[i][j]) ++ >> s->sh.chroma_log2_weight_denom) + 128), -128, 127); ++ } ++ } else { ++ s->sh.chroma_weight_l0[i][0] = 1 << s->sh.chroma_log2_weight_denom; ++ s->sh.chroma_offset_l0[i][0] = 0; ++ s->sh.chroma_weight_l0[i][1] = 1 << s->sh.chroma_log2_weight_denom; ++ s->sh.chroma_offset_l0[i][1] = 0; ++ } ++ } ++ if (s->sh.slice_type == HEVC_SLICE_B) { ++ for (i = 0; i < s->sh.nb_refs[L1]; i++) { ++ luma_weight_l1_flag[i] = get_bits1(gb); ++ if (!luma_weight_l1_flag[i]) { ++ s->sh.luma_weight_l1[i] = 1 << s->sh.luma_log2_weight_denom; ++ s->sh.luma_offset_l1[i] = 0; ++ } ++ } ++ if (s->ps.sps->chroma_format_idc != 0) { ++ for (i = 0; i < s->sh.nb_refs[L1]; i++) ++ chroma_weight_l1_flag[i] = get_bits1(gb); ++ } else { ++ for (i = 0; i < s->sh.nb_refs[L1]; i++) ++ chroma_weight_l1_flag[i] = 0; ++ } ++ for (i = 0; i < s->sh.nb_refs[L1]; i++) { ++ if (luma_weight_l1_flag[i]) { ++ int delta_luma_weight_l1 = get_se_golomb(gb); ++ if ((int8_t)delta_luma_weight_l1 != delta_luma_weight_l1) ++ return AVERROR_INVALIDDATA; ++ s->sh.luma_weight_l1[i] = (1 << s->sh.luma_log2_weight_denom) + delta_luma_weight_l1; ++ s->sh.luma_offset_l1[i] = get_se_golomb(gb); ++ } ++ if (chroma_weight_l1_flag[i]) { ++ for (j = 0; j < 2; j++) { ++ int delta_chroma_weight_l1 = get_se_golomb(gb); ++ int delta_chroma_offset_l1 = get_se_golomb(gb); ++ ++ if ( (int8_t)delta_chroma_weight_l1 != delta_chroma_weight_l1 ++ || delta_chroma_offset_l1 < -(1<<17) || delta_chroma_offset_l1 > (1<<17)) { ++ return AVERROR_INVALIDDATA; ++ } ++ ++ s->sh.chroma_weight_l1[i][j] = (1 << s->sh.chroma_log2_weight_denom) + delta_chroma_weight_l1; ++ s->sh.chroma_offset_l1[i][j] = av_clip((delta_chroma_offset_l1 - ((128 * s->sh.chroma_weight_l1[i][j]) ++ >> s->sh.chroma_log2_weight_denom) + 128), -128, 127); ++ } ++ } else { ++ s->sh.chroma_weight_l1[i][0] = 1 << s->sh.chroma_log2_weight_denom; ++ s->sh.chroma_offset_l1[i][0] = 0; ++ s->sh.chroma_weight_l1[i][1] = 1 << s->sh.chroma_log2_weight_denom; ++ s->sh.chroma_offset_l1[i][1] = 0; ++ } ++ } ++ } ++ return 0; ++} ++ ++static int decode_lt_rps(HEVCContext *s, LongTermRPS *rps, GetBitContext *gb) ++{ ++ const HEVCSPS *sps = s->ps.sps; ++ int max_poc_lsb = 1 << sps->log2_max_poc_lsb; ++ int prev_delta_msb = 0; ++ unsigned int nb_sps = 0, nb_sh; ++ int i; ++ ++ rps->nb_refs = 0; ++ if (!sps->long_term_ref_pics_present_flag) ++ return 0; ++ ++ if (sps->num_long_term_ref_pics_sps > 0) ++ nb_sps = get_ue_golomb_long(gb); ++ nb_sh = get_ue_golomb_long(gb); ++ ++ if (nb_sps > sps->num_long_term_ref_pics_sps) ++ return AVERROR_INVALIDDATA; ++ if (nb_sh + (uint64_t)nb_sps > FF_ARRAY_ELEMS(rps->poc)) ++ return AVERROR_INVALIDDATA; ++ ++ rps->nb_refs = nb_sh + nb_sps; ++ ++ for (i = 0; i < rps->nb_refs; i++) { ++ uint8_t delta_poc_msb_present; ++ ++ if (i < nb_sps) { ++ uint8_t lt_idx_sps = 0; ++ ++ if (sps->num_long_term_ref_pics_sps > 1) ++ lt_idx_sps = get_bits(gb, av_ceil_log2(sps->num_long_term_ref_pics_sps)); ++ ++ rps->poc[i] = sps->lt_ref_pic_poc_lsb_sps[lt_idx_sps]; ++ rps->used[i] = sps->used_by_curr_pic_lt_sps_flag[lt_idx_sps]; ++ } else { ++ rps->poc[i] = get_bits(gb, sps->log2_max_poc_lsb); ++ rps->used[i] = get_bits1(gb); ++ } ++ ++ delta_poc_msb_present = get_bits1(gb); ++ if (delta_poc_msb_present) { ++ int64_t delta = get_ue_golomb_long(gb); ++ int64_t poc; ++ ++ if (i && i != nb_sps) ++ delta += prev_delta_msb; ++ ++ poc = rps->poc[i] + s->poc - delta * max_poc_lsb - s->sh.pic_order_cnt_lsb; ++ if (poc != (int32_t)poc) ++ return AVERROR_INVALIDDATA; ++ rps->poc[i] = poc; ++ prev_delta_msb = delta; ++ } ++ } ++ ++ return 0; ++} ++ ++static void export_stream_params(HEVCContext *s, const HEVCSPS *sps) ++{ ++ AVCodecContext *avctx = s->avctx; ++ const HEVCParamSets *ps = &s->ps; ++ const HEVCVPS *vps = (const HEVCVPS*)ps->vps_list[sps->vps_id]->data; ++ const HEVCWindow *ow = &sps->output_window; ++ unsigned int num = 0, den = 0; ++ ++ avctx->pix_fmt = sps->pix_fmt; ++ avctx->coded_width = sps->width; ++ avctx->coded_height = sps->height; ++ avctx->width = sps->width - ow->left_offset - ow->right_offset; ++ avctx->height = sps->height - ow->top_offset - ow->bottom_offset; ++ avctx->has_b_frames = sps->temporal_layer[sps->max_sub_layers - 1].num_reorder_pics; ++ avctx->profile = sps->ptl.general_ptl.profile_idc; ++ avctx->level = sps->ptl.general_ptl.level_idc; ++ ++ ff_set_sar(avctx, sps->vui.sar); ++ ++ if (sps->vui.video_signal_type_present_flag) ++ avctx->color_range = sps->vui.video_full_range_flag ? AVCOL_RANGE_JPEG ++ : AVCOL_RANGE_MPEG; ++ else ++ avctx->color_range = AVCOL_RANGE_MPEG; ++ ++ if (sps->vui.colour_description_present_flag) { ++ avctx->color_primaries = sps->vui.colour_primaries; ++ avctx->color_trc = sps->vui.transfer_characteristic; ++ avctx->colorspace = sps->vui.matrix_coeffs; ++ } else { ++ avctx->color_primaries = AVCOL_PRI_UNSPECIFIED; ++ avctx->color_trc = AVCOL_TRC_UNSPECIFIED; ++ avctx->colorspace = AVCOL_SPC_UNSPECIFIED; ++ } ++ ++ if (vps->vps_timing_info_present_flag) { ++ num = vps->vps_num_units_in_tick; ++ den = vps->vps_time_scale; ++ } else if (sps->vui.vui_timing_info_present_flag) { ++ num = sps->vui.vui_num_units_in_tick; ++ den = sps->vui.vui_time_scale; ++ } ++ ++ if (num != 0 && den != 0) ++ av_reduce(&avctx->framerate.den, &avctx->framerate.num, ++ num, den, 1 << 30); ++ ++ if (s->sei.alternative_transfer.present && ++ av_color_transfer_name(s->sei.alternative_transfer.preferred_transfer_characteristics) && ++ s->sei.alternative_transfer.preferred_transfer_characteristics != AVCOL_TRC_UNSPECIFIED) { ++ avctx->color_trc = s->sei.alternative_transfer.preferred_transfer_characteristics; ++ } ++} ++ ++static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) ++{ ++#define HWACCEL_MAX (CONFIG_HEVC_DXVA2_HWACCEL + \ ++ CONFIG_HEVC_D3D11VA_HWACCEL * 2 + \ ++ CONFIG_HEVC_NVDEC_HWACCEL + \ ++ CONFIG_HEVC_VAAPI_HWACCEL + \ ++ CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + \ ++ CONFIG_HEVC_VDPAU_HWACCEL) ++ enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts; ++ ++ switch (sps->pix_fmt) { ++ case AV_PIX_FMT_YUV420P: ++ case AV_PIX_FMT_YUVJ420P: ++#if CONFIG_HEVC_DXVA2_HWACCEL ++ *fmt++ = AV_PIX_FMT_DXVA2_VLD; ++#endif ++#if CONFIG_HEVC_D3D11VA_HWACCEL ++ *fmt++ = AV_PIX_FMT_D3D11VA_VLD; ++ *fmt++ = AV_PIX_FMT_D3D11; ++#endif ++#if CONFIG_HEVC_VAAPI_HWACCEL ++ *fmt++ = AV_PIX_FMT_VAAPI; ++#endif ++#if CONFIG_HEVC_VDPAU_HWACCEL ++ *fmt++ = AV_PIX_FMT_VDPAU; ++#endif ++#if CONFIG_HEVC_NVDEC_HWACCEL ++ *fmt++ = AV_PIX_FMT_CUDA; ++#endif ++#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL ++ *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; ++#endif ++ break; ++ case AV_PIX_FMT_YUV420P10: ++#if CONFIG_HEVC_DXVA2_HWACCEL ++ *fmt++ = AV_PIX_FMT_DXVA2_VLD; ++#endif ++#if CONFIG_HEVC_D3D11VA_HWACCEL ++ *fmt++ = AV_PIX_FMT_D3D11VA_VLD; ++ *fmt++ = AV_PIX_FMT_D3D11; ++#endif ++#if CONFIG_HEVC_VAAPI_HWACCEL ++ *fmt++ = AV_PIX_FMT_VAAPI; ++#endif ++#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL ++ *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; ++#endif ++#if CONFIG_HEVC_NVDEC_HWACCEL ++ *fmt++ = AV_PIX_FMT_CUDA; ++#endif ++ break; ++ case AV_PIX_FMT_YUV444P: ++#if CONFIG_HEVC_VDPAU_HWACCEL ++ *fmt++ = AV_PIX_FMT_VDPAU; ++#endif ++#if CONFIG_HEVC_NVDEC_HWACCEL ++ *fmt++ = AV_PIX_FMT_CUDA; ++#endif ++ break; ++ case AV_PIX_FMT_YUV420P12: ++ case AV_PIX_FMT_YUV444P10: ++ case AV_PIX_FMT_YUV444P12: ++#if CONFIG_HEVC_NVDEC_HWACCEL ++ *fmt++ = AV_PIX_FMT_CUDA; ++#endif ++ break; ++ } ++ ++ *fmt++ = sps->pix_fmt; ++ *fmt = AV_PIX_FMT_NONE; ++ ++ return ff_thread_get_format(s->avctx, pix_fmts); ++} ++ ++static int set_sps(HEVCContext *s, const HEVCSPS *sps, ++ enum AVPixelFormat pix_fmt) ++{ ++ int ret, i; ++ ++ pic_arrays_free(s); ++ s->ps.sps = NULL; ++ s->ps.vps = NULL; ++ ++ if (!sps) ++ return 0; ++ ++ ret = pic_arrays_init(s, sps); ++ if (ret < 0) ++ goto fail; ++ ++ export_stream_params(s, sps); ++ ++ s->avctx->pix_fmt = pix_fmt; ++ ++ ff_hevc_pred_init(&s->hpc, sps->bit_depth); ++ ff_hevc_dsp_init (&s->hevcdsp, sps->bit_depth); ++ ff_videodsp_init (&s->vdsp, sps->bit_depth); ++ ++ for (i = 0; i < 3; i++) { ++ av_freep(&s->sao_pixel_buffer_h[i]); ++ av_freep(&s->sao_pixel_buffer_v[i]); ++ } ++ ++ if (sps->sao_enabled && !s->avctx->hwaccel) { ++ int c_count = (sps->chroma_format_idc != 0) ? 3 : 1; ++ int c_idx; ++ ++ for(c_idx = 0; c_idx < c_count; c_idx++) { ++ int w = sps->width >> sps->hshift[c_idx]; ++ int h = sps->height >> sps->vshift[c_idx]; ++ s->sao_pixel_buffer_h[c_idx] = ++ av_malloc((w * 2 * sps->ctb_height) << ++ sps->pixel_shift); ++ s->sao_pixel_buffer_v[c_idx] = ++ av_malloc((h * 2 * sps->ctb_width) << ++ sps->pixel_shift); ++ } ++ } ++ ++ s->ps.sps = sps; ++ s->ps.vps = (HEVCVPS*) s->ps.vps_list[s->ps.sps->vps_id]->data; ++ ++ return 0; ++ ++fail: ++ pic_arrays_free(s); ++ s->ps.sps = NULL; ++ return ret; ++} ++ ++static int hls_slice_header(HEVCContext *s) ++{ ++ GetBitContext *gb = &s->HEVClc->gb; ++ SliceHeader *sh = &s->sh; ++ int i, ret; ++ ++ // Coded parameters ++ sh->first_slice_in_pic_flag = get_bits1(gb); ++ if (s->ref && sh->first_slice_in_pic_flag) { ++ av_log(s->avctx, AV_LOG_ERROR, "Two slices reporting being the first in the same frame.\n"); ++ return 1; // This slice will be skipped later, do not corrupt state ++ } ++ ++ if ((IS_IDR(s) || IS_BLA(s)) && sh->first_slice_in_pic_flag) { ++ s->seq_decode = (s->seq_decode + 1) & 0xff; ++ s->max_ra = INT_MAX; ++ if (IS_IDR(s)) ++ ff_hevc_clear_refs(s); ++ } ++ sh->no_output_of_prior_pics_flag = 0; ++ if (IS_IRAP(s)) ++ sh->no_output_of_prior_pics_flag = get_bits1(gb); ++ ++ sh->pps_id = get_ue_golomb_long(gb); ++ if (sh->pps_id >= HEVC_MAX_PPS_COUNT || !s->ps.pps_list[sh->pps_id]) { ++ av_log(s->avctx, AV_LOG_ERROR, "PPS id out of range: %d\n", sh->pps_id); ++ return AVERROR_INVALIDDATA; ++ } ++ if (!sh->first_slice_in_pic_flag && ++ s->ps.pps != (HEVCPPS*)s->ps.pps_list[sh->pps_id]->data) { ++ av_log(s->avctx, AV_LOG_ERROR, "PPS changed between slices.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ s->ps.pps = (HEVCPPS*)s->ps.pps_list[sh->pps_id]->data; ++ if (s->nal_unit_type == HEVC_NAL_CRA_NUT && s->last_eos == 1) ++ sh->no_output_of_prior_pics_flag = 1; ++ ++ if (s->ps.sps != (HEVCSPS*)s->ps.sps_list[s->ps.pps->sps_id]->data) { ++ const HEVCSPS *sps = (HEVCSPS*)s->ps.sps_list[s->ps.pps->sps_id]->data; ++ const HEVCSPS *last_sps = s->ps.sps; ++ enum AVPixelFormat pix_fmt; ++ ++ if (last_sps && IS_IRAP(s) && s->nal_unit_type != HEVC_NAL_CRA_NUT) { ++ if (sps->width != last_sps->width || sps->height != last_sps->height || ++ sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering != ++ last_sps->temporal_layer[last_sps->max_sub_layers - 1].max_dec_pic_buffering) ++ sh->no_output_of_prior_pics_flag = 0; ++ } ++ ff_hevc_clear_refs(s); ++ ++ ret = set_sps(s, sps, sps->pix_fmt); ++ if (ret < 0) ++ return ret; ++ ++ pix_fmt = get_format(s, sps); ++ if (pix_fmt < 0) ++ return pix_fmt; ++ s->avctx->pix_fmt = pix_fmt; ++ ++ s->seq_decode = (s->seq_decode + 1) & 0xff; ++ s->max_ra = INT_MAX; ++ } ++ ++ sh->dependent_slice_segment_flag = 0; ++ if (!sh->first_slice_in_pic_flag) { ++ int slice_address_length; ++ ++ if (s->ps.pps->dependent_slice_segments_enabled_flag) ++ sh->dependent_slice_segment_flag = get_bits1(gb); ++ ++ slice_address_length = av_ceil_log2(s->ps.sps->ctb_width * ++ s->ps.sps->ctb_height); ++ sh->slice_segment_addr = get_bitsz(gb, slice_address_length); ++ if (sh->slice_segment_addr >= s->ps.sps->ctb_width * s->ps.sps->ctb_height) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "Invalid slice segment address: %u.\n", ++ sh->slice_segment_addr); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (!sh->dependent_slice_segment_flag) { ++ sh->slice_addr = sh->slice_segment_addr; ++ s->slice_idx++; ++ } ++ } else { ++ sh->slice_segment_addr = sh->slice_addr = 0; ++ s->slice_idx = 0; ++ s->slice_initialized = 0; ++ } ++ ++ if (!sh->dependent_slice_segment_flag) { ++ s->slice_initialized = 0; ++ ++ for (i = 0; i < s->ps.pps->num_extra_slice_header_bits; i++) ++ skip_bits(gb, 1); // slice_reserved_undetermined_flag[] ++ ++ sh->slice_type = get_ue_golomb_long(gb); ++ if (!(sh->slice_type == HEVC_SLICE_I || ++ sh->slice_type == HEVC_SLICE_P || ++ sh->slice_type == HEVC_SLICE_B)) { ++ av_log(s->avctx, AV_LOG_ERROR, "Unknown slice type: %d.\n", ++ sh->slice_type); ++ return AVERROR_INVALIDDATA; ++ } ++ if (IS_IRAP(s) && sh->slice_type != HEVC_SLICE_I) { ++ av_log(s->avctx, AV_LOG_ERROR, "Inter slices in an IRAP frame.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ // when flag is not present, picture is inferred to be output ++ sh->pic_output_flag = 1; ++ if (s->ps.pps->output_flag_present_flag) ++ sh->pic_output_flag = get_bits1(gb); ++ ++ if (s->ps.sps->separate_colour_plane_flag) ++ sh->colour_plane_id = get_bits(gb, 2); ++ ++ if (!IS_IDR(s)) { ++ int poc, pos; ++ ++ sh->pic_order_cnt_lsb = get_bits(gb, s->ps.sps->log2_max_poc_lsb); ++ poc = ff_hevc_compute_poc(s->ps.sps, s->pocTid0, sh->pic_order_cnt_lsb, s->nal_unit_type); ++ if (!sh->first_slice_in_pic_flag && poc != s->poc) { ++ av_log(s->avctx, AV_LOG_WARNING, ++ "Ignoring POC change between slices: %d -> %d\n", s->poc, poc); ++ if (s->avctx->err_recognition & AV_EF_EXPLODE) ++ return AVERROR_INVALIDDATA; ++ poc = s->poc; ++ } ++ s->poc = poc; ++ ++ sh->short_term_ref_pic_set_sps_flag = get_bits1(gb); ++ pos = get_bits_left(gb); ++ if (!sh->short_term_ref_pic_set_sps_flag) { ++ ret = ff_hevc_decode_short_term_rps(gb, s->avctx, &sh->slice_rps, s->ps.sps, 1); ++ if (ret < 0) ++ return ret; ++ ++ sh->short_term_rps = &sh->slice_rps; ++ } else { ++ int numbits, rps_idx; ++ ++ if (!s->ps.sps->nb_st_rps) { ++ av_log(s->avctx, AV_LOG_ERROR, "No ref lists in the SPS.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ numbits = av_ceil_log2(s->ps.sps->nb_st_rps); ++ rps_idx = numbits > 0 ? get_bits(gb, numbits) : 0; ++ sh->short_term_rps = &s->ps.sps->st_rps[rps_idx]; ++ } ++ sh->short_term_ref_pic_set_size = pos - get_bits_left(gb); ++ ++ pos = get_bits_left(gb); ++ ret = decode_lt_rps(s, &sh->long_term_rps, gb); ++ if (ret < 0) { ++ av_log(s->avctx, AV_LOG_WARNING, "Invalid long term RPS.\n"); ++ if (s->avctx->err_recognition & AV_EF_EXPLODE) ++ return AVERROR_INVALIDDATA; ++ } ++ sh->long_term_ref_pic_set_size = pos - get_bits_left(gb); ++ ++ if (s->ps.sps->sps_temporal_mvp_enabled_flag) ++ sh->slice_temporal_mvp_enabled_flag = get_bits1(gb); ++ else ++ sh->slice_temporal_mvp_enabled_flag = 0; ++ } else { ++ s->sh.short_term_rps = NULL; ++ s->poc = 0; ++ } ++ ++ /* 8.3.1 */ ++ if (sh->first_slice_in_pic_flag && s->temporal_id == 0 && ++ s->nal_unit_type != HEVC_NAL_TRAIL_N && ++ s->nal_unit_type != HEVC_NAL_TSA_N && ++ s->nal_unit_type != HEVC_NAL_STSA_N && ++ s->nal_unit_type != HEVC_NAL_RADL_N && ++ s->nal_unit_type != HEVC_NAL_RADL_R && ++ s->nal_unit_type != HEVC_NAL_RASL_N && ++ s->nal_unit_type != HEVC_NAL_RASL_R) ++ s->pocTid0 = s->poc; ++ ++ if (s->ps.sps->sao_enabled) { ++ sh->slice_sample_adaptive_offset_flag[0] = get_bits1(gb); ++ if (s->ps.sps->chroma_format_idc) { ++ sh->slice_sample_adaptive_offset_flag[1] = ++ sh->slice_sample_adaptive_offset_flag[2] = get_bits1(gb); ++ } ++ } else { ++ sh->slice_sample_adaptive_offset_flag[0] = 0; ++ sh->slice_sample_adaptive_offset_flag[1] = 0; ++ sh->slice_sample_adaptive_offset_flag[2] = 0; ++ } ++ ++ sh->nb_refs[L0] = sh->nb_refs[L1] = 0; ++ if (sh->slice_type == HEVC_SLICE_P || sh->slice_type == HEVC_SLICE_B) { ++ int nb_refs; ++ ++ sh->nb_refs[L0] = s->ps.pps->num_ref_idx_l0_default_active; ++ if (sh->slice_type == HEVC_SLICE_B) ++ sh->nb_refs[L1] = s->ps.pps->num_ref_idx_l1_default_active; ++ ++ if (get_bits1(gb)) { // num_ref_idx_active_override_flag ++ sh->nb_refs[L0] = get_ue_golomb_long(gb) + 1; ++ if (sh->slice_type == HEVC_SLICE_B) ++ sh->nb_refs[L1] = get_ue_golomb_long(gb) + 1; ++ } ++ if (sh->nb_refs[L0] > HEVC_MAX_REFS || sh->nb_refs[L1] > HEVC_MAX_REFS) { ++ av_log(s->avctx, AV_LOG_ERROR, "Too many refs: %d/%d.\n", ++ sh->nb_refs[L0], sh->nb_refs[L1]); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ sh->rpl_modification_flag[0] = 0; ++ sh->rpl_modification_flag[1] = 0; ++ nb_refs = ff_hevc_frame_nb_refs(s); ++ if (!nb_refs) { ++ av_log(s->avctx, AV_LOG_ERROR, "Zero refs for a frame with P or B slices.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (s->ps.pps->lists_modification_present_flag && nb_refs > 1) { ++ sh->rpl_modification_flag[0] = get_bits1(gb); ++ if (sh->rpl_modification_flag[0]) { ++ for (i = 0; i < sh->nb_refs[L0]; i++) ++ sh->list_entry_lx[0][i] = get_bits(gb, av_ceil_log2(nb_refs)); ++ } ++ ++ if (sh->slice_type == HEVC_SLICE_B) { ++ sh->rpl_modification_flag[1] = get_bits1(gb); ++ if (sh->rpl_modification_flag[1] == 1) ++ for (i = 0; i < sh->nb_refs[L1]; i++) ++ sh->list_entry_lx[1][i] = get_bits(gb, av_ceil_log2(nb_refs)); ++ } ++ } ++ ++ if (sh->slice_type == HEVC_SLICE_B) ++ sh->mvd_l1_zero_flag = get_bits1(gb); ++ ++ if (s->ps.pps->cabac_init_present_flag) ++ sh->cabac_init_flag = get_bits1(gb); ++ else ++ sh->cabac_init_flag = 0; ++ ++ sh->collocated_ref_idx = 0; ++ if (sh->slice_temporal_mvp_enabled_flag) { ++ sh->collocated_list = L0; ++ if (sh->slice_type == HEVC_SLICE_B) ++ sh->collocated_list = !get_bits1(gb); ++ ++ if (sh->nb_refs[sh->collocated_list] > 1) { ++ sh->collocated_ref_idx = get_ue_golomb_long(gb); ++ if (sh->collocated_ref_idx >= sh->nb_refs[sh->collocated_list]) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "Invalid collocated_ref_idx: %d.\n", ++ sh->collocated_ref_idx); ++ return AVERROR_INVALIDDATA; ++ } ++ } ++ } ++ ++ if ((s->ps.pps->weighted_pred_flag && sh->slice_type == HEVC_SLICE_P) || ++ (s->ps.pps->weighted_bipred_flag && sh->slice_type == HEVC_SLICE_B)) { ++ int ret = pred_weight_table(s, gb); ++ if (ret < 0) ++ return ret; ++ } ++ ++ sh->max_num_merge_cand = 5 - get_ue_golomb_long(gb); ++ if (sh->max_num_merge_cand < 1 || sh->max_num_merge_cand > 5) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "Invalid number of merging MVP candidates: %d.\n", ++ sh->max_num_merge_cand); ++ return AVERROR_INVALIDDATA; ++ } ++ } ++ ++ sh->slice_qp_delta = get_se_golomb(gb); ++ ++ if (s->ps.pps->pic_slice_level_chroma_qp_offsets_present_flag) { ++ sh->slice_cb_qp_offset = get_se_golomb(gb); ++ sh->slice_cr_qp_offset = get_se_golomb(gb); ++ } else { ++ sh->slice_cb_qp_offset = 0; ++ sh->slice_cr_qp_offset = 0; ++ } ++ ++ if (s->ps.pps->chroma_qp_offset_list_enabled_flag) ++ sh->cu_chroma_qp_offset_enabled_flag = get_bits1(gb); ++ else ++ sh->cu_chroma_qp_offset_enabled_flag = 0; ++ ++ if (s->ps.pps->deblocking_filter_control_present_flag) { ++ int deblocking_filter_override_flag = 0; ++ ++ if (s->ps.pps->deblocking_filter_override_enabled_flag) ++ deblocking_filter_override_flag = get_bits1(gb); ++ ++ if (deblocking_filter_override_flag) { ++ sh->disable_deblocking_filter_flag = get_bits1(gb); ++ if (!sh->disable_deblocking_filter_flag) { ++ int beta_offset_div2 = get_se_golomb(gb); ++ int tc_offset_div2 = get_se_golomb(gb) ; ++ if (beta_offset_div2 < -6 || beta_offset_div2 > 6 || ++ tc_offset_div2 < -6 || tc_offset_div2 > 6) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "Invalid deblock filter offsets: %d, %d\n", ++ beta_offset_div2, tc_offset_div2); ++ return AVERROR_INVALIDDATA; ++ } ++ sh->beta_offset = beta_offset_div2 * 2; ++ sh->tc_offset = tc_offset_div2 * 2; ++ } ++ } else { ++ sh->disable_deblocking_filter_flag = s->ps.pps->disable_dbf; ++ sh->beta_offset = s->ps.pps->beta_offset; ++ sh->tc_offset = s->ps.pps->tc_offset; ++ } ++ } else { ++ sh->disable_deblocking_filter_flag = 0; ++ sh->beta_offset = 0; ++ sh->tc_offset = 0; ++ } ++ ++ if (s->ps.pps->seq_loop_filter_across_slices_enabled_flag && ++ (sh->slice_sample_adaptive_offset_flag[0] || ++ sh->slice_sample_adaptive_offset_flag[1] || ++ !sh->disable_deblocking_filter_flag)) { ++ sh->slice_loop_filter_across_slices_enabled_flag = get_bits1(gb); ++ } else { ++ sh->slice_loop_filter_across_slices_enabled_flag = s->ps.pps->seq_loop_filter_across_slices_enabled_flag; ++ } ++ } else if (!s->slice_initialized) { ++ av_log(s->avctx, AV_LOG_ERROR, "Independent slice segment missing.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ sh->num_entry_point_offsets = 0; ++ if (s->ps.pps->tiles_enabled_flag || s->ps.pps->entropy_coding_sync_enabled_flag) { ++ unsigned num_entry_point_offsets = get_ue_golomb_long(gb); ++ // It would be possible to bound this tighter but this here is simpler ++ if (num_entry_point_offsets > get_bits_left(gb)) { ++ av_log(s->avctx, AV_LOG_ERROR, "num_entry_point_offsets %d is invalid\n", num_entry_point_offsets); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ sh->num_entry_point_offsets = num_entry_point_offsets; ++ if (sh->num_entry_point_offsets > 0) { ++ int offset_len = get_ue_golomb_long(gb) + 1; ++ ++ if (offset_len < 1 || offset_len > 32) { ++ sh->num_entry_point_offsets = 0; ++ av_log(s->avctx, AV_LOG_ERROR, "offset_len %d is invalid\n", offset_len); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ av_freep(&sh->entry_point_offset); ++ av_freep(&sh->offset); ++ av_freep(&sh->size); ++ sh->entry_point_offset = av_malloc_array(sh->num_entry_point_offsets, sizeof(unsigned)); ++ sh->offset = av_malloc_array(sh->num_entry_point_offsets, sizeof(int)); ++ sh->size = av_malloc_array(sh->num_entry_point_offsets, sizeof(int)); ++ if (!sh->entry_point_offset || !sh->offset || !sh->size) { ++ sh->num_entry_point_offsets = 0; ++ av_log(s->avctx, AV_LOG_ERROR, "Failed to allocate memory\n"); ++ return AVERROR(ENOMEM); ++ } ++ for (i = 0; i < sh->num_entry_point_offsets; i++) { ++ unsigned val = get_bits_long(gb, offset_len); ++ sh->entry_point_offset[i] = val + 1; // +1; // +1 to get the size ++ } ++ if (s->threads_number > 1 && (s->ps.pps->num_tile_rows > 1 || s->ps.pps->num_tile_columns > 1)) { ++ s->enable_parallel_tiles = 0; // TODO: you can enable tiles in parallel here ++ s->threads_number = 1; ++ } else ++ s->enable_parallel_tiles = 0; ++ } else ++ s->enable_parallel_tiles = 0; ++ } ++ ++ if (s->ps.pps->slice_header_extension_present_flag) { ++ unsigned int length = get_ue_golomb_long(gb); ++ if (length*8LL > get_bits_left(gb)) { ++ av_log(s->avctx, AV_LOG_ERROR, "too many slice_header_extension_data_bytes\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ for (i = 0; i < length; i++) ++ skip_bits(gb, 8); // slice_header_extension_data_byte ++ } ++ ++ // Inferred parameters ++ sh->slice_qp = 26U + s->ps.pps->pic_init_qp_minus26 + sh->slice_qp_delta; ++ if (sh->slice_qp > 51 || ++ sh->slice_qp < -s->ps.sps->qp_bd_offset) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "The slice_qp %d is outside the valid range " ++ "[%d, 51].\n", ++ sh->slice_qp, ++ -s->ps.sps->qp_bd_offset); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ sh->slice_ctb_addr_rs = sh->slice_segment_addr; ++ ++ if (!s->sh.slice_ctb_addr_rs && s->sh.dependent_slice_segment_flag) { ++ av_log(s->avctx, AV_LOG_ERROR, "Impossible slice segment.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (get_bits_left(gb) < 0) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "Overread slice header by %d bits\n", -get_bits_left(gb)); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ s->HEVClc->first_qp_group = !s->sh.dependent_slice_segment_flag; ++ ++ if (!s->ps.pps->cu_qp_delta_enabled_flag) ++ s->HEVClc->qp_y = s->sh.slice_qp; ++ ++ s->slice_initialized = 1; ++ s->HEVClc->tu.cu_qp_offset_cb = 0; ++ s->HEVClc->tu.cu_qp_offset_cr = 0; ++ ++ return 0; ++} ++ ++#define CTB(tab, x, y) ((tab)[(y) * s->ps.sps->ctb_width + (x)]) ++ ++#define SET_SAO(elem, value) \ ++do { \ ++ if (!sao_merge_up_flag && !sao_merge_left_flag) \ ++ sao->elem = value; \ ++ else if (sao_merge_left_flag) \ ++ sao->elem = CTB(s->sao, rx-1, ry).elem; \ ++ else if (sao_merge_up_flag) \ ++ sao->elem = CTB(s->sao, rx, ry-1).elem; \ ++ else \ ++ sao->elem = 0; \ ++} while (0) ++ ++static void hls_sao_param(HEVCContext *s, int rx, int ry) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ int sao_merge_left_flag = 0; ++ int sao_merge_up_flag = 0; ++ SAOParams *sao = &CTB(s->sao, rx, ry); ++ int c_idx, i; ++ ++ if (s->sh.slice_sample_adaptive_offset_flag[0] || ++ s->sh.slice_sample_adaptive_offset_flag[1]) { ++ if (rx > 0) { ++ if (lc->ctb_left_flag) ++ sao_merge_left_flag = ff_hevc_sao_merge_flag_decode(s); ++ } ++ if (ry > 0 && !sao_merge_left_flag) { ++ if (lc->ctb_up_flag) ++ sao_merge_up_flag = ff_hevc_sao_merge_flag_decode(s); ++ } ++ } ++ ++ for (c_idx = 0; c_idx < (s->ps.sps->chroma_format_idc ? 3 : 1); c_idx++) { ++ int log2_sao_offset_scale = c_idx == 0 ? s->ps.pps->log2_sao_offset_scale_luma : ++ s->ps.pps->log2_sao_offset_scale_chroma; ++ ++ if (!s->sh.slice_sample_adaptive_offset_flag[c_idx]) { ++ sao->type_idx[c_idx] = SAO_NOT_APPLIED; ++ continue; ++ } ++ ++ if (c_idx == 2) { ++ sao->type_idx[2] = sao->type_idx[1]; ++ sao->eo_class[2] = sao->eo_class[1]; ++ } else { ++ SET_SAO(type_idx[c_idx], ff_hevc_sao_type_idx_decode(s)); ++ } ++ ++ if (sao->type_idx[c_idx] == SAO_NOT_APPLIED) ++ continue; ++ ++ for (i = 0; i < 4; i++) ++ SET_SAO(offset_abs[c_idx][i], ff_hevc_sao_offset_abs_decode(s)); ++ ++ if (sao->type_idx[c_idx] == SAO_BAND) { ++ for (i = 0; i < 4; i++) { ++ if (sao->offset_abs[c_idx][i]) { ++ SET_SAO(offset_sign[c_idx][i], ++ ff_hevc_sao_offset_sign_decode(s)); ++ } else { ++ sao->offset_sign[c_idx][i] = 0; ++ } ++ } ++ SET_SAO(band_position[c_idx], ff_hevc_sao_band_position_decode(s)); ++ } else if (c_idx != 2) { ++ SET_SAO(eo_class[c_idx], ff_hevc_sao_eo_class_decode(s)); ++ } ++ ++ // Inferred parameters ++ sao->offset_val[c_idx][0] = 0; ++ for (i = 0; i < 4; i++) { ++ sao->offset_val[c_idx][i + 1] = sao->offset_abs[c_idx][i]; ++ if (sao->type_idx[c_idx] == SAO_EDGE) { ++ if (i > 1) ++ sao->offset_val[c_idx][i + 1] = -sao->offset_val[c_idx][i + 1]; ++ } else if (sao->offset_sign[c_idx][i]) { ++ sao->offset_val[c_idx][i + 1] = -sao->offset_val[c_idx][i + 1]; ++ } ++ sao->offset_val[c_idx][i + 1] *= 1 << log2_sao_offset_scale; ++ } ++ } ++} ++ ++#undef SET_SAO ++#undef CTB ++ ++static int hls_cross_component_pred(HEVCContext *s, int idx) { ++ HEVCLocalContext *lc = s->HEVClc; ++ int log2_res_scale_abs_plus1 = ff_hevc_log2_res_scale_abs(s, idx); ++ ++ if (log2_res_scale_abs_plus1 != 0) { ++ int res_scale_sign_flag = ff_hevc_res_scale_sign_flag(s, idx); ++ lc->tu.res_scale_val = (1 << (log2_res_scale_abs_plus1 - 1)) * ++ (1 - 2 * res_scale_sign_flag); ++ } else { ++ lc->tu.res_scale_val = 0; ++ } ++ ++ ++ return 0; ++} ++ ++static int hls_transform_unit(HEVCContext *s, int x0, int y0, ++ int xBase, int yBase, int cb_xBase, int cb_yBase, ++ int log2_cb_size, int log2_trafo_size, ++ int blk_idx, int cbf_luma, int *cbf_cb, int *cbf_cr) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ const int log2_trafo_size_c = log2_trafo_size - s->ps.sps->hshift[1]; ++ int i; ++ ++ if (lc->cu.pred_mode == MODE_INTRA) { ++ int trafo_size = 1 << log2_trafo_size; ++ ff_hevc_set_neighbour_available(s, x0, y0, trafo_size, trafo_size); ++ ++ s->hpc.intra_pred[log2_trafo_size - 2](s, x0, y0, 0); ++ } ++ ++ if (cbf_luma || cbf_cb[0] || cbf_cr[0] || ++ (s->ps.sps->chroma_format_idc == 2 && (cbf_cb[1] || cbf_cr[1]))) { ++ int scan_idx = SCAN_DIAG; ++ int scan_idx_c = SCAN_DIAG; ++ int cbf_chroma = cbf_cb[0] || cbf_cr[0] || ++ (s->ps.sps->chroma_format_idc == 2 && ++ (cbf_cb[1] || cbf_cr[1])); ++ ++ if (s->ps.pps->cu_qp_delta_enabled_flag && !lc->tu.is_cu_qp_delta_coded) { ++ lc->tu.cu_qp_delta = ff_hevc_cu_qp_delta_abs(s); ++ if (lc->tu.cu_qp_delta != 0) ++ if (ff_hevc_cu_qp_delta_sign_flag(s) == 1) ++ lc->tu.cu_qp_delta = -lc->tu.cu_qp_delta; ++ lc->tu.is_cu_qp_delta_coded = 1; ++ ++ if (lc->tu.cu_qp_delta < -(26 + s->ps.sps->qp_bd_offset / 2) || ++ lc->tu.cu_qp_delta > (25 + s->ps.sps->qp_bd_offset / 2)) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "The cu_qp_delta %d is outside the valid range " ++ "[%d, %d].\n", ++ lc->tu.cu_qp_delta, ++ -(26 + s->ps.sps->qp_bd_offset / 2), ++ (25 + s->ps.sps->qp_bd_offset / 2)); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ ff_hevc_set_qPy(s, cb_xBase, cb_yBase, log2_cb_size); ++ } ++ ++ if (s->sh.cu_chroma_qp_offset_enabled_flag && cbf_chroma && ++ !lc->cu.cu_transquant_bypass_flag && !lc->tu.is_cu_chroma_qp_offset_coded) { ++ int cu_chroma_qp_offset_flag = ff_hevc_cu_chroma_qp_offset_flag(s); ++ if (cu_chroma_qp_offset_flag) { ++ int cu_chroma_qp_offset_idx = 0; ++ if (s->ps.pps->chroma_qp_offset_list_len_minus1 > 0) { ++ cu_chroma_qp_offset_idx = ff_hevc_cu_chroma_qp_offset_idx(s); ++ av_log(s->avctx, AV_LOG_ERROR, ++ "cu_chroma_qp_offset_idx not yet tested.\n"); ++ } ++ lc->tu.cu_qp_offset_cb = s->ps.pps->cb_qp_offset_list[cu_chroma_qp_offset_idx]; ++ lc->tu.cu_qp_offset_cr = s->ps.pps->cr_qp_offset_list[cu_chroma_qp_offset_idx]; ++ } else { ++ lc->tu.cu_qp_offset_cb = 0; ++ lc->tu.cu_qp_offset_cr = 0; ++ } ++ lc->tu.is_cu_chroma_qp_offset_coded = 1; ++ } ++ ++ if (lc->cu.pred_mode == MODE_INTRA && log2_trafo_size < 4) { ++ if (lc->tu.intra_pred_mode >= 6 && ++ lc->tu.intra_pred_mode <= 14) { ++ scan_idx = SCAN_VERT; ++ } else if (lc->tu.intra_pred_mode >= 22 && ++ lc->tu.intra_pred_mode <= 30) { ++ scan_idx = SCAN_HORIZ; ++ } ++ ++ if (lc->tu.intra_pred_mode_c >= 6 && ++ lc->tu.intra_pred_mode_c <= 14) { ++ scan_idx_c = SCAN_VERT; ++ } else if (lc->tu.intra_pred_mode_c >= 22 && ++ lc->tu.intra_pred_mode_c <= 30) { ++ scan_idx_c = SCAN_HORIZ; ++ } ++ } ++ ++ lc->tu.cross_pf = 0; ++ ++ if (cbf_luma) ++ ff_hevc_hls_residual_coding(s, x0, y0, log2_trafo_size, scan_idx, 0); ++ if (s->ps.sps->chroma_format_idc && (log2_trafo_size > 2 || s->ps.sps->chroma_format_idc == 3)) { ++ int trafo_size_h = 1 << (log2_trafo_size_c + s->ps.sps->hshift[1]); ++ int trafo_size_v = 1 << (log2_trafo_size_c + s->ps.sps->vshift[1]); ++ lc->tu.cross_pf = (s->ps.pps->cross_component_prediction_enabled_flag && cbf_luma && ++ (lc->cu.pred_mode == MODE_INTER || ++ (lc->tu.chroma_mode_c == 4))); ++ ++ if (lc->tu.cross_pf) { ++ hls_cross_component_pred(s, 0); ++ } ++ for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) { ++ if (lc->cu.pred_mode == MODE_INTRA) { ++ ff_hevc_set_neighbour_available(s, x0, y0 + (i << log2_trafo_size_c), trafo_size_h, trafo_size_v); ++ s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 1); ++ } ++ if (cbf_cb[i]) ++ ff_hevc_hls_residual_coding(s, x0, y0 + (i << log2_trafo_size_c), ++ log2_trafo_size_c, scan_idx_c, 1); ++ else ++ if (lc->tu.cross_pf) { ++ ptrdiff_t stride = s->frame->linesize[1]; ++ int hshift = s->ps.sps->hshift[1]; ++ int vshift = s->ps.sps->vshift[1]; ++ int16_t *coeffs_y = (int16_t*)lc->edge_emu_buffer; ++ int16_t *coeffs = (int16_t*)lc->edge_emu_buffer2; ++ int size = 1 << log2_trafo_size_c; ++ ++ uint8_t *dst = &s->frame->data[1][(y0 >> vshift) * stride + ++ ((x0 >> hshift) << s->ps.sps->pixel_shift)]; ++ for (i = 0; i < (size * size); i++) { ++ coeffs[i] = ((lc->tu.res_scale_val * coeffs_y[i]) >> 3); ++ } ++ s->hevcdsp.add_residual[log2_trafo_size_c-2](dst, coeffs, stride); ++ } ++ } ++ ++ if (lc->tu.cross_pf) { ++ hls_cross_component_pred(s, 1); ++ } ++ for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) { ++ if (lc->cu.pred_mode == MODE_INTRA) { ++ ff_hevc_set_neighbour_available(s, x0, y0 + (i << log2_trafo_size_c), trafo_size_h, trafo_size_v); ++ s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 2); ++ } ++ if (cbf_cr[i]) ++ ff_hevc_hls_residual_coding(s, x0, y0 + (i << log2_trafo_size_c), ++ log2_trafo_size_c, scan_idx_c, 2); ++ else ++ if (lc->tu.cross_pf) { ++ ptrdiff_t stride = s->frame->linesize[2]; ++ int hshift = s->ps.sps->hshift[2]; ++ int vshift = s->ps.sps->vshift[2]; ++ int16_t *coeffs_y = (int16_t*)lc->edge_emu_buffer; ++ int16_t *coeffs = (int16_t*)lc->edge_emu_buffer2; ++ int size = 1 << log2_trafo_size_c; ++ ++ uint8_t *dst = &s->frame->data[2][(y0 >> vshift) * stride + ++ ((x0 >> hshift) << s->ps.sps->pixel_shift)]; ++ for (i = 0; i < (size * size); i++) { ++ coeffs[i] = ((lc->tu.res_scale_val * coeffs_y[i]) >> 3); ++ } ++ s->hevcdsp.add_residual[log2_trafo_size_c-2](dst, coeffs, stride); ++ } ++ } ++ } else if (s->ps.sps->chroma_format_idc && blk_idx == 3) { ++ int trafo_size_h = 1 << (log2_trafo_size + 1); ++ int trafo_size_v = 1 << (log2_trafo_size + s->ps.sps->vshift[1]); ++ for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) { ++ if (lc->cu.pred_mode == MODE_INTRA) { ++ ff_hevc_set_neighbour_available(s, xBase, yBase + (i << log2_trafo_size), ++ trafo_size_h, trafo_size_v); ++ s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 1); ++ } ++ if (cbf_cb[i]) ++ ff_hevc_hls_residual_coding(s, xBase, yBase + (i << log2_trafo_size), ++ log2_trafo_size, scan_idx_c, 1); ++ } ++ for (i = 0; i < (s->ps.sps->chroma_format_idc == 2 ? 2 : 1); i++) { ++ if (lc->cu.pred_mode == MODE_INTRA) { ++ ff_hevc_set_neighbour_available(s, xBase, yBase + (i << log2_trafo_size), ++ trafo_size_h, trafo_size_v); ++ s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 2); ++ } ++ if (cbf_cr[i]) ++ ff_hevc_hls_residual_coding(s, xBase, yBase + (i << log2_trafo_size), ++ log2_trafo_size, scan_idx_c, 2); ++ } ++ } ++ } else if (s->ps.sps->chroma_format_idc && lc->cu.pred_mode == MODE_INTRA) { ++ if (log2_trafo_size > 2 || s->ps.sps->chroma_format_idc == 3) { ++ int trafo_size_h = 1 << (log2_trafo_size_c + s->ps.sps->hshift[1]); ++ int trafo_size_v = 1 << (log2_trafo_size_c + s->ps.sps->vshift[1]); ++ ff_hevc_set_neighbour_available(s, x0, y0, trafo_size_h, trafo_size_v); ++ s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0, 1); ++ s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0, 2); ++ if (s->ps.sps->chroma_format_idc == 2) { ++ ff_hevc_set_neighbour_available(s, x0, y0 + (1 << log2_trafo_size_c), ++ trafo_size_h, trafo_size_v); ++ s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (1 << log2_trafo_size_c), 1); ++ s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (1 << log2_trafo_size_c), 2); ++ } ++ } else if (blk_idx == 3) { ++ int trafo_size_h = 1 << (log2_trafo_size + 1); ++ int trafo_size_v = 1 << (log2_trafo_size + s->ps.sps->vshift[1]); ++ ff_hevc_set_neighbour_available(s, xBase, yBase, ++ trafo_size_h, trafo_size_v); ++ s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 1); ++ s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 2); ++ if (s->ps.sps->chroma_format_idc == 2) { ++ ff_hevc_set_neighbour_available(s, xBase, yBase + (1 << (log2_trafo_size)), ++ trafo_size_h, trafo_size_v); ++ s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (1 << (log2_trafo_size)), 1); ++ s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (1 << (log2_trafo_size)), 2); ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static void set_deblocking_bypass(HEVCContext *s, int x0, int y0, int log2_cb_size) ++{ ++ int cb_size = 1 << log2_cb_size; ++ int log2_min_pu_size = s->ps.sps->log2_min_pu_size; ++ ++ int min_pu_width = s->ps.sps->min_pu_width; ++ int x_end = FFMIN(x0 + cb_size, s->ps.sps->width); ++ int y_end = FFMIN(y0 + cb_size, s->ps.sps->height); ++ int i, j; ++ ++ for (j = (y0 >> log2_min_pu_size); j < (y_end >> log2_min_pu_size); j++) ++ for (i = (x0 >> log2_min_pu_size); i < (x_end >> log2_min_pu_size); i++) ++ s->is_pcm[i + j * min_pu_width] = 2; ++} ++ ++static int hls_transform_tree(HEVCContext *s, int x0, int y0, ++ int xBase, int yBase, int cb_xBase, int cb_yBase, ++ int log2_cb_size, int log2_trafo_size, ++ int trafo_depth, int blk_idx, ++ const int *base_cbf_cb, const int *base_cbf_cr) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ uint8_t split_transform_flag; ++ int cbf_cb[2]; ++ int cbf_cr[2]; ++ int ret; ++ ++ cbf_cb[0] = base_cbf_cb[0]; ++ cbf_cb[1] = base_cbf_cb[1]; ++ cbf_cr[0] = base_cbf_cr[0]; ++ cbf_cr[1] = base_cbf_cr[1]; ++ ++ if (lc->cu.intra_split_flag) { ++ if (trafo_depth == 1) { ++ lc->tu.intra_pred_mode = lc->pu.intra_pred_mode[blk_idx]; ++ if (s->ps.sps->chroma_format_idc == 3) { ++ lc->tu.intra_pred_mode_c = lc->pu.intra_pred_mode_c[blk_idx]; ++ lc->tu.chroma_mode_c = lc->pu.chroma_mode_c[blk_idx]; ++ } else { ++ lc->tu.intra_pred_mode_c = lc->pu.intra_pred_mode_c[0]; ++ lc->tu.chroma_mode_c = lc->pu.chroma_mode_c[0]; ++ } ++ } ++ } else { ++ lc->tu.intra_pred_mode = lc->pu.intra_pred_mode[0]; ++ lc->tu.intra_pred_mode_c = lc->pu.intra_pred_mode_c[0]; ++ lc->tu.chroma_mode_c = lc->pu.chroma_mode_c[0]; ++ } ++ ++ if (log2_trafo_size <= s->ps.sps->log2_max_trafo_size && ++ log2_trafo_size > s->ps.sps->log2_min_tb_size && ++ trafo_depth < lc->cu.max_trafo_depth && ++ !(lc->cu.intra_split_flag && trafo_depth == 0)) { ++ split_transform_flag = ff_hevc_split_transform_flag_decode(s, log2_trafo_size); ++ } else { ++ int inter_split = s->ps.sps->max_transform_hierarchy_depth_inter == 0 && ++ lc->cu.pred_mode == MODE_INTER && ++ lc->cu.part_mode != PART_2Nx2N && ++ trafo_depth == 0; ++ ++ split_transform_flag = log2_trafo_size > s->ps.sps->log2_max_trafo_size || ++ (lc->cu.intra_split_flag && trafo_depth == 0) || ++ inter_split; ++ } ++ ++ if (s->ps.sps->chroma_format_idc && (log2_trafo_size > 2 || s->ps.sps->chroma_format_idc == 3)) { ++ if (trafo_depth == 0 || cbf_cb[0]) { ++ cbf_cb[0] = ff_hevc_cbf_cb_cr_decode(s, trafo_depth); ++ if (s->ps.sps->chroma_format_idc == 2 && (!split_transform_flag || log2_trafo_size == 3)) { ++ cbf_cb[1] = ff_hevc_cbf_cb_cr_decode(s, trafo_depth); ++ } ++ } ++ ++ if (trafo_depth == 0 || cbf_cr[0]) { ++ cbf_cr[0] = ff_hevc_cbf_cb_cr_decode(s, trafo_depth); ++ if (s->ps.sps->chroma_format_idc == 2 && (!split_transform_flag || log2_trafo_size == 3)) { ++ cbf_cr[1] = ff_hevc_cbf_cb_cr_decode(s, trafo_depth); ++ } ++ } ++ } ++ ++ if (split_transform_flag) { ++ const int trafo_size_split = 1 << (log2_trafo_size - 1); ++ const int x1 = x0 + trafo_size_split; ++ const int y1 = y0 + trafo_size_split; ++ ++#define SUBDIVIDE(x, y, idx) \ ++do { \ ++ ret = hls_transform_tree(s, x, y, x0, y0, cb_xBase, cb_yBase, log2_cb_size, \ ++ log2_trafo_size - 1, trafo_depth + 1, idx, \ ++ cbf_cb, cbf_cr); \ ++ if (ret < 0) \ ++ return ret; \ ++} while (0) ++ ++ SUBDIVIDE(x0, y0, 0); ++ SUBDIVIDE(x1, y0, 1); ++ SUBDIVIDE(x0, y1, 2); ++ SUBDIVIDE(x1, y1, 3); ++ ++#undef SUBDIVIDE ++ } else { ++ int min_tu_size = 1 << s->ps.sps->log2_min_tb_size; ++ int log2_min_tu_size = s->ps.sps->log2_min_tb_size; ++ int min_tu_width = s->ps.sps->min_tb_width; ++ int cbf_luma = 1; ++ ++ if (lc->cu.pred_mode == MODE_INTRA || trafo_depth != 0 || ++ cbf_cb[0] || cbf_cr[0] || ++ (s->ps.sps->chroma_format_idc == 2 && (cbf_cb[1] || cbf_cr[1]))) { ++ cbf_luma = ff_hevc_cbf_luma_decode(s, trafo_depth); ++ } ++ ++ ret = hls_transform_unit(s, x0, y0, xBase, yBase, cb_xBase, cb_yBase, ++ log2_cb_size, log2_trafo_size, ++ blk_idx, cbf_luma, cbf_cb, cbf_cr); ++ if (ret < 0) ++ return ret; ++ // TODO: store cbf_luma somewhere else ++ if (cbf_luma) { ++ int i, j; ++ for (i = 0; i < (1 << log2_trafo_size); i += min_tu_size) ++ for (j = 0; j < (1 << log2_trafo_size); j += min_tu_size) { ++ int x_tu = (x0 + j) >> log2_min_tu_size; ++ int y_tu = (y0 + i) >> log2_min_tu_size; ++ s->cbf_luma[y_tu * min_tu_width + x_tu] = 1; ++ } ++ } ++ if (!s->sh.disable_deblocking_filter_flag) { ++ ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_trafo_size); ++ if (s->ps.pps->transquant_bypass_enable_flag && ++ lc->cu.cu_transquant_bypass_flag) ++ set_deblocking_bypass(s, x0, y0, log2_trafo_size); ++ } ++ } ++ return 0; ++} ++ ++static int hls_pcm_sample(HEVCContext *s, int x0, int y0, int log2_cb_size) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ GetBitContext gb; ++ int cb_size = 1 << log2_cb_size; ++ ptrdiff_t stride0 = s->frame->linesize[0]; ++ ptrdiff_t stride1 = s->frame->linesize[1]; ++ ptrdiff_t stride2 = s->frame->linesize[2]; ++ uint8_t *dst0 = &s->frame->data[0][y0 * stride0 + (x0 << s->ps.sps->pixel_shift)]; ++ uint8_t *dst1 = &s->frame->data[1][(y0 >> s->ps.sps->vshift[1]) * stride1 + ((x0 >> s->ps.sps->hshift[1]) << s->ps.sps->pixel_shift)]; ++ uint8_t *dst2 = &s->frame->data[2][(y0 >> s->ps.sps->vshift[2]) * stride2 + ((x0 >> s->ps.sps->hshift[2]) << s->ps.sps->pixel_shift)]; ++ ++ int length = cb_size * cb_size * s->ps.sps->pcm.bit_depth + ++ (((cb_size >> s->ps.sps->hshift[1]) * (cb_size >> s->ps.sps->vshift[1])) + ++ ((cb_size >> s->ps.sps->hshift[2]) * (cb_size >> s->ps.sps->vshift[2]))) * ++ s->ps.sps->pcm.bit_depth_chroma; ++ const uint8_t *pcm = skip_bytes(&lc->cc, (length + 7) >> 3); ++ int ret; ++ ++ if (!s->sh.disable_deblocking_filter_flag) ++ ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size); ++ ++ ret = init_get_bits(&gb, pcm, length); ++ if (ret < 0) ++ return ret; ++ ++ s->hevcdsp.put_pcm(dst0, stride0, cb_size, cb_size, &gb, s->ps.sps->pcm.bit_depth); ++ if (s->ps.sps->chroma_format_idc) { ++ s->hevcdsp.put_pcm(dst1, stride1, ++ cb_size >> s->ps.sps->hshift[1], ++ cb_size >> s->ps.sps->vshift[1], ++ &gb, s->ps.sps->pcm.bit_depth_chroma); ++ s->hevcdsp.put_pcm(dst2, stride2, ++ cb_size >> s->ps.sps->hshift[2], ++ cb_size >> s->ps.sps->vshift[2], ++ &gb, s->ps.sps->pcm.bit_depth_chroma); ++ } ++ ++ return 0; ++} ++ ++/** ++ * 8.5.3.2.2.1 Luma sample unidirectional interpolation process ++ * ++ * @param s HEVC decoding context ++ * @param dst target buffer for block data at block position ++ * @param dststride stride of the dst buffer ++ * @param ref reference picture buffer at origin (0, 0) ++ * @param mv motion vector (relative to block position) to get pixel data from ++ * @param x_off horizontal position of block from origin (0, 0) ++ * @param y_off vertical position of block from origin (0, 0) ++ * @param block_w width of block ++ * @param block_h height of block ++ * @param luma_weight weighting factor applied to the luma prediction ++ * @param luma_offset additive offset applied to the luma prediction value ++ */ ++ ++static void luma_mc_uni(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, ++ AVFrame *ref, const Mv *mv, int x_off, int y_off, ++ int block_w, int block_h, int luma_weight, int luma_offset) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ uint8_t *src = ref->data[0]; ++ ptrdiff_t srcstride = ref->linesize[0]; ++ int pic_width = s->ps.sps->width; ++ int pic_height = s->ps.sps->height; ++ int mx = mv->x & 3; ++ int my = mv->y & 3; ++ int weight_flag = (s->sh.slice_type == HEVC_SLICE_P && s->ps.pps->weighted_pred_flag) || ++ (s->sh.slice_type == HEVC_SLICE_B && s->ps.pps->weighted_bipred_flag); ++ int idx = ff_hevc_pel_weight[block_w]; ++ ++ x_off += mv->x >> 2; ++ y_off += mv->y >> 2; ++ src += y_off * srcstride + (x_off * (1 << s->ps.sps->pixel_shift)); ++ ++ if (x_off < QPEL_EXTRA_BEFORE || y_off < QPEL_EXTRA_AFTER || ++ x_off >= pic_width - block_w - QPEL_EXTRA_AFTER || ++ y_off >= pic_height - block_h - QPEL_EXTRA_AFTER) { ++ const ptrdiff_t edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->ps.sps->pixel_shift; ++ int offset = QPEL_EXTRA_BEFORE * srcstride + (QPEL_EXTRA_BEFORE << s->ps.sps->pixel_shift); ++ int buf_offset = QPEL_EXTRA_BEFORE * edge_emu_stride + (QPEL_EXTRA_BEFORE << s->ps.sps->pixel_shift); ++ ++ s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src - offset, ++ edge_emu_stride, srcstride, ++ block_w + QPEL_EXTRA, ++ block_h + QPEL_EXTRA, ++ x_off - QPEL_EXTRA_BEFORE, y_off - QPEL_EXTRA_BEFORE, ++ pic_width, pic_height); ++ src = lc->edge_emu_buffer + buf_offset; ++ srcstride = edge_emu_stride; ++ } ++ ++ if (!weight_flag) ++ s->hevcdsp.put_hevc_qpel_uni[idx][!!my][!!mx](dst, dststride, src, srcstride, ++ block_h, mx, my, block_w); ++ else ++ s->hevcdsp.put_hevc_qpel_uni_w[idx][!!my][!!mx](dst, dststride, src, srcstride, ++ block_h, s->sh.luma_log2_weight_denom, ++ luma_weight, luma_offset, mx, my, block_w); ++} ++ ++/** ++ * 8.5.3.2.2.1 Luma sample bidirectional interpolation process ++ * ++ * @param s HEVC decoding context ++ * @param dst target buffer for block data at block position ++ * @param dststride stride of the dst buffer ++ * @param ref0 reference picture0 buffer at origin (0, 0) ++ * @param mv0 motion vector0 (relative to block position) to get pixel data from ++ * @param x_off horizontal position of block from origin (0, 0) ++ * @param y_off vertical position of block from origin (0, 0) ++ * @param block_w width of block ++ * @param block_h height of block ++ * @param ref1 reference picture1 buffer at origin (0, 0) ++ * @param mv1 motion vector1 (relative to block position) to get pixel data from ++ * @param current_mv current motion vector structure ++ */ ++ static void luma_mc_bi(HEVCContext *s, uint8_t *dst, ptrdiff_t dststride, ++ AVFrame *ref0, const Mv *mv0, int x_off, int y_off, ++ int block_w, int block_h, AVFrame *ref1, const Mv *mv1, struct MvField *current_mv) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ ptrdiff_t src0stride = ref0->linesize[0]; ++ ptrdiff_t src1stride = ref1->linesize[0]; ++ int pic_width = s->ps.sps->width; ++ int pic_height = s->ps.sps->height; ++ int mx0 = mv0->x & 3; ++ int my0 = mv0->y & 3; ++ int mx1 = mv1->x & 3; ++ int my1 = mv1->y & 3; ++ int weight_flag = (s->sh.slice_type == HEVC_SLICE_P && s->ps.pps->weighted_pred_flag) || ++ (s->sh.slice_type == HEVC_SLICE_B && s->ps.pps->weighted_bipred_flag); ++ int x_off0 = x_off + (mv0->x >> 2); ++ int y_off0 = y_off + (mv0->y >> 2); ++ int x_off1 = x_off + (mv1->x >> 2); ++ int y_off1 = y_off + (mv1->y >> 2); ++ int idx = ff_hevc_pel_weight[block_w]; ++ ++ uint8_t *src0 = ref0->data[0] + y_off0 * src0stride + (int)((unsigned)x_off0 << s->ps.sps->pixel_shift); ++ uint8_t *src1 = ref1->data[0] + y_off1 * src1stride + (int)((unsigned)x_off1 << s->ps.sps->pixel_shift); ++ ++ if (x_off0 < QPEL_EXTRA_BEFORE || y_off0 < QPEL_EXTRA_AFTER || ++ x_off0 >= pic_width - block_w - QPEL_EXTRA_AFTER || ++ y_off0 >= pic_height - block_h - QPEL_EXTRA_AFTER) { ++ const ptrdiff_t edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->ps.sps->pixel_shift; ++ int offset = QPEL_EXTRA_BEFORE * src0stride + (QPEL_EXTRA_BEFORE << s->ps.sps->pixel_shift); ++ int buf_offset = QPEL_EXTRA_BEFORE * edge_emu_stride + (QPEL_EXTRA_BEFORE << s->ps.sps->pixel_shift); ++ ++ s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src0 - offset, ++ edge_emu_stride, src0stride, ++ block_w + QPEL_EXTRA, ++ block_h + QPEL_EXTRA, ++ x_off0 - QPEL_EXTRA_BEFORE, y_off0 - QPEL_EXTRA_BEFORE, ++ pic_width, pic_height); ++ src0 = lc->edge_emu_buffer + buf_offset; ++ src0stride = edge_emu_stride; ++ } ++ ++ if (x_off1 < QPEL_EXTRA_BEFORE || y_off1 < QPEL_EXTRA_AFTER || ++ x_off1 >= pic_width - block_w - QPEL_EXTRA_AFTER || ++ y_off1 >= pic_height - block_h - QPEL_EXTRA_AFTER) { ++ const ptrdiff_t edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->ps.sps->pixel_shift; ++ int offset = QPEL_EXTRA_BEFORE * src1stride + (QPEL_EXTRA_BEFORE << s->ps.sps->pixel_shift); ++ int buf_offset = QPEL_EXTRA_BEFORE * edge_emu_stride + (QPEL_EXTRA_BEFORE << s->ps.sps->pixel_shift); ++ ++ s->vdsp.emulated_edge_mc(lc->edge_emu_buffer2, src1 - offset, ++ edge_emu_stride, src1stride, ++ block_w + QPEL_EXTRA, ++ block_h + QPEL_EXTRA, ++ x_off1 - QPEL_EXTRA_BEFORE, y_off1 - QPEL_EXTRA_BEFORE, ++ pic_width, pic_height); ++ src1 = lc->edge_emu_buffer2 + buf_offset; ++ src1stride = edge_emu_stride; ++ } ++ ++ s->hevcdsp.put_hevc_qpel[idx][!!my0][!!mx0](lc->tmp, src0, src0stride, ++ block_h, mx0, my0, block_w); ++ if (!weight_flag) ++ s->hevcdsp.put_hevc_qpel_bi[idx][!!my1][!!mx1](dst, dststride, src1, src1stride, lc->tmp, ++ block_h, mx1, my1, block_w); ++ else ++ s->hevcdsp.put_hevc_qpel_bi_w[idx][!!my1][!!mx1](dst, dststride, src1, src1stride, lc->tmp, ++ block_h, s->sh.luma_log2_weight_denom, ++ s->sh.luma_weight_l0[current_mv->ref_idx[0]], ++ s->sh.luma_weight_l1[current_mv->ref_idx[1]], ++ s->sh.luma_offset_l0[current_mv->ref_idx[0]], ++ s->sh.luma_offset_l1[current_mv->ref_idx[1]], ++ mx1, my1, block_w); ++ ++} ++ ++/** ++ * 8.5.3.2.2.2 Chroma sample uniprediction interpolation process ++ * ++ * @param s HEVC decoding context ++ * @param dst1 target buffer for block data at block position (U plane) ++ * @param dst2 target buffer for block data at block position (V plane) ++ * @param dststride stride of the dst1 and dst2 buffers ++ * @param ref reference picture buffer at origin (0, 0) ++ * @param mv motion vector (relative to block position) to get pixel data from ++ * @param x_off horizontal position of block from origin (0, 0) ++ * @param y_off vertical position of block from origin (0, 0) ++ * @param block_w width of block ++ * @param block_h height of block ++ * @param chroma_weight weighting factor applied to the chroma prediction ++ * @param chroma_offset additive offset applied to the chroma prediction value ++ */ ++ ++static void chroma_mc_uni(HEVCContext *s, uint8_t *dst0, ++ ptrdiff_t dststride, uint8_t *src0, ptrdiff_t srcstride, int reflist, ++ int x_off, int y_off, int block_w, int block_h, struct MvField *current_mv, int chroma_weight, int chroma_offset) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ int pic_width = s->ps.sps->width >> s->ps.sps->hshift[1]; ++ int pic_height = s->ps.sps->height >> s->ps.sps->vshift[1]; ++ const Mv *mv = ¤t_mv->mv[reflist]; ++ int weight_flag = (s->sh.slice_type == HEVC_SLICE_P && s->ps.pps->weighted_pred_flag) || ++ (s->sh.slice_type == HEVC_SLICE_B && s->ps.pps->weighted_bipred_flag); ++ int idx = ff_hevc_pel_weight[block_w]; ++ int hshift = s->ps.sps->hshift[1]; ++ int vshift = s->ps.sps->vshift[1]; ++ intptr_t mx = av_mod_uintp2(mv->x, 2 + hshift); ++ intptr_t my = av_mod_uintp2(mv->y, 2 + vshift); ++ intptr_t _mx = mx << (1 - hshift); ++ intptr_t _my = my << (1 - vshift); ++ ++ x_off += mv->x >> (2 + hshift); ++ y_off += mv->y >> (2 + vshift); ++ src0 += y_off * srcstride + (x_off * (1 << s->ps.sps->pixel_shift)); ++ ++ if (x_off < EPEL_EXTRA_BEFORE || y_off < EPEL_EXTRA_AFTER || ++ x_off >= pic_width - block_w - EPEL_EXTRA_AFTER || ++ y_off >= pic_height - block_h - EPEL_EXTRA_AFTER) { ++ const int edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->ps.sps->pixel_shift; ++ int offset0 = EPEL_EXTRA_BEFORE * (srcstride + (1 << s->ps.sps->pixel_shift)); ++ int buf_offset0 = EPEL_EXTRA_BEFORE * ++ (edge_emu_stride + (1 << s->ps.sps->pixel_shift)); ++ s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src0 - offset0, ++ edge_emu_stride, srcstride, ++ block_w + EPEL_EXTRA, block_h + EPEL_EXTRA, ++ x_off - EPEL_EXTRA_BEFORE, ++ y_off - EPEL_EXTRA_BEFORE, ++ pic_width, pic_height); ++ ++ src0 = lc->edge_emu_buffer + buf_offset0; ++ srcstride = edge_emu_stride; ++ } ++ if (!weight_flag) ++ s->hevcdsp.put_hevc_epel_uni[idx][!!my][!!mx](dst0, dststride, src0, srcstride, ++ block_h, _mx, _my, block_w); ++ else ++ s->hevcdsp.put_hevc_epel_uni_w[idx][!!my][!!mx](dst0, dststride, src0, srcstride, ++ block_h, s->sh.chroma_log2_weight_denom, ++ chroma_weight, chroma_offset, _mx, _my, block_w); ++} ++ ++/** ++ * 8.5.3.2.2.2 Chroma sample bidirectional interpolation process ++ * ++ * @param s HEVC decoding context ++ * @param dst target buffer for block data at block position ++ * @param dststride stride of the dst buffer ++ * @param ref0 reference picture0 buffer at origin (0, 0) ++ * @param mv0 motion vector0 (relative to block position) to get pixel data from ++ * @param x_off horizontal position of block from origin (0, 0) ++ * @param y_off vertical position of block from origin (0, 0) ++ * @param block_w width of block ++ * @param block_h height of block ++ * @param ref1 reference picture1 buffer at origin (0, 0) ++ * @param mv1 motion vector1 (relative to block position) to get pixel data from ++ * @param current_mv current motion vector structure ++ * @param cidx chroma component(cb, cr) ++ */ ++static void chroma_mc_bi(HEVCContext *s, uint8_t *dst0, ptrdiff_t dststride, AVFrame *ref0, AVFrame *ref1, ++ int x_off, int y_off, int block_w, int block_h, struct MvField *current_mv, int cidx) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ uint8_t *src1 = ref0->data[cidx+1]; ++ uint8_t *src2 = ref1->data[cidx+1]; ++ ptrdiff_t src1stride = ref0->linesize[cidx+1]; ++ ptrdiff_t src2stride = ref1->linesize[cidx+1]; ++ int weight_flag = (s->sh.slice_type == HEVC_SLICE_P && s->ps.pps->weighted_pred_flag) || ++ (s->sh.slice_type == HEVC_SLICE_B && s->ps.pps->weighted_bipred_flag); ++ int pic_width = s->ps.sps->width >> s->ps.sps->hshift[1]; ++ int pic_height = s->ps.sps->height >> s->ps.sps->vshift[1]; ++ Mv *mv0 = ¤t_mv->mv[0]; ++ Mv *mv1 = ¤t_mv->mv[1]; ++ int hshift = s->ps.sps->hshift[1]; ++ int vshift = s->ps.sps->vshift[1]; ++ ++ intptr_t mx0 = av_mod_uintp2(mv0->x, 2 + hshift); ++ intptr_t my0 = av_mod_uintp2(mv0->y, 2 + vshift); ++ intptr_t mx1 = av_mod_uintp2(mv1->x, 2 + hshift); ++ intptr_t my1 = av_mod_uintp2(mv1->y, 2 + vshift); ++ intptr_t _mx0 = mx0 << (1 - hshift); ++ intptr_t _my0 = my0 << (1 - vshift); ++ intptr_t _mx1 = mx1 << (1 - hshift); ++ intptr_t _my1 = my1 << (1 - vshift); ++ ++ int x_off0 = x_off + (mv0->x >> (2 + hshift)); ++ int y_off0 = y_off + (mv0->y >> (2 + vshift)); ++ int x_off1 = x_off + (mv1->x >> (2 + hshift)); ++ int y_off1 = y_off + (mv1->y >> (2 + vshift)); ++ int idx = ff_hevc_pel_weight[block_w]; ++ src1 += y_off0 * src1stride + (int)((unsigned)x_off0 << s->ps.sps->pixel_shift); ++ src2 += y_off1 * src2stride + (int)((unsigned)x_off1 << s->ps.sps->pixel_shift); ++ ++ if (x_off0 < EPEL_EXTRA_BEFORE || y_off0 < EPEL_EXTRA_AFTER || ++ x_off0 >= pic_width - block_w - EPEL_EXTRA_AFTER || ++ y_off0 >= pic_height - block_h - EPEL_EXTRA_AFTER) { ++ const int edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->ps.sps->pixel_shift; ++ int offset1 = EPEL_EXTRA_BEFORE * (src1stride + (1 << s->ps.sps->pixel_shift)); ++ int buf_offset1 = EPEL_EXTRA_BEFORE * ++ (edge_emu_stride + (1 << s->ps.sps->pixel_shift)); ++ ++ s->vdsp.emulated_edge_mc(lc->edge_emu_buffer, src1 - offset1, ++ edge_emu_stride, src1stride, ++ block_w + EPEL_EXTRA, block_h + EPEL_EXTRA, ++ x_off0 - EPEL_EXTRA_BEFORE, ++ y_off0 - EPEL_EXTRA_BEFORE, ++ pic_width, pic_height); ++ ++ src1 = lc->edge_emu_buffer + buf_offset1; ++ src1stride = edge_emu_stride; ++ } ++ ++ if (x_off1 < EPEL_EXTRA_BEFORE || y_off1 < EPEL_EXTRA_AFTER || ++ x_off1 >= pic_width - block_w - EPEL_EXTRA_AFTER || ++ y_off1 >= pic_height - block_h - EPEL_EXTRA_AFTER) { ++ const int edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << s->ps.sps->pixel_shift; ++ int offset1 = EPEL_EXTRA_BEFORE * (src2stride + (1 << s->ps.sps->pixel_shift)); ++ int buf_offset1 = EPEL_EXTRA_BEFORE * ++ (edge_emu_stride + (1 << s->ps.sps->pixel_shift)); ++ ++ s->vdsp.emulated_edge_mc(lc->edge_emu_buffer2, src2 - offset1, ++ edge_emu_stride, src2stride, ++ block_w + EPEL_EXTRA, block_h + EPEL_EXTRA, ++ x_off1 - EPEL_EXTRA_BEFORE, ++ y_off1 - EPEL_EXTRA_BEFORE, ++ pic_width, pic_height); ++ ++ src2 = lc->edge_emu_buffer2 + buf_offset1; ++ src2stride = edge_emu_stride; ++ } ++ ++ s->hevcdsp.put_hevc_epel[idx][!!my0][!!mx0](lc->tmp, src1, src1stride, ++ block_h, _mx0, _my0, block_w); ++ if (!weight_flag) ++ s->hevcdsp.put_hevc_epel_bi[idx][!!my1][!!mx1](dst0, s->frame->linesize[cidx+1], ++ src2, src2stride, lc->tmp, ++ block_h, _mx1, _my1, block_w); ++ else ++ s->hevcdsp.put_hevc_epel_bi_w[idx][!!my1][!!mx1](dst0, s->frame->linesize[cidx+1], ++ src2, src2stride, lc->tmp, ++ block_h, ++ s->sh.chroma_log2_weight_denom, ++ s->sh.chroma_weight_l0[current_mv->ref_idx[0]][cidx], ++ s->sh.chroma_weight_l1[current_mv->ref_idx[1]][cidx], ++ s->sh.chroma_offset_l0[current_mv->ref_idx[0]][cidx], ++ s->sh.chroma_offset_l1[current_mv->ref_idx[1]][cidx], ++ _mx1, _my1, block_w); ++} ++ ++static void hevc_await_progress(HEVCContext *s, HEVCFrame *ref, ++ const Mv *mv, int y0, int height) ++{ ++ if (s->threads_type == FF_THREAD_FRAME ) { ++ int y = FFMAX(0, (mv->y >> 2) + y0 + height + 9); ++ ++ ff_thread_await_progress(&ref->tf, y, 0); ++ } ++} ++ ++static void hevc_luma_mv_mvp_mode(HEVCContext *s, int x0, int y0, int nPbW, ++ int nPbH, int log2_cb_size, int part_idx, ++ int merge_idx, MvField *mv) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ enum InterPredIdc inter_pred_idc = PRED_L0; ++ int mvp_flag; ++ ++ ff_hevc_set_neighbour_available(s, x0, y0, nPbW, nPbH); ++ mv->pred_flag = 0; ++ if (s->sh.slice_type == HEVC_SLICE_B) ++ inter_pred_idc = ff_hevc_inter_pred_idc_decode(s, nPbW, nPbH); ++ ++ if (inter_pred_idc != PRED_L1) { ++ if (s->sh.nb_refs[L0]) ++ mv->ref_idx[0]= ff_hevc_ref_idx_lx_decode(s, s->sh.nb_refs[L0]); ++ ++ mv->pred_flag = PF_L0; ++ ff_hevc_hls_mvd_coding(s, x0, y0, 0); ++ mvp_flag = ff_hevc_mvp_lx_flag_decode(s); ++ ff_hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size, ++ part_idx, merge_idx, mv, mvp_flag, 0); ++ mv->mv[0].x += lc->pu.mvd.x; ++ mv->mv[0].y += lc->pu.mvd.y; ++ } ++ ++ if (inter_pred_idc != PRED_L0) { ++ if (s->sh.nb_refs[L1]) ++ mv->ref_idx[1]= ff_hevc_ref_idx_lx_decode(s, s->sh.nb_refs[L1]); ++ ++ if (s->sh.mvd_l1_zero_flag == 1 && inter_pred_idc == PRED_BI) { ++ AV_ZERO32(&lc->pu.mvd); ++ } else { ++ ff_hevc_hls_mvd_coding(s, x0, y0, 1); ++ } ++ ++ mv->pred_flag += PF_L1; ++ mvp_flag = ff_hevc_mvp_lx_flag_decode(s); ++ ff_hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size, ++ part_idx, merge_idx, mv, mvp_flag, 1); ++ mv->mv[1].x += lc->pu.mvd.x; ++ mv->mv[1].y += lc->pu.mvd.y; ++ } ++} ++ ++static void hls_prediction_unit(HEVCContext *s, int x0, int y0, ++ int nPbW, int nPbH, ++ int log2_cb_size, int partIdx, int idx) ++{ ++#define POS(c_idx, x, y) \ ++ &s->frame->data[c_idx][((y) >> s->ps.sps->vshift[c_idx]) * s->frame->linesize[c_idx] + \ ++ (((x) >> s->ps.sps->hshift[c_idx]) << s->ps.sps->pixel_shift)] ++ HEVCLocalContext *lc = s->HEVClc; ++ int merge_idx = 0; ++ struct MvField current_mv = {{{ 0 }}}; ++ ++ int min_pu_width = s->ps.sps->min_pu_width; ++ ++ MvField *tab_mvf = s->ref->tab_mvf; ++ RefPicList *refPicList = s->ref->refPicList; ++ HEVCFrame *ref0 = NULL, *ref1 = NULL; ++ uint8_t *dst0 = POS(0, x0, y0); ++ uint8_t *dst1 = POS(1, x0, y0); ++ uint8_t *dst2 = POS(2, x0, y0); ++ int log2_min_cb_size = s->ps.sps->log2_min_cb_size; ++ int min_cb_width = s->ps.sps->min_cb_width; ++ int x_cb = x0 >> log2_min_cb_size; ++ int y_cb = y0 >> log2_min_cb_size; ++ int x_pu, y_pu; ++ int i, j; ++ ++ int skip_flag = SAMPLE_CTB(s->skip_flag, x_cb, y_cb); ++ ++ if (!skip_flag) ++ lc->pu.merge_flag = ff_hevc_merge_flag_decode(s); ++ ++ if (skip_flag || lc->pu.merge_flag) { ++ if (s->sh.max_num_merge_cand > 1) ++ merge_idx = ff_hevc_merge_idx_decode(s); ++ else ++ merge_idx = 0; ++ ++ ff_hevc_luma_mv_merge_mode(s, x0, y0, nPbW, nPbH, log2_cb_size, ++ partIdx, merge_idx, ¤t_mv); ++ } else { ++ hevc_luma_mv_mvp_mode(s, x0, y0, nPbW, nPbH, log2_cb_size, ++ partIdx, merge_idx, ¤t_mv); ++ } ++ ++ x_pu = x0 >> s->ps.sps->log2_min_pu_size; ++ y_pu = y0 >> s->ps.sps->log2_min_pu_size; ++ ++ for (j = 0; j < nPbH >> s->ps.sps->log2_min_pu_size; j++) ++ for (i = 0; i < nPbW >> s->ps.sps->log2_min_pu_size; i++) ++ tab_mvf[(y_pu + j) * min_pu_width + x_pu + i] = current_mv; ++ ++ if (current_mv.pred_flag & PF_L0) { ++ ref0 = refPicList[0].ref[current_mv.ref_idx[0]]; ++ if (!ref0) ++ return; ++ hevc_await_progress(s, ref0, ¤t_mv.mv[0], y0, nPbH); ++ } ++ if (current_mv.pred_flag & PF_L1) { ++ ref1 = refPicList[1].ref[current_mv.ref_idx[1]]; ++ if (!ref1) ++ return; ++ hevc_await_progress(s, ref1, ¤t_mv.mv[1], y0, nPbH); ++ } ++ ++ if (current_mv.pred_flag == PF_L0) { ++ int x0_c = x0 >> s->ps.sps->hshift[1]; ++ int y0_c = y0 >> s->ps.sps->vshift[1]; ++ int nPbW_c = nPbW >> s->ps.sps->hshift[1]; ++ int nPbH_c = nPbH >> s->ps.sps->vshift[1]; ++ ++ luma_mc_uni(s, dst0, s->frame->linesize[0], ref0->frame, ++ ¤t_mv.mv[0], x0, y0, nPbW, nPbH, ++ s->sh.luma_weight_l0[current_mv.ref_idx[0]], ++ s->sh.luma_offset_l0[current_mv.ref_idx[0]]); ++ ++ if (s->ps.sps->chroma_format_idc) { ++ chroma_mc_uni(s, dst1, s->frame->linesize[1], ref0->frame->data[1], ref0->frame->linesize[1], ++ 0, x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, ++ s->sh.chroma_weight_l0[current_mv.ref_idx[0]][0], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][0]); ++ chroma_mc_uni(s, dst2, s->frame->linesize[2], ref0->frame->data[2], ref0->frame->linesize[2], ++ 0, x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, ++ s->sh.chroma_weight_l0[current_mv.ref_idx[0]][1], s->sh.chroma_offset_l0[current_mv.ref_idx[0]][1]); ++ } ++ } else if (current_mv.pred_flag == PF_L1) { ++ int x0_c = x0 >> s->ps.sps->hshift[1]; ++ int y0_c = y0 >> s->ps.sps->vshift[1]; ++ int nPbW_c = nPbW >> s->ps.sps->hshift[1]; ++ int nPbH_c = nPbH >> s->ps.sps->vshift[1]; ++ ++ luma_mc_uni(s, dst0, s->frame->linesize[0], ref1->frame, ++ ¤t_mv.mv[1], x0, y0, nPbW, nPbH, ++ s->sh.luma_weight_l1[current_mv.ref_idx[1]], ++ s->sh.luma_offset_l1[current_mv.ref_idx[1]]); ++ ++ if (s->ps.sps->chroma_format_idc) { ++ chroma_mc_uni(s, dst1, s->frame->linesize[1], ref1->frame->data[1], ref1->frame->linesize[1], ++ 1, x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, ++ s->sh.chroma_weight_l1[current_mv.ref_idx[1]][0], s->sh.chroma_offset_l1[current_mv.ref_idx[1]][0]); ++ ++ chroma_mc_uni(s, dst2, s->frame->linesize[2], ref1->frame->data[2], ref1->frame->linesize[2], ++ 1, x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, ++ s->sh.chroma_weight_l1[current_mv.ref_idx[1]][1], s->sh.chroma_offset_l1[current_mv.ref_idx[1]][1]); ++ } ++ } else if (current_mv.pred_flag == PF_BI) { ++ int x0_c = x0 >> s->ps.sps->hshift[1]; ++ int y0_c = y0 >> s->ps.sps->vshift[1]; ++ int nPbW_c = nPbW >> s->ps.sps->hshift[1]; ++ int nPbH_c = nPbH >> s->ps.sps->vshift[1]; ++ ++ luma_mc_bi(s, dst0, s->frame->linesize[0], ref0->frame, ++ ¤t_mv.mv[0], x0, y0, nPbW, nPbH, ++ ref1->frame, ¤t_mv.mv[1], ¤t_mv); ++ ++ if (s->ps.sps->chroma_format_idc) { ++ chroma_mc_bi(s, dst1, s->frame->linesize[1], ref0->frame, ref1->frame, ++ x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, 0); ++ ++ chroma_mc_bi(s, dst2, s->frame->linesize[2], ref0->frame, ref1->frame, ++ x0_c, y0_c, nPbW_c, nPbH_c, ¤t_mv, 1); ++ } ++ } ++} ++ ++/** ++ * 8.4.1 ++ */ ++static int luma_intra_pred_mode(HEVCContext *s, int x0, int y0, int pu_size, ++ int prev_intra_luma_pred_flag) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ int x_pu = x0 >> s->ps.sps->log2_min_pu_size; ++ int y_pu = y0 >> s->ps.sps->log2_min_pu_size; ++ int min_pu_width = s->ps.sps->min_pu_width; ++ int size_in_pus = pu_size >> s->ps.sps->log2_min_pu_size; ++ int x0b = av_mod_uintp2(x0, s->ps.sps->log2_ctb_size); ++ int y0b = av_mod_uintp2(y0, s->ps.sps->log2_ctb_size); ++ ++ int cand_up = (lc->ctb_up_flag || y0b) ? ++ s->tab_ipm[(y_pu - 1) * min_pu_width + x_pu] : INTRA_DC; ++ int cand_left = (lc->ctb_left_flag || x0b) ? ++ s->tab_ipm[y_pu * min_pu_width + x_pu - 1] : INTRA_DC; ++ ++ int y_ctb = (y0 >> (s->ps.sps->log2_ctb_size)) << (s->ps.sps->log2_ctb_size); ++ ++ MvField *tab_mvf = s->ref->tab_mvf; ++ int intra_pred_mode; ++ int candidate[3]; ++ int i, j; ++ ++ // intra_pred_mode prediction does not cross vertical CTB boundaries ++ if ((y0 - 1) < y_ctb) ++ cand_up = INTRA_DC; ++ ++ if (cand_left == cand_up) { ++ if (cand_left < 2) { ++ candidate[0] = INTRA_PLANAR; ++ candidate[1] = INTRA_DC; ++ candidate[2] = INTRA_ANGULAR_26; ++ } else { ++ candidate[0] = cand_left; ++ candidate[1] = 2 + ((cand_left - 2 - 1 + 32) & 31); ++ candidate[2] = 2 + ((cand_left - 2 + 1) & 31); ++ } ++ } else { ++ candidate[0] = cand_left; ++ candidate[1] = cand_up; ++ if (candidate[0] != INTRA_PLANAR && candidate[1] != INTRA_PLANAR) { ++ candidate[2] = INTRA_PLANAR; ++ } else if (candidate[0] != INTRA_DC && candidate[1] != INTRA_DC) { ++ candidate[2] = INTRA_DC; ++ } else { ++ candidate[2] = INTRA_ANGULAR_26; ++ } ++ } ++ ++ if (prev_intra_luma_pred_flag) { ++ intra_pred_mode = candidate[lc->pu.mpm_idx]; ++ } else { ++ if (candidate[0] > candidate[1]) ++ FFSWAP(uint8_t, candidate[0], candidate[1]); ++ if (candidate[0] > candidate[2]) ++ FFSWAP(uint8_t, candidate[0], candidate[2]); ++ if (candidate[1] > candidate[2]) ++ FFSWAP(uint8_t, candidate[1], candidate[2]); ++ ++ intra_pred_mode = lc->pu.rem_intra_luma_pred_mode; ++ for (i = 0; i < 3; i++) ++ if (intra_pred_mode >= candidate[i]) ++ intra_pred_mode++; ++ } ++ ++ /* write the intra prediction units into the mv array */ ++ if (!size_in_pus) ++ size_in_pus = 1; ++ for (i = 0; i < size_in_pus; i++) { ++ memset(&s->tab_ipm[(y_pu + i) * min_pu_width + x_pu], ++ intra_pred_mode, size_in_pus); ++ ++ for (j = 0; j < size_in_pus; j++) { ++ tab_mvf[(y_pu + j) * min_pu_width + x_pu + i].pred_flag = PF_INTRA; ++ } ++ } ++ ++ return intra_pred_mode; ++} ++ ++static av_always_inline void set_ct_depth(HEVCContext *s, int x0, int y0, ++ int log2_cb_size, int ct_depth) ++{ ++ int length = (1 << log2_cb_size) >> s->ps.sps->log2_min_cb_size; ++ int x_cb = x0 >> s->ps.sps->log2_min_cb_size; ++ int y_cb = y0 >> s->ps.sps->log2_min_cb_size; ++ int y; ++ ++ for (y = 0; y < length; y++) ++ memset(&s->tab_ct_depth[(y_cb + y) * s->ps.sps->min_cb_width + x_cb], ++ ct_depth, length); ++} ++ ++static const uint8_t tab_mode_idx[] = { ++ 0, 1, 2, 2, 2, 2, 3, 5, 7, 8, 10, 12, 13, 15, 17, 18, 19, 20, ++ 21, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 28, 28, 29, 29, 30, 31}; ++ ++static void intra_prediction_unit(HEVCContext *s, int x0, int y0, ++ int log2_cb_size) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ static const uint8_t intra_chroma_table[4] = { 0, 26, 10, 1 }; ++ uint8_t prev_intra_luma_pred_flag[4]; ++ int split = lc->cu.part_mode == PART_NxN; ++ int pb_size = (1 << log2_cb_size) >> split; ++ int side = split + 1; ++ int chroma_mode; ++ int i, j; ++ ++ for (i = 0; i < side; i++) ++ for (j = 0; j < side; j++) ++ prev_intra_luma_pred_flag[2 * i + j] = ff_hevc_prev_intra_luma_pred_flag_decode(s); ++ ++ for (i = 0; i < side; i++) { ++ for (j = 0; j < side; j++) { ++ if (prev_intra_luma_pred_flag[2 * i + j]) ++ lc->pu.mpm_idx = ff_hevc_mpm_idx_decode(s); ++ else ++ lc->pu.rem_intra_luma_pred_mode = ff_hevc_rem_intra_luma_pred_mode_decode(s); ++ ++ lc->pu.intra_pred_mode[2 * i + j] = ++ luma_intra_pred_mode(s, x0 + pb_size * j, y0 + pb_size * i, pb_size, ++ prev_intra_luma_pred_flag[2 * i + j]); ++ } ++ } ++ ++ if (s->ps.sps->chroma_format_idc == 3) { ++ for (i = 0; i < side; i++) { ++ for (j = 0; j < side; j++) { ++ lc->pu.chroma_mode_c[2 * i + j] = chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(s); ++ if (chroma_mode != 4) { ++ if (lc->pu.intra_pred_mode[2 * i + j] == intra_chroma_table[chroma_mode]) ++ lc->pu.intra_pred_mode_c[2 * i + j] = 34; ++ else ++ lc->pu.intra_pred_mode_c[2 * i + j] = intra_chroma_table[chroma_mode]; ++ } else { ++ lc->pu.intra_pred_mode_c[2 * i + j] = lc->pu.intra_pred_mode[2 * i + j]; ++ } ++ } ++ } ++ } else if (s->ps.sps->chroma_format_idc == 2) { ++ int mode_idx; ++ lc->pu.chroma_mode_c[0] = chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(s); ++ if (chroma_mode != 4) { ++ if (lc->pu.intra_pred_mode[0] == intra_chroma_table[chroma_mode]) ++ mode_idx = 34; ++ else ++ mode_idx = intra_chroma_table[chroma_mode]; ++ } else { ++ mode_idx = lc->pu.intra_pred_mode[0]; ++ } ++ lc->pu.intra_pred_mode_c[0] = tab_mode_idx[mode_idx]; ++ } else if (s->ps.sps->chroma_format_idc != 0) { ++ chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(s); ++ if (chroma_mode != 4) { ++ if (lc->pu.intra_pred_mode[0] == intra_chroma_table[chroma_mode]) ++ lc->pu.intra_pred_mode_c[0] = 34; ++ else ++ lc->pu.intra_pred_mode_c[0] = intra_chroma_table[chroma_mode]; ++ } else { ++ lc->pu.intra_pred_mode_c[0] = lc->pu.intra_pred_mode[0]; ++ } ++ } ++} ++ ++static void intra_prediction_unit_default_value(HEVCContext *s, ++ int x0, int y0, ++ int log2_cb_size) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ int pb_size = 1 << log2_cb_size; ++ int size_in_pus = pb_size >> s->ps.sps->log2_min_pu_size; ++ int min_pu_width = s->ps.sps->min_pu_width; ++ MvField *tab_mvf = s->ref->tab_mvf; ++ int x_pu = x0 >> s->ps.sps->log2_min_pu_size; ++ int y_pu = y0 >> s->ps.sps->log2_min_pu_size; ++ int j, k; ++ ++ if (size_in_pus == 0) ++ size_in_pus = 1; ++ for (j = 0; j < size_in_pus; j++) ++ memset(&s->tab_ipm[(y_pu + j) * min_pu_width + x_pu], INTRA_DC, size_in_pus); ++ if (lc->cu.pred_mode == MODE_INTRA) ++ for (j = 0; j < size_in_pus; j++) ++ for (k = 0; k < size_in_pus; k++) ++ tab_mvf[(y_pu + j) * min_pu_width + x_pu + k].pred_flag = PF_INTRA; ++} ++ ++static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) ++{ ++ int cb_size = 1 << log2_cb_size; ++ HEVCLocalContext *lc = s->HEVClc; ++ int log2_min_cb_size = s->ps.sps->log2_min_cb_size; ++ int length = cb_size >> log2_min_cb_size; ++ int min_cb_width = s->ps.sps->min_cb_width; ++ int x_cb = x0 >> log2_min_cb_size; ++ int y_cb = y0 >> log2_min_cb_size; ++ int idx = log2_cb_size - 2; ++ int qp_block_mask = (1<<(s->ps.sps->log2_ctb_size - s->ps.pps->diff_cu_qp_delta_depth)) - 1; ++ int x, y, ret; ++ ++ lc->cu.x = x0; ++ lc->cu.y = y0; ++ lc->cu.pred_mode = MODE_INTRA; ++ lc->cu.part_mode = PART_2Nx2N; ++ lc->cu.intra_split_flag = 0; ++ ++ SAMPLE_CTB(s->skip_flag, x_cb, y_cb) = 0; ++ for (x = 0; x < 4; x++) ++ lc->pu.intra_pred_mode[x] = 1; ++ if (s->ps.pps->transquant_bypass_enable_flag) { ++ lc->cu.cu_transquant_bypass_flag = ff_hevc_cu_transquant_bypass_flag_decode(s); ++ if (lc->cu.cu_transquant_bypass_flag) ++ set_deblocking_bypass(s, x0, y0, log2_cb_size); ++ } else ++ lc->cu.cu_transquant_bypass_flag = 0; ++ ++ if (s->sh.slice_type != HEVC_SLICE_I) { ++ uint8_t skip_flag = ff_hevc_skip_flag_decode(s, x0, y0, x_cb, y_cb); ++ ++ x = y_cb * min_cb_width + x_cb; ++ for (y = 0; y < length; y++) { ++ memset(&s->skip_flag[x], skip_flag, length); ++ x += min_cb_width; ++ } ++ lc->cu.pred_mode = skip_flag ? MODE_SKIP : MODE_INTER; ++ } else { ++ x = y_cb * min_cb_width + x_cb; ++ for (y = 0; y < length; y++) { ++ memset(&s->skip_flag[x], 0, length); ++ x += min_cb_width; ++ } ++ } ++ ++ if (SAMPLE_CTB(s->skip_flag, x_cb, y_cb)) { ++ hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0, idx); ++ intra_prediction_unit_default_value(s, x0, y0, log2_cb_size); ++ ++ if (!s->sh.disable_deblocking_filter_flag) ++ ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size); ++ } else { ++ int pcm_flag = 0; ++ ++ if (s->sh.slice_type != HEVC_SLICE_I) ++ lc->cu.pred_mode = ff_hevc_pred_mode_decode(s); ++ if (lc->cu.pred_mode != MODE_INTRA || ++ log2_cb_size == s->ps.sps->log2_min_cb_size) { ++ lc->cu.part_mode = ff_hevc_part_mode_decode(s, log2_cb_size); ++ lc->cu.intra_split_flag = lc->cu.part_mode == PART_NxN && ++ lc->cu.pred_mode == MODE_INTRA; ++ } ++ ++ if (lc->cu.pred_mode == MODE_INTRA) { ++ if (lc->cu.part_mode == PART_2Nx2N && s->ps.sps->pcm_enabled_flag && ++ log2_cb_size >= s->ps.sps->pcm.log2_min_pcm_cb_size && ++ log2_cb_size <= s->ps.sps->pcm.log2_max_pcm_cb_size) { ++ pcm_flag = ff_hevc_pcm_flag_decode(s); ++ } ++ if (pcm_flag) { ++ intra_prediction_unit_default_value(s, x0, y0, log2_cb_size); ++ ret = hls_pcm_sample(s, x0, y0, log2_cb_size); ++ if (s->ps.sps->pcm.loop_filter_disable_flag) ++ set_deblocking_bypass(s, x0, y0, log2_cb_size); ++ ++ if (ret < 0) ++ return ret; ++ } else { ++ intra_prediction_unit(s, x0, y0, log2_cb_size); ++ } ++ } else { ++ intra_prediction_unit_default_value(s, x0, y0, log2_cb_size); ++ switch (lc->cu.part_mode) { ++ case PART_2Nx2N: ++ hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0, idx); ++ break; ++ case PART_2NxN: ++ hls_prediction_unit(s, x0, y0, cb_size, cb_size / 2, log2_cb_size, 0, idx); ++ hls_prediction_unit(s, x0, y0 + cb_size / 2, cb_size, cb_size / 2, log2_cb_size, 1, idx); ++ break; ++ case PART_Nx2N: ++ hls_prediction_unit(s, x0, y0, cb_size / 2, cb_size, log2_cb_size, 0, idx - 1); ++ hls_prediction_unit(s, x0 + cb_size / 2, y0, cb_size / 2, cb_size, log2_cb_size, 1, idx - 1); ++ break; ++ case PART_2NxnU: ++ hls_prediction_unit(s, x0, y0, cb_size, cb_size / 4, log2_cb_size, 0, idx); ++ hls_prediction_unit(s, x0, y0 + cb_size / 4, cb_size, cb_size * 3 / 4, log2_cb_size, 1, idx); ++ break; ++ case PART_2NxnD: ++ hls_prediction_unit(s, x0, y0, cb_size, cb_size * 3 / 4, log2_cb_size, 0, idx); ++ hls_prediction_unit(s, x0, y0 + cb_size * 3 / 4, cb_size, cb_size / 4, log2_cb_size, 1, idx); ++ break; ++ case PART_nLx2N: ++ hls_prediction_unit(s, x0, y0, cb_size / 4, cb_size, log2_cb_size, 0, idx - 2); ++ hls_prediction_unit(s, x0 + cb_size / 4, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 1, idx - 2); ++ break; ++ case PART_nRx2N: ++ hls_prediction_unit(s, x0, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 0, idx - 2); ++ hls_prediction_unit(s, x0 + cb_size * 3 / 4, y0, cb_size / 4, cb_size, log2_cb_size, 1, idx - 2); ++ break; ++ case PART_NxN: ++ hls_prediction_unit(s, x0, y0, cb_size / 2, cb_size / 2, log2_cb_size, 0, idx - 1); ++ hls_prediction_unit(s, x0 + cb_size / 2, y0, cb_size / 2, cb_size / 2, log2_cb_size, 1, idx - 1); ++ hls_prediction_unit(s, x0, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 2, idx - 1); ++ hls_prediction_unit(s, x0 + cb_size / 2, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 3, idx - 1); ++ break; ++ } ++ } ++ ++ if (!pcm_flag) { ++ int rqt_root_cbf = 1; ++ ++ if (lc->cu.pred_mode != MODE_INTRA && ++ !(lc->cu.part_mode == PART_2Nx2N && lc->pu.merge_flag)) { ++ rqt_root_cbf = ff_hevc_no_residual_syntax_flag_decode(s); ++ } ++ if (rqt_root_cbf) { ++ const static int cbf[2] = { 0 }; ++ lc->cu.max_trafo_depth = lc->cu.pred_mode == MODE_INTRA ? ++ s->ps.sps->max_transform_hierarchy_depth_intra + lc->cu.intra_split_flag : ++ s->ps.sps->max_transform_hierarchy_depth_inter; ++ ret = hls_transform_tree(s, x0, y0, x0, y0, x0, y0, ++ log2_cb_size, ++ log2_cb_size, 0, 0, cbf, cbf); ++ if (ret < 0) ++ return ret; ++ } else { ++ if (!s->sh.disable_deblocking_filter_flag) ++ ff_hevc_deblocking_boundary_strengths(s, x0, y0, log2_cb_size); ++ } ++ } ++ } ++ ++ if (s->ps.pps->cu_qp_delta_enabled_flag && lc->tu.is_cu_qp_delta_coded == 0) ++ ff_hevc_set_qPy(s, x0, y0, log2_cb_size); ++ ++ x = y_cb * min_cb_width + x_cb; ++ for (y = 0; y < length; y++) { ++ memset(&s->qp_y_tab[x], lc->qp_y, length); ++ x += min_cb_width; ++ } ++ ++ if(((x0 + (1<qPy_pred = lc->qp_y; ++ } ++ ++ set_ct_depth(s, x0, y0, log2_cb_size, lc->ct_depth); ++ ++ return 0; ++} ++ ++static int hls_coding_quadtree(HEVCContext *s, int x0, int y0, ++ int log2_cb_size, int cb_depth) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ const int cb_size = 1 << log2_cb_size; ++ int ret; ++ int split_cu; ++ ++ lc->ct_depth = cb_depth; ++ if (x0 + cb_size <= s->ps.sps->width && ++ y0 + cb_size <= s->ps.sps->height && ++ log2_cb_size > s->ps.sps->log2_min_cb_size) { ++ split_cu = ff_hevc_split_coding_unit_flag_decode(s, cb_depth, x0, y0); ++ } else { ++ split_cu = (log2_cb_size > s->ps.sps->log2_min_cb_size); ++ } ++ if (s->ps.pps->cu_qp_delta_enabled_flag && ++ log2_cb_size >= s->ps.sps->log2_ctb_size - s->ps.pps->diff_cu_qp_delta_depth) { ++ lc->tu.is_cu_qp_delta_coded = 0; ++ lc->tu.cu_qp_delta = 0; ++ } ++ ++ if (s->sh.cu_chroma_qp_offset_enabled_flag && ++ log2_cb_size >= s->ps.sps->log2_ctb_size - s->ps.pps->diff_cu_chroma_qp_offset_depth) { ++ lc->tu.is_cu_chroma_qp_offset_coded = 0; ++ } ++ ++ if (split_cu) { ++ int qp_block_mask = (1<<(s->ps.sps->log2_ctb_size - s->ps.pps->diff_cu_qp_delta_depth)) - 1; ++ const int cb_size_split = cb_size >> 1; ++ const int x1 = x0 + cb_size_split; ++ const int y1 = y0 + cb_size_split; ++ ++ int more_data = 0; ++ ++ more_data = hls_coding_quadtree(s, x0, y0, log2_cb_size - 1, cb_depth + 1); ++ if (more_data < 0) ++ return more_data; ++ ++ if (more_data && x1 < s->ps.sps->width) { ++ more_data = hls_coding_quadtree(s, x1, y0, log2_cb_size - 1, cb_depth + 1); ++ if (more_data < 0) ++ return more_data; ++ } ++ if (more_data && y1 < s->ps.sps->height) { ++ more_data = hls_coding_quadtree(s, x0, y1, log2_cb_size - 1, cb_depth + 1); ++ if (more_data < 0) ++ return more_data; ++ } ++ if (more_data && x1 < s->ps.sps->width && ++ y1 < s->ps.sps->height) { ++ more_data = hls_coding_quadtree(s, x1, y1, log2_cb_size - 1, cb_depth + 1); ++ if (more_data < 0) ++ return more_data; ++ } ++ ++ if(((x0 + (1<qPy_pred = lc->qp_y; ++ ++ if (more_data) ++ return ((x1 + cb_size_split) < s->ps.sps->width || ++ (y1 + cb_size_split) < s->ps.sps->height); ++ else ++ return 0; ++ } else { ++ ret = hls_coding_unit(s, x0, y0, log2_cb_size); ++ if (ret < 0) ++ return ret; ++ if ((!((x0 + cb_size) % ++ (1 << (s->ps.sps->log2_ctb_size))) || ++ (x0 + cb_size >= s->ps.sps->width)) && ++ (!((y0 + cb_size) % ++ (1 << (s->ps.sps->log2_ctb_size))) || ++ (y0 + cb_size >= s->ps.sps->height))) { ++ int end_of_slice_flag = ff_hevc_end_of_slice_flag_decode(s); ++ return !end_of_slice_flag; ++ } else { ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++static void hls_decode_neighbour(HEVCContext *s, int x_ctb, int y_ctb, ++ int ctb_addr_ts) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ int ctb_size = 1 << s->ps.sps->log2_ctb_size; ++ int ctb_addr_rs = s->ps.pps->ctb_addr_ts_to_rs[ctb_addr_ts]; ++ int ctb_addr_in_slice = ctb_addr_rs - s->sh.slice_addr; ++ ++ s->tab_slice_address[ctb_addr_rs] = s->sh.slice_addr; ++ ++ if (s->ps.pps->entropy_coding_sync_enabled_flag) { ++ if (x_ctb == 0 && (y_ctb & (ctb_size - 1)) == 0) ++ lc->first_qp_group = 1; ++ lc->end_of_tiles_x = s->ps.sps->width; ++ } else if (s->ps.pps->tiles_enabled_flag) { ++ if (ctb_addr_ts && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[ctb_addr_ts - 1]) { ++ int idxX = s->ps.pps->col_idxX[x_ctb >> s->ps.sps->log2_ctb_size]; ++ lc->end_of_tiles_x = x_ctb + (s->ps.pps->column_width[idxX] << s->ps.sps->log2_ctb_size); ++ lc->first_qp_group = 1; ++ } ++ } else { ++ lc->end_of_tiles_x = s->ps.sps->width; ++ } ++ ++ lc->end_of_tiles_y = FFMIN(y_ctb + ctb_size, s->ps.sps->height); ++ ++ lc->boundary_flags = 0; ++ if (s->ps.pps->tiles_enabled_flag) { ++ if (x_ctb > 0 && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs - 1]]) ++ lc->boundary_flags |= BOUNDARY_LEFT_TILE; ++ if (x_ctb > 0 && s->tab_slice_address[ctb_addr_rs] != s->tab_slice_address[ctb_addr_rs - 1]) ++ lc->boundary_flags |= BOUNDARY_LEFT_SLICE; ++ if (y_ctb > 0 && s->ps.pps->tile_id[ctb_addr_ts] != s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs - s->ps.sps->ctb_width]]) ++ lc->boundary_flags |= BOUNDARY_UPPER_TILE; ++ if (y_ctb > 0 && s->tab_slice_address[ctb_addr_rs] != s->tab_slice_address[ctb_addr_rs - s->ps.sps->ctb_width]) ++ lc->boundary_flags |= BOUNDARY_UPPER_SLICE; ++ } else { ++ if (ctb_addr_in_slice <= 0) ++ lc->boundary_flags |= BOUNDARY_LEFT_SLICE; ++ if (ctb_addr_in_slice < s->ps.sps->ctb_width) ++ lc->boundary_flags |= BOUNDARY_UPPER_SLICE; ++ } ++ ++ lc->ctb_left_flag = ((x_ctb > 0) && (ctb_addr_in_slice > 0) && !(lc->boundary_flags & BOUNDARY_LEFT_TILE)); ++ lc->ctb_up_flag = ((y_ctb > 0) && (ctb_addr_in_slice >= s->ps.sps->ctb_width) && !(lc->boundary_flags & BOUNDARY_UPPER_TILE)); ++ lc->ctb_up_right_flag = ((y_ctb > 0) && (ctb_addr_in_slice+1 >= s->ps.sps->ctb_width) && (s->ps.pps->tile_id[ctb_addr_ts] == s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs+1 - s->ps.sps->ctb_width]])); ++ lc->ctb_up_left_flag = ((x_ctb > 0) && (y_ctb > 0) && (ctb_addr_in_slice-1 >= s->ps.sps->ctb_width) && (s->ps.pps->tile_id[ctb_addr_ts] == s->ps.pps->tile_id[s->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs-1 - s->ps.sps->ctb_width]])); ++} ++ ++static int hls_decode_entry(AVCodecContext *avctxt, void *isFilterThread) ++{ ++ HEVCContext *s = avctxt->priv_data; ++ int ctb_size = 1 << s->ps.sps->log2_ctb_size; ++ int more_data = 1; ++ int x_ctb = 0; ++ int y_ctb = 0; ++ int ctb_addr_ts = s->ps.pps->ctb_addr_rs_to_ts[s->sh.slice_ctb_addr_rs]; ++ int ret; ++ ++ if (!ctb_addr_ts && s->sh.dependent_slice_segment_flag) { ++ av_log(s->avctx, AV_LOG_ERROR, "Impossible initial tile.\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (s->sh.dependent_slice_segment_flag) { ++ int prev_rs = s->ps.pps->ctb_addr_ts_to_rs[ctb_addr_ts - 1]; ++ if (s->tab_slice_address[prev_rs] != s->sh.slice_addr) { ++ av_log(s->avctx, AV_LOG_ERROR, "Previous slice segment missing\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ } ++ ++ while (more_data && ctb_addr_ts < s->ps.sps->ctb_size) { ++ int ctb_addr_rs = s->ps.pps->ctb_addr_ts_to_rs[ctb_addr_ts]; ++ ++ x_ctb = (ctb_addr_rs % ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size)) << s->ps.sps->log2_ctb_size; ++ y_ctb = (ctb_addr_rs / ((s->ps.sps->width + ctb_size - 1) >> s->ps.sps->log2_ctb_size)) << s->ps.sps->log2_ctb_size; ++ hls_decode_neighbour(s, x_ctb, y_ctb, ctb_addr_ts); ++ ++ ret = ff_hevc_cabac_init(s, ctb_addr_ts); ++ if (ret < 0) { ++ s->tab_slice_address[ctb_addr_rs] = -1; ++ return ret; ++ } ++ ++ hls_sao_param(s, x_ctb >> s->ps.sps->log2_ctb_size, y_ctb >> s->ps.sps->log2_ctb_size); ++ ++ s->deblock[ctb_addr_rs].beta_offset = s->sh.beta_offset; ++ s->deblock[ctb_addr_rs].tc_offset = s->sh.tc_offset; ++ s->filter_slice_edges[ctb_addr_rs] = s->sh.slice_loop_filter_across_slices_enabled_flag; ++ ++ more_data = hls_coding_quadtree(s, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0); ++ if (more_data < 0) { ++ s->tab_slice_address[ctb_addr_rs] = -1; ++ return more_data; ++ } ++ ++ ++ ctb_addr_ts++; ++ ff_hevc_save_states(s, ctb_addr_ts); ++ ff_hevc_hls_filters(s, x_ctb, y_ctb, ctb_size); ++ } ++ ++ if (x_ctb + ctb_size >= s->ps.sps->width && ++ y_ctb + ctb_size >= s->ps.sps->height) ++ ff_hevc_hls_filter(s, x_ctb, y_ctb, ctb_size); ++ ++ return ctb_addr_ts; ++} ++ ++static int hls_slice_data(HEVCContext *s) ++{ ++ int arg[2]; ++ int ret[2]; ++ ++ arg[0] = 0; ++ arg[1] = 1; ++ ++ s->avctx->execute(s->avctx, hls_decode_entry, arg, ret , 1, sizeof(int)); ++ return ret[0]; ++} ++static int hls_decode_entry_wpp(AVCodecContext *avctxt, void *input_ctb_row, int job, int self_id) ++{ ++ HEVCContext *s1 = avctxt->priv_data, *s; ++ HEVCLocalContext *lc; ++ int ctb_size = 1<< s1->ps.sps->log2_ctb_size; ++ int more_data = 1; ++ int *ctb_row_p = input_ctb_row; ++ int ctb_row = ctb_row_p[job]; ++ int ctb_addr_rs = s1->sh.slice_ctb_addr_rs + ctb_row * ((s1->ps.sps->width + ctb_size - 1) >> s1->ps.sps->log2_ctb_size); ++ int ctb_addr_ts = s1->ps.pps->ctb_addr_rs_to_ts[ctb_addr_rs]; ++ int thread = ctb_row % s1->threads_number; ++ int ret; ++ ++ s = s1->sList[self_id]; ++ lc = s->HEVClc; ++ ++ if(ctb_row) { ++ ret = init_get_bits8(&lc->gb, s->data + s->sh.offset[ctb_row - 1], s->sh.size[ctb_row - 1]); ++ if (ret < 0) ++ goto error; ++ ff_init_cabac_decoder(&lc->cc, s->data + s->sh.offset[(ctb_row)-1], s->sh.size[ctb_row - 1]); ++ } ++ ++ while(more_data && ctb_addr_ts < s->ps.sps->ctb_size) { ++ int x_ctb = (ctb_addr_rs % s->ps.sps->ctb_width) << s->ps.sps->log2_ctb_size; ++ int y_ctb = (ctb_addr_rs / s->ps.sps->ctb_width) << s->ps.sps->log2_ctb_size; ++ ++ hls_decode_neighbour(s, x_ctb, y_ctb, ctb_addr_ts); ++ ++ ff_thread_await_progress2(s->avctx, ctb_row, thread, SHIFT_CTB_WPP); ++ ++ if (atomic_load(&s1->wpp_err)) { ++ ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP); ++ return 0; ++ } ++ ++ ret = ff_hevc_cabac_init(s, ctb_addr_ts); ++ if (ret < 0) ++ goto error; ++ hls_sao_param(s, x_ctb >> s->ps.sps->log2_ctb_size, y_ctb >> s->ps.sps->log2_ctb_size); ++ more_data = hls_coding_quadtree(s, x_ctb, y_ctb, s->ps.sps->log2_ctb_size, 0); ++ ++ if (more_data < 0) { ++ ret = more_data; ++ goto error; ++ } ++ ++ ctb_addr_ts++; ++ ++ ff_hevc_save_states(s, ctb_addr_ts); ++ ff_thread_report_progress2(s->avctx, ctb_row, thread, 1); ++ ff_hevc_hls_filters(s, x_ctb, y_ctb, ctb_size); ++ ++ if (!more_data && (x_ctb+ctb_size) < s->ps.sps->width && ctb_row != s->sh.num_entry_point_offsets) { ++ atomic_store(&s1->wpp_err, 1); ++ ff_thread_report_progress2(s->avctx, ctb_row ,thread, SHIFT_CTB_WPP); ++ return 0; ++ } ++ ++ if ((x_ctb+ctb_size) >= s->ps.sps->width && (y_ctb+ctb_size) >= s->ps.sps->height ) { ++ ff_hevc_hls_filter(s, x_ctb, y_ctb, ctb_size); ++ ff_thread_report_progress2(s->avctx, ctb_row , thread, SHIFT_CTB_WPP); ++ return ctb_addr_ts; ++ } ++ ctb_addr_rs = s->ps.pps->ctb_addr_ts_to_rs[ctb_addr_ts]; ++ x_ctb+=ctb_size; ++ ++ if(x_ctb >= s->ps.sps->width) { ++ break; ++ } ++ } ++ ff_thread_report_progress2(s->avctx, ctb_row ,thread, SHIFT_CTB_WPP); ++ ++ return 0; ++error: ++ s->tab_slice_address[ctb_addr_rs] = -1; ++ atomic_store(&s1->wpp_err, 1); ++ ff_thread_report_progress2(s->avctx, ctb_row ,thread, SHIFT_CTB_WPP); ++ return ret; ++} ++ ++static int hls_slice_data_wpp(HEVCContext *s, const H2645NAL *nal) ++{ ++ const uint8_t *data = nal->data; ++ int length = nal->size; ++ HEVCLocalContext *lc = s->HEVClc; ++ int *ret = av_malloc_array(s->sh.num_entry_point_offsets + 1, sizeof(int)); ++ int *arg = av_malloc_array(s->sh.num_entry_point_offsets + 1, sizeof(int)); ++ int64_t offset; ++ int64_t startheader, cmpt = 0; ++ int i, j, res = 0; ++ ++ if (!ret || !arg) { ++ av_free(ret); ++ av_free(arg); ++ return AVERROR(ENOMEM); ++ } ++ ++ if (s->sh.slice_ctb_addr_rs + s->sh.num_entry_point_offsets * s->ps.sps->ctb_width >= s->ps.sps->ctb_width * s->ps.sps->ctb_height) { ++ av_log(s->avctx, AV_LOG_ERROR, "WPP ctb addresses are wrong (%d %d %d %d)\n", ++ s->sh.slice_ctb_addr_rs, s->sh.num_entry_point_offsets, ++ s->ps.sps->ctb_width, s->ps.sps->ctb_height ++ ); ++ res = AVERROR_INVALIDDATA; ++ goto error; ++ } ++ ++ ff_alloc_entries(s->avctx, s->sh.num_entry_point_offsets + 1); ++ ++ if (!s->sList[1]) { ++ for (i = 1; i < s->threads_number; i++) { ++ s->sList[i] = av_malloc(sizeof(HEVCContext)); ++ memcpy(s->sList[i], s, sizeof(HEVCContext)); ++ s->HEVClcList[i] = av_mallocz(sizeof(HEVCLocalContext)); ++ s->sList[i]->HEVClc = s->HEVClcList[i]; ++ } ++ } ++ ++ offset = (lc->gb.index >> 3); ++ ++ for (j = 0, cmpt = 0, startheader = offset + s->sh.entry_point_offset[0]; j < nal->skipped_bytes; j++) { ++ if (nal->skipped_bytes_pos[j] >= offset && nal->skipped_bytes_pos[j] < startheader) { ++ startheader--; ++ cmpt++; ++ } ++ } ++ ++ for (i = 1; i < s->sh.num_entry_point_offsets; i++) { ++ offset += (s->sh.entry_point_offset[i - 1] - cmpt); ++ for (j = 0, cmpt = 0, startheader = offset ++ + s->sh.entry_point_offset[i]; j < nal->skipped_bytes; j++) { ++ if (nal->skipped_bytes_pos[j] >= offset && nal->skipped_bytes_pos[j] < startheader) { ++ startheader--; ++ cmpt++; ++ } ++ } ++ s->sh.size[i - 1] = s->sh.entry_point_offset[i] - cmpt; ++ s->sh.offset[i - 1] = offset; ++ ++ } ++ if (s->sh.num_entry_point_offsets != 0) { ++ offset += s->sh.entry_point_offset[s->sh.num_entry_point_offsets - 1] - cmpt; ++ if (length < offset) { ++ av_log(s->avctx, AV_LOG_ERROR, "entry_point_offset table is corrupted\n"); ++ res = AVERROR_INVALIDDATA; ++ goto error; ++ } ++ s->sh.size[s->sh.num_entry_point_offsets - 1] = length - offset; ++ s->sh.offset[s->sh.num_entry_point_offsets - 1] = offset; ++ ++ } ++ s->data = data; ++ ++ for (i = 1; i < s->threads_number; i++) { ++ s->sList[i]->HEVClc->first_qp_group = 1; ++ s->sList[i]->HEVClc->qp_y = s->sList[0]->HEVClc->qp_y; ++ memcpy(s->sList[i], s, sizeof(HEVCContext)); ++ s->sList[i]->HEVClc = s->HEVClcList[i]; ++ } ++ ++ atomic_store(&s->wpp_err, 0); ++ ff_reset_entries(s->avctx); ++ ++ for (i = 0; i <= s->sh.num_entry_point_offsets; i++) { ++ arg[i] = i; ++ ret[i] = 0; ++ } ++ ++ if (s->ps.pps->entropy_coding_sync_enabled_flag) ++ s->avctx->execute2(s->avctx, hls_decode_entry_wpp, arg, ret, s->sh.num_entry_point_offsets + 1); ++ ++ for (i = 0; i <= s->sh.num_entry_point_offsets; i++) ++ res += ret[i]; ++error: ++ av_free(ret); ++ av_free(arg); ++ return res; ++} ++ ++static int set_side_data(HEVCContext *s) ++{ ++ AVFrame *out = s->ref->frame; ++ ++ if (s->sei.frame_packing.present && ++ s->sei.frame_packing.arrangement_type >= 3 && ++ s->sei.frame_packing.arrangement_type <= 5 && ++ s->sei.frame_packing.content_interpretation_type > 0 && ++ s->sei.frame_packing.content_interpretation_type < 3) { ++ AVStereo3D *stereo = av_stereo3d_create_side_data(out); ++ if (!stereo) ++ return AVERROR(ENOMEM); ++ ++ switch (s->sei.frame_packing.arrangement_type) { ++ case 3: ++ if (s->sei.frame_packing.quincunx_subsampling) ++ stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX; ++ else ++ stereo->type = AV_STEREO3D_SIDEBYSIDE; ++ break; ++ case 4: ++ stereo->type = AV_STEREO3D_TOPBOTTOM; ++ break; ++ case 5: ++ stereo->type = AV_STEREO3D_FRAMESEQUENCE; ++ break; ++ } ++ ++ if (s->sei.frame_packing.content_interpretation_type == 2) ++ stereo->flags = AV_STEREO3D_FLAG_INVERT; ++ ++ if (s->sei.frame_packing.arrangement_type == 5) { ++ if (s->sei.frame_packing.current_frame_is_frame0_flag) ++ stereo->view = AV_STEREO3D_VIEW_LEFT; ++ else ++ stereo->view = AV_STEREO3D_VIEW_RIGHT; ++ } ++ } ++ ++ if (s->sei.display_orientation.present && ++ (s->sei.display_orientation.anticlockwise_rotation || ++ s->sei.display_orientation.hflip || s->sei.display_orientation.vflip)) { ++ double angle = s->sei.display_orientation.anticlockwise_rotation * 360 / (double) (1 << 16); ++ AVFrameSideData *rotation = av_frame_new_side_data(out, ++ AV_FRAME_DATA_DISPLAYMATRIX, ++ sizeof(int32_t) * 9); ++ if (!rotation) ++ return AVERROR(ENOMEM); ++ ++ av_display_rotation_set((int32_t *)rotation->data, angle); ++ av_display_matrix_flip((int32_t *)rotation->data, ++ s->sei.display_orientation.hflip, ++ s->sei.display_orientation.vflip); ++ } ++ ++ // Decrement the mastering display flag when IRAP frame has no_rasl_output_flag=1 ++ // so the side data persists for the entire coded video sequence. ++ if (s->sei.mastering_display.present > 0 && ++ IS_IRAP(s) && s->no_rasl_output_flag) { ++ s->sei.mastering_display.present--; ++ } ++ if (s->sei.mastering_display.present) { ++ // HEVC uses a g,b,r ordering, which we convert to a more natural r,g,b ++ const int mapping[3] = {2, 0, 1}; ++ const int chroma_den = 50000; ++ const int luma_den = 10000; ++ int i; ++ AVMasteringDisplayMetadata *metadata = ++ av_mastering_display_metadata_create_side_data(out); ++ if (!metadata) ++ return AVERROR(ENOMEM); ++ ++ for (i = 0; i < 3; i++) { ++ const int j = mapping[i]; ++ metadata->display_primaries[i][0].num = s->sei.mastering_display.display_primaries[j][0]; ++ metadata->display_primaries[i][0].den = chroma_den; ++ metadata->display_primaries[i][1].num = s->sei.mastering_display.display_primaries[j][1]; ++ metadata->display_primaries[i][1].den = chroma_den; ++ } ++ metadata->white_point[0].num = s->sei.mastering_display.white_point[0]; ++ metadata->white_point[0].den = chroma_den; ++ metadata->white_point[1].num = s->sei.mastering_display.white_point[1]; ++ metadata->white_point[1].den = chroma_den; ++ ++ metadata->max_luminance.num = s->sei.mastering_display.max_luminance; ++ metadata->max_luminance.den = luma_den; ++ metadata->min_luminance.num = s->sei.mastering_display.min_luminance; ++ metadata->min_luminance.den = luma_den; ++ metadata->has_luminance = 1; ++ metadata->has_primaries = 1; ++ ++ av_log(s->avctx, AV_LOG_DEBUG, "Mastering Display Metadata:\n"); ++ av_log(s->avctx, AV_LOG_DEBUG, ++ "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f)\n", ++ av_q2d(metadata->display_primaries[0][0]), ++ av_q2d(metadata->display_primaries[0][1]), ++ av_q2d(metadata->display_primaries[1][0]), ++ av_q2d(metadata->display_primaries[1][1]), ++ av_q2d(metadata->display_primaries[2][0]), ++ av_q2d(metadata->display_primaries[2][1]), ++ av_q2d(metadata->white_point[0]), av_q2d(metadata->white_point[1])); ++ av_log(s->avctx, AV_LOG_DEBUG, ++ "min_luminance=%f, max_luminance=%f\n", ++ av_q2d(metadata->min_luminance), av_q2d(metadata->max_luminance)); ++ } ++ // Decrement the mastering display flag when IRAP frame has no_rasl_output_flag=1 ++ // so the side data persists for the entire coded video sequence. ++ if (s->sei.content_light.present > 0 && ++ IS_IRAP(s) && s->no_rasl_output_flag) { ++ s->sei.content_light.present--; ++ } ++ if (s->sei.content_light.present) { ++ AVContentLightMetadata *metadata = ++ av_content_light_metadata_create_side_data(out); ++ if (!metadata) ++ return AVERROR(ENOMEM); ++ metadata->MaxCLL = s->sei.content_light.max_content_light_level; ++ metadata->MaxFALL = s->sei.content_light.max_pic_average_light_level; ++ ++ av_log(s->avctx, AV_LOG_DEBUG, "Content Light Level Metadata:\n"); ++ av_log(s->avctx, AV_LOG_DEBUG, "MaxCLL=%d, MaxFALL=%d\n", ++ metadata->MaxCLL, metadata->MaxFALL); ++ } ++ ++ if (s->sei.a53_caption.buf_ref) { ++ HEVCSEIA53Caption *a53 = &s->sei.a53_caption; ++ ++ AVFrameSideData *sd = av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_A53_CC, a53->buf_ref); ++ if (!sd) ++ av_buffer_unref(&a53->buf_ref); ++ a53->buf_ref = NULL; ++ ++ s->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; ++ } ++ ++ return 0; ++} ++ ++static int hevc_frame_start(HEVCContext *s) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ int pic_size_in_ctb = ((s->ps.sps->width >> s->ps.sps->log2_min_cb_size) + 1) * ++ ((s->ps.sps->height >> s->ps.sps->log2_min_cb_size) + 1); ++ int ret; ++ ++ memset(s->horizontal_bs, 0, s->bs_width * s->bs_height); ++ memset(s->vertical_bs, 0, s->bs_width * s->bs_height); ++ memset(s->cbf_luma, 0, s->ps.sps->min_tb_width * s->ps.sps->min_tb_height); ++ memset(s->is_pcm, 0, (s->ps.sps->min_pu_width + 1) * (s->ps.sps->min_pu_height + 1)); ++ memset(s->tab_slice_address, -1, pic_size_in_ctb * sizeof(*s->tab_slice_address)); ++ ++ s->is_decoded = 0; ++ s->first_nal_type = s->nal_unit_type; ++ ++ s->no_rasl_output_flag = IS_IDR(s) || IS_BLA(s) || (s->nal_unit_type == HEVC_NAL_CRA_NUT && s->last_eos); ++ ++ if (s->ps.pps->tiles_enabled_flag) ++ lc->end_of_tiles_x = s->ps.pps->column_width[0] << s->ps.sps->log2_ctb_size; ++ ++ ret = ff_hevc_set_new_ref(s, &s->frame, s->poc); ++ if (ret < 0) ++ goto fail; ++ ++ ret = ff_hevc_frame_rps(s); ++ if (ret < 0) { ++ av_log(s->avctx, AV_LOG_ERROR, "Error constructing the frame RPS.\n"); ++ goto fail; ++ } ++ ++ s->ref->frame->key_frame = IS_IRAP(s); ++ ++ ret = set_side_data(s); ++ if (ret < 0) ++ goto fail; ++ ++ s->frame->pict_type = 3 - s->sh.slice_type; ++ ++ if (!IS_IRAP(s)) ++ ff_hevc_bump_frame(s); ++ ++ av_frame_unref(s->output_frame); ++ ret = ff_hevc_output_frame(s, s->output_frame, 0); ++ if (ret < 0) ++ goto fail; ++ ++ if (!s->avctx->hwaccel) ++ ff_thread_finish_setup(s->avctx); ++ ++ return 0; ++ ++fail: ++ if (s->ref) ++ ff_hevc_unref_frame(s, s->ref, ~0); ++ s->ref = NULL; ++ return ret; ++} ++ ++static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) ++{ ++ HEVCLocalContext *lc = s->HEVClc; ++ GetBitContext *gb = &lc->gb; ++ int ctb_addr_ts, ret; ++ ++ *gb = nal->gb; ++ s->nal_unit_type = nal->type; ++ s->temporal_id = nal->temporal_id; ++ ++ switch (s->nal_unit_type) { ++ case HEVC_NAL_VPS: ++ if (s->avctx->hwaccel && s->avctx->hwaccel->decode_params) { ++ ret = s->avctx->hwaccel->decode_params(s->avctx, ++ nal->type, ++ nal->raw_data, ++ nal->raw_size); ++ if (ret < 0) ++ goto fail; ++ } ++ ret = ff_hevc_decode_nal_vps(gb, s->avctx, &s->ps); ++ if (ret < 0) ++ goto fail; ++ break; ++ case HEVC_NAL_SPS: ++ if (s->avctx->hwaccel && s->avctx->hwaccel->decode_params) { ++ ret = s->avctx->hwaccel->decode_params(s->avctx, ++ nal->type, ++ nal->raw_data, ++ nal->raw_size); ++ if (ret < 0) ++ goto fail; ++ } ++ ret = ff_hevc_decode_nal_sps(gb, s->avctx, &s->ps, ++ s->apply_defdispwin); ++ if (ret < 0) ++ goto fail; ++ break; ++ case HEVC_NAL_PPS: ++ if (s->avctx->hwaccel && s->avctx->hwaccel->decode_params) { ++ ret = s->avctx->hwaccel->decode_params(s->avctx, ++ nal->type, ++ nal->raw_data, ++ nal->raw_size); ++ if (ret < 0) ++ goto fail; ++ } ++ ret = ff_hevc_decode_nal_pps(gb, s->avctx, &s->ps); ++ if (ret < 0) ++ goto fail; ++ break; ++ case HEVC_NAL_SEI_PREFIX: ++ case HEVC_NAL_SEI_SUFFIX: ++ if (s->avctx->hwaccel && s->avctx->hwaccel->decode_params) { ++ ret = s->avctx->hwaccel->decode_params(s->avctx, ++ nal->type, ++ nal->raw_data, ++ nal->raw_size); ++ if (ret < 0) ++ goto fail; ++ } ++ ret = ff_hevc_decode_nal_sei(gb, s->avctx, &s->sei, &s->ps, s->nal_unit_type); ++ if (ret < 0) ++ goto fail; ++ break; ++ case HEVC_NAL_TRAIL_R: ++ case HEVC_NAL_TRAIL_N: ++ case HEVC_NAL_TSA_N: ++ case HEVC_NAL_TSA_R: ++ case HEVC_NAL_STSA_N: ++ case HEVC_NAL_STSA_R: ++ case HEVC_NAL_BLA_W_LP: ++ case HEVC_NAL_BLA_W_RADL: ++ case HEVC_NAL_BLA_N_LP: ++ case HEVC_NAL_IDR_W_RADL: ++ case HEVC_NAL_IDR_N_LP: ++ case HEVC_NAL_CRA_NUT: ++ case HEVC_NAL_RADL_N: ++ case HEVC_NAL_RADL_R: ++ case HEVC_NAL_RASL_N: ++ case HEVC_NAL_RASL_R: ++ ret = hls_slice_header(s); ++ if (ret < 0) ++ return ret; ++ if (ret == 1) { ++ ret = AVERROR_INVALIDDATA; ++ goto fail; ++ } ++ ++ ++ if ( ++ (s->avctx->skip_frame >= AVDISCARD_BIDIR && s->sh.slice_type == HEVC_SLICE_B) || ++ (s->avctx->skip_frame >= AVDISCARD_NONINTRA && s->sh.slice_type != HEVC_SLICE_I) || ++ (s->avctx->skip_frame >= AVDISCARD_NONKEY && !IS_IRAP(s))) { ++ break; ++ } ++ ++ if (s->sh.first_slice_in_pic_flag) { ++ if (s->max_ra == INT_MAX) { ++ if (s->nal_unit_type == HEVC_NAL_CRA_NUT || IS_BLA(s)) { ++ s->max_ra = s->poc; ++ } else { ++ if (IS_IDR(s)) ++ s->max_ra = INT_MIN; ++ } ++ } ++ ++ if ((s->nal_unit_type == HEVC_NAL_RASL_R || s->nal_unit_type == HEVC_NAL_RASL_N) && ++ s->poc <= s->max_ra) { ++ s->is_decoded = 0; ++ break; ++ } else { ++ if (s->nal_unit_type == HEVC_NAL_RASL_R && s->poc > s->max_ra) ++ s->max_ra = INT_MIN; ++ } ++ ++ s->overlap ++; ++ ret = hevc_frame_start(s); ++ if (ret < 0) ++ return ret; ++ } else if (!s->ref) { ++ av_log(s->avctx, AV_LOG_ERROR, "First slice in a frame missing.\n"); ++ goto fail; ++ } ++ ++ if (s->nal_unit_type != s->first_nal_type) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "Non-matching NAL types of the VCL NALUs: %d %d\n", ++ s->first_nal_type, s->nal_unit_type); ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (!s->sh.dependent_slice_segment_flag && ++ s->sh.slice_type != HEVC_SLICE_I) { ++ ret = ff_hevc_slice_rpl(s); ++ if (ret < 0) { ++ av_log(s->avctx, AV_LOG_WARNING, ++ "Error constructing the reference lists for the current slice.\n"); ++ goto fail; ++ } ++ } ++ ++ if (s->sh.first_slice_in_pic_flag && s->avctx->hwaccel) { ++ ret = s->avctx->hwaccel->start_frame(s->avctx, NULL, 0); ++ if (ret < 0) ++ goto fail; ++ } ++ ++ if (s->avctx->hwaccel) { ++ ret = s->avctx->hwaccel->decode_slice(s->avctx, nal->raw_data, nal->raw_size); ++ if (ret < 0) ++ goto fail; ++ } else { ++ if (s->threads_number > 1 && s->sh.num_entry_point_offsets > 0) ++ ctb_addr_ts = hls_slice_data_wpp(s, nal); ++ else ++ ctb_addr_ts = hls_slice_data(s); ++ if (ctb_addr_ts >= (s->ps.sps->ctb_width * s->ps.sps->ctb_height)) { ++ s->is_decoded = 1; ++ } ++ ++ if (ctb_addr_ts < 0) { ++ ret = ctb_addr_ts; ++ goto fail; ++ } ++ } ++ break; ++ case HEVC_NAL_EOS_NUT: ++ case HEVC_NAL_EOB_NUT: ++ s->seq_decode = (s->seq_decode + 1) & 0xff; ++ s->max_ra = INT_MAX; ++ break; ++ case HEVC_NAL_AUD: ++ case HEVC_NAL_FD_NUT: ++ break; ++ default: ++ av_log(s->avctx, AV_LOG_INFO, ++ "Skipping NAL unit %d\n", s->nal_unit_type); ++ } ++ ++ return 0; ++fail: ++ if (s->avctx->err_recognition & AV_EF_EXPLODE) ++ return ret; ++ return 0; ++} ++ ++static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) ++{ ++ int i, ret = 0; ++ int eos_at_start = 1; ++ ++ s->ref = NULL; ++ s->last_eos = s->eos; ++ s->eos = 0; ++ s->overlap = 0; ++ ++ /* split the input packet into NAL units, so we know the upper bound on the ++ * number of slices in the frame */ ++ ret = ff_h2645_packet_split(&s->pkt, buf, length, s->avctx, s->is_nalff, ++ s->nal_length_size, s->avctx->codec_id, 1, 0); ++ if (ret < 0) { ++ av_log(s->avctx, AV_LOG_ERROR, ++ "Error splitting the input into NAL units.\n"); ++ return ret; ++ } ++ ++ for (i = 0; i < s->pkt.nb_nals; i++) { ++ if (s->pkt.nals[i].type == HEVC_NAL_EOB_NUT || ++ s->pkt.nals[i].type == HEVC_NAL_EOS_NUT) { ++ if (eos_at_start) { ++ s->last_eos = 1; ++ } else { ++ s->eos = 1; ++ } ++ } else { ++ eos_at_start = 0; ++ } ++ } ++ ++ /* decode the NAL units */ ++ for (i = 0; i < s->pkt.nb_nals; i++) { ++ H2645NAL *nal = &s->pkt.nals[i]; ++ ++ if (s->avctx->skip_frame >= AVDISCARD_ALL || ++ (s->avctx->skip_frame >= AVDISCARD_NONREF ++ && ff_hevc_nal_is_nonref(nal->type)) || nal->nuh_layer_id > 0) ++ continue; ++ ++ ret = decode_nal_unit(s, nal); ++ if (ret >= 0 && s->overlap > 2) ++ ret = AVERROR_INVALIDDATA; ++ if (ret < 0) { ++ av_log(s->avctx, AV_LOG_WARNING, ++ "Error parsing NAL unit #%d.\n", i); ++ goto fail; ++ } ++ } ++ ++fail: ++ if (s->ref && s->threads_type == FF_THREAD_FRAME) ++ ff_thread_report_progress(&s->ref->tf, INT_MAX, 0); ++ ++ return ret; ++} ++ ++static void print_md5(void *log_ctx, int level, uint8_t md5[16]) ++{ ++ int i; ++ for (i = 0; i < 16; i++) ++ av_log(log_ctx, level, "%02"PRIx8, md5[i]); ++} ++ ++static int verify_md5(HEVCContext *s, AVFrame *frame) ++{ ++ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); ++ int pixel_shift; ++ int i, j; ++ ++ if (!desc) ++ return AVERROR(EINVAL); ++ ++ pixel_shift = desc->comp[0].depth > 8; ++ ++ av_log(s->avctx, AV_LOG_DEBUG, "Verifying checksum for frame with POC %d: ", ++ s->poc); ++ ++ /* the checksums are LE, so we have to byteswap for >8bpp formats ++ * on BE arches */ ++#if HAVE_BIGENDIAN ++ if (pixel_shift && !s->checksum_buf) { ++ av_fast_malloc(&s->checksum_buf, &s->checksum_buf_size, ++ FFMAX3(frame->linesize[0], frame->linesize[1], ++ frame->linesize[2])); ++ if (!s->checksum_buf) ++ return AVERROR(ENOMEM); ++ } ++#endif ++ ++ for (i = 0; frame->data[i]; i++) { ++ int width = s->avctx->coded_width; ++ int height = s->avctx->coded_height; ++ int w = (i == 1 || i == 2) ? (width >> desc->log2_chroma_w) : width; ++ int h = (i == 1 || i == 2) ? (height >> desc->log2_chroma_h) : height; ++ uint8_t md5[16]; ++ ++ av_md5_init(s->md5_ctx); ++ for (j = 0; j < h; j++) { ++ const uint8_t *src = frame->data[i] + j * frame->linesize[i]; ++#if HAVE_BIGENDIAN ++ if (pixel_shift) { ++ s->bdsp.bswap16_buf((uint16_t *) s->checksum_buf, ++ (const uint16_t *) src, w); ++ src = s->checksum_buf; ++ } ++#endif ++ av_md5_update(s->md5_ctx, src, w << pixel_shift); ++ } ++ av_md5_final(s->md5_ctx, md5); ++ ++ if (!memcmp(md5, s->sei.picture_hash.md5[i], 16)) { ++ av_log (s->avctx, AV_LOG_DEBUG, "plane %d - correct ", i); ++ print_md5(s->avctx, AV_LOG_DEBUG, md5); ++ av_log (s->avctx, AV_LOG_DEBUG, "; "); ++ } else { ++ av_log (s->avctx, AV_LOG_ERROR, "mismatching checksum of plane %d - ", i); ++ print_md5(s->avctx, AV_LOG_ERROR, md5); ++ av_log (s->avctx, AV_LOG_ERROR, " != "); ++ print_md5(s->avctx, AV_LOG_ERROR, s->sei.picture_hash.md5[i]); ++ av_log (s->avctx, AV_LOG_ERROR, "\n"); ++ return AVERROR_INVALIDDATA; ++ } ++ } ++ ++ av_log(s->avctx, AV_LOG_DEBUG, "\n"); ++ ++ return 0; ++} ++ ++static int hevc_decode_extradata(HEVCContext *s, uint8_t *buf, int length, int first) ++{ ++ int ret, i; ++ ++ ret = ff_hevc_decode_extradata(buf, length, &s->ps, &s->sei, &s->is_nalff, ++ &s->nal_length_size, s->avctx->err_recognition, ++ s->apply_defdispwin, s->avctx); ++ if (ret < 0) ++ return ret; ++ ++ /* export stream parameters from the first SPS */ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) { ++ if (first && s->ps.sps_list[i]) { ++ const HEVCSPS *sps = (const HEVCSPS*)s->ps.sps_list[i]->data; ++ export_stream_params(s, sps); ++ break; ++ } ++ } ++ ++ return 0; ++} ++ ++static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, ++ AVPacket *avpkt) ++{ ++ int ret; ++ int new_extradata_size; ++ uint8_t *new_extradata; ++ HEVCContext *s = avctx->priv_data; ++ ++ if (!avpkt->size) { ++ ret = ff_hevc_output_frame(s, data, 1); ++ if (ret < 0) ++ return ret; ++ ++ *got_output = ret; ++ return 0; ++ } ++ ++ new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, ++ &new_extradata_size); ++ if (new_extradata && new_extradata_size > 0) { ++ ret = hevc_decode_extradata(s, new_extradata, new_extradata_size, 0); ++ if (ret < 0) ++ return ret; ++ } ++ ++ s->ref = NULL; ++ ret = decode_nal_units(s, avpkt->data, avpkt->size); ++ if (ret < 0) ++ return ret; ++ ++ if (avctx->hwaccel) { ++ if (s->ref && (ret = avctx->hwaccel->end_frame(avctx)) < 0) { ++ av_log(avctx, AV_LOG_ERROR, ++ "hardware accelerator failed to decode picture\n"); ++ ff_hevc_unref_frame(s, s->ref, ~0); ++ return ret; ++ } ++ } else { ++ /* verify the SEI checksum */ ++ if (avctx->err_recognition & AV_EF_CRCCHECK && s->is_decoded && ++ s->sei.picture_hash.is_md5) { ++ ret = verify_md5(s, s->ref->frame); ++ if (ret < 0 && avctx->err_recognition & AV_EF_EXPLODE) { ++ ff_hevc_unref_frame(s, s->ref, ~0); ++ return ret; ++ } ++ } ++ } ++ s->sei.picture_hash.is_md5 = 0; ++ ++ if (s->is_decoded) { ++ av_log(avctx, AV_LOG_DEBUG, "Decoded frame with POC %d.\n", s->poc); ++ s->is_decoded = 0; ++ } ++ ++ if (s->output_frame->buf[0]) { ++ av_frame_move_ref(data, s->output_frame); ++ *got_output = 1; ++ } ++ ++ return avpkt->size; ++} ++ ++static int hevc_ref_frame(HEVCContext *s, HEVCFrame *dst, HEVCFrame *src) ++{ ++ int ret; ++ ++ ret = ff_thread_ref_frame(&dst->tf, &src->tf); ++ if (ret < 0) ++ return ret; ++ ++ dst->tab_mvf_buf = av_buffer_ref(src->tab_mvf_buf); ++ if (!dst->tab_mvf_buf) ++ goto fail; ++ dst->tab_mvf = src->tab_mvf; ++ ++ dst->rpl_tab_buf = av_buffer_ref(src->rpl_tab_buf); ++ if (!dst->rpl_tab_buf) ++ goto fail; ++ dst->rpl_tab = src->rpl_tab; ++ ++ dst->rpl_buf = av_buffer_ref(src->rpl_buf); ++ if (!dst->rpl_buf) ++ goto fail; ++ ++ dst->poc = src->poc; ++ dst->ctb_count = src->ctb_count; ++ dst->flags = src->flags; ++ dst->sequence = src->sequence; ++ ++ if (src->hwaccel_picture_private) { ++ dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf); ++ if (!dst->hwaccel_priv_buf) ++ goto fail; ++ dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data; ++ } ++ ++ return 0; ++fail: ++ ff_hevc_unref_frame(s, dst, ~0); ++ return AVERROR(ENOMEM); ++} ++ ++static av_cold int hevc_decode_free(AVCodecContext *avctx) ++{ ++ HEVCContext *s = avctx->priv_data; ++ int i; ++ ++ pic_arrays_free(s); ++ ++ av_freep(&s->md5_ctx); ++ ++ av_freep(&s->cabac_state); ++ ++ for (i = 0; i < 3; i++) { ++ av_freep(&s->sao_pixel_buffer_h[i]); ++ av_freep(&s->sao_pixel_buffer_v[i]); ++ } ++ av_frame_free(&s->output_frame); ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ ff_hevc_unref_frame(s, &s->DPB[i], ~0); ++ av_frame_free(&s->DPB[i].frame); ++ } ++ ++ ff_hevc_ps_uninit(&s->ps); ++ ++ av_freep(&s->sh.entry_point_offset); ++ av_freep(&s->sh.offset); ++ av_freep(&s->sh.size); ++ ++ for (i = 1; i < s->threads_number; i++) { ++ HEVCLocalContext *lc = s->HEVClcList[i]; ++ if (lc) { ++ av_freep(&s->HEVClcList[i]); ++ av_freep(&s->sList[i]); ++ } ++ } ++ if (s->HEVClc == s->HEVClcList[0]) ++ s->HEVClc = NULL; ++ av_freep(&s->HEVClcList[0]); ++ ++ ff_h2645_packet_uninit(&s->pkt); ++ ++ ff_hevc_reset_sei(&s->sei); ++ ++ return 0; ++} ++ ++static av_cold int hevc_init_context(AVCodecContext *avctx) ++{ ++ HEVCContext *s = avctx->priv_data; ++ int i; ++ ++ s->avctx = avctx; ++ ++ s->HEVClc = av_mallocz(sizeof(HEVCLocalContext)); ++ if (!s->HEVClc) ++ goto fail; ++ s->HEVClcList[0] = s->HEVClc; ++ s->sList[0] = s; ++ ++ s->cabac_state = av_malloc(HEVC_CONTEXTS); ++ if (!s->cabac_state) ++ goto fail; ++ ++ s->output_frame = av_frame_alloc(); ++ if (!s->output_frame) ++ goto fail; ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ s->DPB[i].frame = av_frame_alloc(); ++ if (!s->DPB[i].frame) ++ goto fail; ++ s->DPB[i].tf.f = s->DPB[i].frame; ++ } ++ ++ s->max_ra = INT_MAX; ++ ++ s->md5_ctx = av_md5_alloc(); ++ if (!s->md5_ctx) ++ goto fail; ++ ++ ff_bswapdsp_init(&s->bdsp); ++ ++ s->context_initialized = 1; ++ s->eos = 0; ++ ++ ff_hevc_reset_sei(&s->sei); ++ ++ return 0; ++ ++fail: ++ hevc_decode_free(avctx); ++ return AVERROR(ENOMEM); ++} ++ ++#if HAVE_THREADS ++static int hevc_update_thread_context(AVCodecContext *dst, ++ const AVCodecContext *src) ++{ ++ HEVCContext *s = dst->priv_data; ++ HEVCContext *s0 = src->priv_data; ++ int i, ret; ++ ++ if (!s->context_initialized) { ++ ret = hevc_init_context(dst); ++ if (ret < 0) ++ return ret; ++ } ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) { ++ ff_hevc_unref_frame(s, &s->DPB[i], ~0); ++ if (s0->DPB[i].frame->buf[0]) { ++ ret = hevc_ref_frame(s, &s->DPB[i], &s0->DPB[i]); ++ if (ret < 0) ++ return ret; ++ } ++ } ++ ++ if (s->ps.sps != s0->ps.sps) ++ s->ps.sps = NULL; ++ for (i = 0; i < FF_ARRAY_ELEMS(s->ps.vps_list); i++) { ++ av_buffer_unref(&s->ps.vps_list[i]); ++ if (s0->ps.vps_list[i]) { ++ s->ps.vps_list[i] = av_buffer_ref(s0->ps.vps_list[i]); ++ if (!s->ps.vps_list[i]) ++ return AVERROR(ENOMEM); ++ } ++ } ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) { ++ av_buffer_unref(&s->ps.sps_list[i]); ++ if (s0->ps.sps_list[i]) { ++ s->ps.sps_list[i] = av_buffer_ref(s0->ps.sps_list[i]); ++ if (!s->ps.sps_list[i]) ++ return AVERROR(ENOMEM); ++ } ++ } ++ ++ for (i = 0; i < FF_ARRAY_ELEMS(s->ps.pps_list); i++) { ++ av_buffer_unref(&s->ps.pps_list[i]); ++ if (s0->ps.pps_list[i]) { ++ s->ps.pps_list[i] = av_buffer_ref(s0->ps.pps_list[i]); ++ if (!s->ps.pps_list[i]) ++ return AVERROR(ENOMEM); ++ } ++ } ++ ++ if (s->ps.sps != s0->ps.sps) ++ if ((ret = set_sps(s, s0->ps.sps, src->pix_fmt)) < 0) ++ return ret; ++ ++ s->seq_decode = s0->seq_decode; ++ s->seq_output = s0->seq_output; ++ s->pocTid0 = s0->pocTid0; ++ s->max_ra = s0->max_ra; ++ s->eos = s0->eos; ++ s->no_rasl_output_flag = s0->no_rasl_output_flag; ++ ++ s->is_nalff = s0->is_nalff; ++ s->nal_length_size = s0->nal_length_size; ++ ++ s->threads_number = s0->threads_number; ++ s->threads_type = s0->threads_type; ++ ++ if (s0->eos) { ++ s->seq_decode = (s->seq_decode + 1) & 0xff; ++ s->max_ra = INT_MAX; ++ } ++ ++ av_buffer_unref(&s->sei.a53_caption.buf_ref); ++ if (s0->sei.a53_caption.buf_ref) { ++ s->sei.a53_caption.buf_ref = av_buffer_ref(s0->sei.a53_caption.buf_ref); ++ if (!s->sei.a53_caption.buf_ref) ++ return AVERROR(ENOMEM); ++ } ++ ++ s->sei.frame_packing = s0->sei.frame_packing; ++ s->sei.display_orientation = s0->sei.display_orientation; ++ s->sei.mastering_display = s0->sei.mastering_display; ++ s->sei.content_light = s0->sei.content_light; ++ s->sei.alternative_transfer = s0->sei.alternative_transfer; ++ ++ return 0; ++} ++#endif ++ ++static av_cold int hevc_decode_init(AVCodecContext *avctx) ++{ ++ HEVCContext *s = avctx->priv_data; ++ int ret; ++ ++ avctx->internal->allocate_progress = 1; ++ ++ ret = hevc_init_context(avctx); ++ if (ret < 0) ++ return ret; ++ ++ s->enable_parallel_tiles = 0; ++ s->sei.picture_timing.picture_struct = 0; ++ s->eos = 1; ++ ++ atomic_init(&s->wpp_err, 0); ++ ++ if(avctx->active_thread_type & FF_THREAD_SLICE) ++ s->threads_number = avctx->thread_count; ++ else ++ s->threads_number = 1; ++ ++ if (avctx->extradata_size > 0 && avctx->extradata) { ++ ret = hevc_decode_extradata(s, avctx->extradata, avctx->extradata_size, 1); ++ if (ret < 0) { ++ hevc_decode_free(avctx); ++ return ret; ++ } ++ } ++ ++ if((avctx->active_thread_type & FF_THREAD_FRAME) && avctx->thread_count > 1) ++ s->threads_type = FF_THREAD_FRAME; ++ else ++ s->threads_type = FF_THREAD_SLICE; ++ ++ return 0; ++} ++ ++#if HAVE_THREADS ++static av_cold int hevc_init_thread_copy(AVCodecContext *avctx) ++{ ++ HEVCContext *s = avctx->priv_data; ++ int ret; ++ ++ memset(s, 0, sizeof(*s)); ++ ++ ret = hevc_init_context(avctx); ++ if (ret < 0) ++ return ret; ++ ++ return 0; ++} ++#endif ++ ++static void hevc_decode_flush(AVCodecContext *avctx) ++{ ++ HEVCContext *s = avctx->priv_data; ++ ff_hevc_flush_dpb(s); ++ ff_hevc_reset_sei(&s->sei); ++ s->max_ra = INT_MAX; ++ s->eos = 1; ++} ++ ++#define OFFSET(x) offsetof(HEVCContext, x) ++#define PAR (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) ++ ++static const AVOption options[] = { ++ { "apply_defdispwin", "Apply default display window from VUI", OFFSET(apply_defdispwin), ++ AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, PAR }, ++ { "strict-displaywin", "stricly apply default display window size", OFFSET(apply_defdispwin), ++ AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, PAR }, ++ { NULL }, ++}; ++ ++static const AVClass hevc_decoder_class = { ++ .class_name = "HEVC decoder", ++ .item_name = av_default_item_name, ++ .option = options, ++ .version = LIBAVUTIL_VERSION_INT, ++}; ++ ++AVCodec ff_hevc_decoder = { ++ .name = "hevc", ++ .long_name = NULL_IF_CONFIG_SMALL("HEVC (High Efficiency Video Coding)"), ++ .type = AVMEDIA_TYPE_VIDEO, ++ .id = AV_CODEC_ID_HEVC, ++ .priv_data_size = sizeof(HEVCContext), ++ .priv_class = &hevc_decoder_class, ++ .init = hevc_decode_init, ++ .close = hevc_decode_free, ++ .decode = hevc_decode_frame, ++ .flush = hevc_decode_flush, ++ .update_thread_context = ONLY_IF_THREADS_ENABLED(hevc_update_thread_context), ++ .init_thread_copy = ONLY_IF_THREADS_ENABLED(hevc_init_thread_copy), ++ .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | ++ AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, ++ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING, ++ .profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), ++ .hw_configs = (const AVCodecHWConfigInternal*[]) { ++#if CONFIG_HEVC_DXVA2_HWACCEL ++ HWACCEL_DXVA2(hevc), ++#endif ++#if CONFIG_HEVC_D3D11VA_HWACCEL ++ HWACCEL_D3D11VA(hevc), ++#endif ++#if CONFIG_HEVC_D3D11VA2_HWACCEL ++ HWACCEL_D3D11VA2(hevc), ++#endif ++#if CONFIG_HEVC_NVDEC_HWACCEL ++ HWACCEL_NVDEC(hevc), ++#endif ++#if CONFIG_HEVC_VAAPI_HWACCEL ++ HWACCEL_VAAPI(hevc), ++#endif ++#if CONFIG_HEVC_VDPAU_HWACCEL ++ HWACCEL_VDPAU(hevc), ++#endif ++#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL ++ HWACCEL_VIDEOTOOLBOX(hevc), ++#endif ++ NULL ++ }, ++}; +diff --git a/libavformat/autorename_libavformat_hevc.c b/libavformat/autorename_libavformat_hevc.c +new file mode 100644 +index 0000000000000000000000000000000000000000..f621cb2f198c9bddd9c09f1a9ab4b7db33042aa5 +--- /dev/null ++++ b/libavformat/autorename_libavformat_hevc.c +@@ -0,0 +1,1127 @@ ++/* ++ * Copyright (c) 2014 Tim Walker ++ * ++ * 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 "libavcodec/avcodec.h" ++#include "libavcodec/get_bits.h" ++#include "libavcodec/golomb.h" ++#include "libavcodec/hevc.h" ++#include "libavutil/intreadwrite.h" ++#include "avc.h" ++#include "avio.h" ++#include "avio_internal.h" ++#include "hevc.h" ++ ++#define MAX_SPATIAL_SEGMENTATION 4096 // max. value of u(12) field ++ ++typedef struct HVCCNALUnitArray { ++ uint8_t array_completeness; ++ uint8_t NAL_unit_type; ++ uint16_t numNalus; ++ uint16_t *nalUnitLength; ++ uint8_t **nalUnit; ++} HVCCNALUnitArray; ++ ++typedef struct HEVCDecoderConfigurationRecord { ++ uint8_t configurationVersion; ++ uint8_t general_profile_space; ++ uint8_t general_tier_flag; ++ uint8_t general_profile_idc; ++ uint32_t general_profile_compatibility_flags; ++ uint64_t general_constraint_indicator_flags; ++ uint8_t general_level_idc; ++ uint16_t min_spatial_segmentation_idc; ++ uint8_t parallelismType; ++ uint8_t chromaFormat; ++ uint8_t bitDepthLumaMinus8; ++ uint8_t bitDepthChromaMinus8; ++ uint16_t avgFrameRate; ++ uint8_t constantFrameRate; ++ uint8_t numTemporalLayers; ++ uint8_t temporalIdNested; ++ uint8_t lengthSizeMinusOne; ++ uint8_t numOfArrays; ++ HVCCNALUnitArray *array; ++} HEVCDecoderConfigurationRecord; ++ ++typedef struct HVCCProfileTierLevel { ++ uint8_t profile_space; ++ uint8_t tier_flag; ++ uint8_t profile_idc; ++ uint32_t profile_compatibility_flags; ++ uint64_t constraint_indicator_flags; ++ uint8_t level_idc; ++} HVCCProfileTierLevel; ++ ++static void hvcc_update_ptl(HEVCDecoderConfigurationRecord *hvcc, ++ HVCCProfileTierLevel *ptl) ++{ ++ /* ++ * The value of general_profile_space in all the parameter sets must be ++ * identical. ++ */ ++ hvcc->general_profile_space = ptl->profile_space; ++ ++ /* ++ * The level indication general_level_idc must indicate a level of ++ * capability equal to or greater than the highest level indicated for the ++ * highest tier in all the parameter sets. ++ */ ++ if (hvcc->general_tier_flag < ptl->tier_flag) ++ hvcc->general_level_idc = ptl->level_idc; ++ else ++ hvcc->general_level_idc = FFMAX(hvcc->general_level_idc, ptl->level_idc); ++ ++ /* ++ * The tier indication general_tier_flag must indicate a tier equal to or ++ * greater than the highest tier indicated in all the parameter sets. ++ */ ++ hvcc->general_tier_flag = FFMAX(hvcc->general_tier_flag, ptl->tier_flag); ++ ++ /* ++ * The profile indication general_profile_idc must indicate a profile to ++ * which the stream associated with this configuration record conforms. ++ * ++ * If the sequence parameter sets are marked with different profiles, then ++ * the stream may need examination to determine which profile, if any, the ++ * entire stream conforms to. If the entire stream is not examined, or the ++ * examination reveals that there is no profile to which the entire stream ++ * conforms, then the entire stream must be split into two or more ++ * sub-streams with separate configuration records in which these rules can ++ * be met. ++ * ++ * Note: set the profile to the highest value for the sake of simplicity. ++ */ ++ hvcc->general_profile_idc = FFMAX(hvcc->general_profile_idc, ptl->profile_idc); ++ ++ /* ++ * Each bit in general_profile_compatibility_flags may only be set if all ++ * the parameter sets set that bit. ++ */ ++ hvcc->general_profile_compatibility_flags &= ptl->profile_compatibility_flags; ++ ++ /* ++ * Each bit in general_constraint_indicator_flags may only be set if all ++ * the parameter sets set that bit. ++ */ ++ hvcc->general_constraint_indicator_flags &= ptl->constraint_indicator_flags; ++} ++ ++static void hvcc_parse_ptl(GetBitContext *gb, ++ HEVCDecoderConfigurationRecord *hvcc, ++ unsigned int max_sub_layers_minus1) ++{ ++ unsigned int i; ++ HVCCProfileTierLevel general_ptl; ++ uint8_t sub_layer_profile_present_flag[HEVC_MAX_SUB_LAYERS]; ++ uint8_t sub_layer_level_present_flag[HEVC_MAX_SUB_LAYERS]; ++ ++ general_ptl.profile_space = get_bits(gb, 2); ++ general_ptl.tier_flag = get_bits1(gb); ++ general_ptl.profile_idc = get_bits(gb, 5); ++ general_ptl.profile_compatibility_flags = get_bits_long(gb, 32); ++ general_ptl.constraint_indicator_flags = get_bits64(gb, 48); ++ general_ptl.level_idc = get_bits(gb, 8); ++ hvcc_update_ptl(hvcc, &general_ptl); ++ ++ for (i = 0; i < max_sub_layers_minus1; i++) { ++ sub_layer_profile_present_flag[i] = get_bits1(gb); ++ sub_layer_level_present_flag[i] = get_bits1(gb); ++ } ++ ++ if (max_sub_layers_minus1 > 0) ++ for (i = max_sub_layers_minus1; i < 8; i++) ++ skip_bits(gb, 2); // reserved_zero_2bits[i] ++ ++ for (i = 0; i < max_sub_layers_minus1; i++) { ++ if (sub_layer_profile_present_flag[i]) { ++ /* ++ * sub_layer_profile_space[i] u(2) ++ * sub_layer_tier_flag[i] u(1) ++ * sub_layer_profile_idc[i] u(5) ++ * sub_layer_profile_compatibility_flag[i][0..31] u(32) ++ * sub_layer_progressive_source_flag[i] u(1) ++ * sub_layer_interlaced_source_flag[i] u(1) ++ * sub_layer_non_packed_constraint_flag[i] u(1) ++ * sub_layer_frame_only_constraint_flag[i] u(1) ++ * sub_layer_reserved_zero_44bits[i] u(44) ++ */ ++ skip_bits_long(gb, 32); ++ skip_bits_long(gb, 32); ++ skip_bits (gb, 24); ++ } ++ ++ if (sub_layer_level_present_flag[i]) ++ skip_bits(gb, 8); ++ } ++} ++ ++static void skip_sub_layer_hrd_parameters(GetBitContext *gb, ++ unsigned int cpb_cnt_minus1, ++ uint8_t sub_pic_hrd_params_present_flag) ++{ ++ unsigned int i; ++ ++ for (i = 0; i <= cpb_cnt_minus1; i++) { ++ get_ue_golomb_long(gb); // bit_rate_value_minus1 ++ get_ue_golomb_long(gb); // cpb_size_value_minus1 ++ ++ if (sub_pic_hrd_params_present_flag) { ++ get_ue_golomb_long(gb); // cpb_size_du_value_minus1 ++ get_ue_golomb_long(gb); // bit_rate_du_value_minus1 ++ } ++ ++ skip_bits1(gb); // cbr_flag ++ } ++} ++ ++static int skip_hrd_parameters(GetBitContext *gb, uint8_t cprms_present_flag, ++ unsigned int max_sub_layers_minus1) ++{ ++ unsigned int i; ++ uint8_t sub_pic_hrd_params_present_flag = 0; ++ uint8_t nal_hrd_parameters_present_flag = 0; ++ uint8_t vcl_hrd_parameters_present_flag = 0; ++ ++ if (cprms_present_flag) { ++ nal_hrd_parameters_present_flag = get_bits1(gb); ++ vcl_hrd_parameters_present_flag = get_bits1(gb); ++ ++ if (nal_hrd_parameters_present_flag || ++ vcl_hrd_parameters_present_flag) { ++ sub_pic_hrd_params_present_flag = get_bits1(gb); ++ ++ if (sub_pic_hrd_params_present_flag) ++ /* ++ * tick_divisor_minus2 u(8) ++ * du_cpb_removal_delay_increment_length_minus1 u(5) ++ * sub_pic_cpb_params_in_pic_timing_sei_flag u(1) ++ * dpb_output_delay_du_length_minus1 u(5) ++ */ ++ skip_bits(gb, 19); ++ ++ /* ++ * bit_rate_scale u(4) ++ * cpb_size_scale u(4) ++ */ ++ skip_bits(gb, 8); ++ ++ if (sub_pic_hrd_params_present_flag) ++ skip_bits(gb, 4); // cpb_size_du_scale ++ ++ /* ++ * initial_cpb_removal_delay_length_minus1 u(5) ++ * au_cpb_removal_delay_length_minus1 u(5) ++ * dpb_output_delay_length_minus1 u(5) ++ */ ++ skip_bits(gb, 15); ++ } ++ } ++ ++ for (i = 0; i <= max_sub_layers_minus1; i++) { ++ unsigned int cpb_cnt_minus1 = 0; ++ uint8_t low_delay_hrd_flag = 0; ++ uint8_t fixed_pic_rate_within_cvs_flag = 0; ++ uint8_t fixed_pic_rate_general_flag = get_bits1(gb); ++ ++ if (!fixed_pic_rate_general_flag) ++ fixed_pic_rate_within_cvs_flag = get_bits1(gb); ++ ++ if (fixed_pic_rate_within_cvs_flag) ++ get_ue_golomb_long(gb); // elemental_duration_in_tc_minus1 ++ else ++ low_delay_hrd_flag = get_bits1(gb); ++ ++ if (!low_delay_hrd_flag) { ++ cpb_cnt_minus1 = get_ue_golomb_long(gb); ++ if (cpb_cnt_minus1 > 31) ++ return AVERROR_INVALIDDATA; ++ } ++ ++ if (nal_hrd_parameters_present_flag) ++ skip_sub_layer_hrd_parameters(gb, cpb_cnt_minus1, ++ sub_pic_hrd_params_present_flag); ++ ++ if (vcl_hrd_parameters_present_flag) ++ skip_sub_layer_hrd_parameters(gb, cpb_cnt_minus1, ++ sub_pic_hrd_params_present_flag); ++ } ++ ++ return 0; ++} ++ ++static void skip_timing_info(GetBitContext *gb) ++{ ++ skip_bits_long(gb, 32); // num_units_in_tick ++ skip_bits_long(gb, 32); // time_scale ++ ++ if (get_bits1(gb)) // poc_proportional_to_timing_flag ++ get_ue_golomb_long(gb); // num_ticks_poc_diff_one_minus1 ++} ++ ++static void hvcc_parse_vui(GetBitContext *gb, ++ HEVCDecoderConfigurationRecord *hvcc, ++ unsigned int max_sub_layers_minus1) ++{ ++ unsigned int min_spatial_segmentation_idc; ++ ++ if (get_bits1(gb)) // aspect_ratio_info_present_flag ++ if (get_bits(gb, 8) == 255) // aspect_ratio_idc ++ skip_bits_long(gb, 32); // sar_width u(16), sar_height u(16) ++ ++ if (get_bits1(gb)) // overscan_info_present_flag ++ skip_bits1(gb); // overscan_appropriate_flag ++ ++ if (get_bits1(gb)) { // video_signal_type_present_flag ++ skip_bits(gb, 4); // video_format u(3), video_full_range_flag u(1) ++ ++ if (get_bits1(gb)) // colour_description_present_flag ++ /* ++ * colour_primaries u(8) ++ * transfer_characteristics u(8) ++ * matrix_coeffs u(8) ++ */ ++ skip_bits(gb, 24); ++ } ++ ++ if (get_bits1(gb)) { // chroma_loc_info_present_flag ++ get_ue_golomb_long(gb); // chroma_sample_loc_type_top_field ++ get_ue_golomb_long(gb); // chroma_sample_loc_type_bottom_field ++ } ++ ++ /* ++ * neutral_chroma_indication_flag u(1) ++ * field_seq_flag u(1) ++ * frame_field_info_present_flag u(1) ++ */ ++ skip_bits(gb, 3); ++ ++ if (get_bits1(gb)) { // default_display_window_flag ++ get_ue_golomb_long(gb); // def_disp_win_left_offset ++ get_ue_golomb_long(gb); // def_disp_win_right_offset ++ get_ue_golomb_long(gb); // def_disp_win_top_offset ++ get_ue_golomb_long(gb); // def_disp_win_bottom_offset ++ } ++ ++ if (get_bits1(gb)) { // vui_timing_info_present_flag ++ skip_timing_info(gb); ++ ++ if (get_bits1(gb)) // vui_hrd_parameters_present_flag ++ skip_hrd_parameters(gb, 1, max_sub_layers_minus1); ++ } ++ ++ if (get_bits1(gb)) { // bitstream_restriction_flag ++ /* ++ * tiles_fixed_structure_flag u(1) ++ * motion_vectors_over_pic_boundaries_flag u(1) ++ * restricted_ref_pic_lists_flag u(1) ++ */ ++ skip_bits(gb, 3); ++ ++ min_spatial_segmentation_idc = get_ue_golomb_long(gb); ++ ++ /* ++ * unsigned int(12) min_spatial_segmentation_idc; ++ * ++ * The min_spatial_segmentation_idc indication must indicate a level of ++ * spatial segmentation equal to or less than the lowest level of ++ * spatial segmentation indicated in all the parameter sets. ++ */ ++ hvcc->min_spatial_segmentation_idc = FFMIN(hvcc->min_spatial_segmentation_idc, ++ min_spatial_segmentation_idc); ++ ++ get_ue_golomb_long(gb); // max_bytes_per_pic_denom ++ get_ue_golomb_long(gb); // max_bits_per_min_cu_denom ++ get_ue_golomb_long(gb); // log2_max_mv_length_horizontal ++ get_ue_golomb_long(gb); // log2_max_mv_length_vertical ++ } ++} ++ ++static void skip_sub_layer_ordering_info(GetBitContext *gb) ++{ ++ get_ue_golomb_long(gb); // max_dec_pic_buffering_minus1 ++ get_ue_golomb_long(gb); // max_num_reorder_pics ++ get_ue_golomb_long(gb); // max_latency_increase_plus1 ++} ++ ++static int hvcc_parse_vps(GetBitContext *gb, ++ HEVCDecoderConfigurationRecord *hvcc) ++{ ++ unsigned int vps_max_sub_layers_minus1; ++ ++ /* ++ * vps_video_parameter_set_id u(4) ++ * vps_reserved_three_2bits u(2) ++ * vps_max_layers_minus1 u(6) ++ */ ++ skip_bits(gb, 12); ++ ++ vps_max_sub_layers_minus1 = get_bits(gb, 3); ++ ++ /* ++ * numTemporalLayers greater than 1 indicates that the stream to which this ++ * configuration record applies is temporally scalable and the contained ++ * number of temporal layers (also referred to as temporal sub-layer or ++ * sub-layer in ISO/IEC 23008-2) is equal to numTemporalLayers. Value 1 ++ * indicates that the stream is not temporally scalable. Value 0 indicates ++ * that it is unknown whether the stream is temporally scalable. ++ */ ++ hvcc->numTemporalLayers = FFMAX(hvcc->numTemporalLayers, ++ vps_max_sub_layers_minus1 + 1); ++ ++ /* ++ * vps_temporal_id_nesting_flag u(1) ++ * vps_reserved_0xffff_16bits u(16) ++ */ ++ skip_bits(gb, 17); ++ ++ hvcc_parse_ptl(gb, hvcc, vps_max_sub_layers_minus1); ++ ++ /* nothing useful for hvcC past this point */ ++ return 0; ++} ++ ++static void skip_scaling_list_data(GetBitContext *gb) ++{ ++ int i, j, k, num_coeffs; ++ ++ for (i = 0; i < 4; i++) ++ for (j = 0; j < (i == 3 ? 2 : 6); j++) ++ if (!get_bits1(gb)) // scaling_list_pred_mode_flag[i][j] ++ get_ue_golomb_long(gb); // scaling_list_pred_matrix_id_delta[i][j] ++ else { ++ num_coeffs = FFMIN(64, 1 << (4 + (i << 1))); ++ ++ if (i > 1) ++ get_se_golomb_long(gb); // scaling_list_dc_coef_minus8[i-2][j] ++ ++ for (k = 0; k < num_coeffs; k++) ++ get_se_golomb_long(gb); // scaling_list_delta_coef ++ } ++} ++ ++static int parse_rps(GetBitContext *gb, unsigned int rps_idx, ++ unsigned int num_rps, ++ unsigned int num_delta_pocs[HEVC_MAX_SHORT_TERM_REF_PIC_SETS]) ++{ ++ unsigned int i; ++ ++ if (rps_idx && get_bits1(gb)) { // inter_ref_pic_set_prediction_flag ++ /* this should only happen for slice headers, and this isn't one */ ++ if (rps_idx >= num_rps) ++ return AVERROR_INVALIDDATA; ++ ++ skip_bits1 (gb); // delta_rps_sign ++ get_ue_golomb_long(gb); // abs_delta_rps_minus1 ++ ++ num_delta_pocs[rps_idx] = 0; ++ ++ /* ++ * From libavcodec/hevc_ps.c: ++ * ++ * if (is_slice_header) { ++ * //foo ++ * } else ++ * rps_ridx = &sps->st_rps[rps - sps->st_rps - 1]; ++ * ++ * where: ++ * rps: &sps->st_rps[rps_idx] ++ * sps->st_rps: &sps->st_rps[0] ++ * is_slice_header: rps_idx == num_rps ++ * ++ * thus: ++ * if (num_rps != rps_idx) ++ * rps_ridx = &sps->st_rps[rps_idx - 1]; ++ * ++ * NumDeltaPocs[RefRpsIdx]: num_delta_pocs[rps_idx - 1] ++ */ ++ for (i = 0; i <= num_delta_pocs[rps_idx - 1]; i++) { ++ uint8_t use_delta_flag = 0; ++ uint8_t used_by_curr_pic_flag = get_bits1(gb); ++ if (!used_by_curr_pic_flag) ++ use_delta_flag = get_bits1(gb); ++ ++ if (used_by_curr_pic_flag || use_delta_flag) ++ num_delta_pocs[rps_idx]++; ++ } ++ } else { ++ unsigned int num_negative_pics = get_ue_golomb_long(gb); ++ unsigned int num_positive_pics = get_ue_golomb_long(gb); ++ ++ if ((num_positive_pics + (uint64_t)num_negative_pics) * 2 > get_bits_left(gb)) ++ return AVERROR_INVALIDDATA; ++ ++ num_delta_pocs[rps_idx] = num_negative_pics + num_positive_pics; ++ ++ for (i = 0; i < num_negative_pics; i++) { ++ get_ue_golomb_long(gb); // delta_poc_s0_minus1[rps_idx] ++ skip_bits1 (gb); // used_by_curr_pic_s0_flag[rps_idx] ++ } ++ ++ for (i = 0; i < num_positive_pics; i++) { ++ get_ue_golomb_long(gb); // delta_poc_s1_minus1[rps_idx] ++ skip_bits1 (gb); // used_by_curr_pic_s1_flag[rps_idx] ++ } ++ } ++ ++ return 0; ++} ++ ++static int hvcc_parse_sps(GetBitContext *gb, ++ HEVCDecoderConfigurationRecord *hvcc) ++{ ++ unsigned int i, sps_max_sub_layers_minus1, log2_max_pic_order_cnt_lsb_minus4; ++ unsigned int num_short_term_ref_pic_sets, num_delta_pocs[HEVC_MAX_SHORT_TERM_REF_PIC_SETS]; ++ ++ skip_bits(gb, 4); // sps_video_parameter_set_id ++ ++ sps_max_sub_layers_minus1 = get_bits (gb, 3); ++ ++ /* ++ * numTemporalLayers greater than 1 indicates that the stream to which this ++ * configuration record applies is temporally scalable and the contained ++ * number of temporal layers (also referred to as temporal sub-layer or ++ * sub-layer in ISO/IEC 23008-2) is equal to numTemporalLayers. Value 1 ++ * indicates that the stream is not temporally scalable. Value 0 indicates ++ * that it is unknown whether the stream is temporally scalable. ++ */ ++ hvcc->numTemporalLayers = FFMAX(hvcc->numTemporalLayers, ++ sps_max_sub_layers_minus1 + 1); ++ ++ hvcc->temporalIdNested = get_bits1(gb); ++ ++ hvcc_parse_ptl(gb, hvcc, sps_max_sub_layers_minus1); ++ ++ get_ue_golomb_long(gb); // sps_seq_parameter_set_id ++ ++ hvcc->chromaFormat = get_ue_golomb_long(gb); ++ ++ if (hvcc->chromaFormat == 3) ++ skip_bits1(gb); // separate_colour_plane_flag ++ ++ get_ue_golomb_long(gb); // pic_width_in_luma_samples ++ get_ue_golomb_long(gb); // pic_height_in_luma_samples ++ ++ if (get_bits1(gb)) { // conformance_window_flag ++ get_ue_golomb_long(gb); // conf_win_left_offset ++ get_ue_golomb_long(gb); // conf_win_right_offset ++ get_ue_golomb_long(gb); // conf_win_top_offset ++ get_ue_golomb_long(gb); // conf_win_bottom_offset ++ } ++ ++ hvcc->bitDepthLumaMinus8 = get_ue_golomb_long(gb); ++ hvcc->bitDepthChromaMinus8 = get_ue_golomb_long(gb); ++ log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb_long(gb); ++ ++ /* sps_sub_layer_ordering_info_present_flag */ ++ i = get_bits1(gb) ? 0 : sps_max_sub_layers_minus1; ++ for (; i <= sps_max_sub_layers_minus1; i++) ++ skip_sub_layer_ordering_info(gb); ++ ++ get_ue_golomb_long(gb); // log2_min_luma_coding_block_size_minus3 ++ get_ue_golomb_long(gb); // log2_diff_max_min_luma_coding_block_size ++ get_ue_golomb_long(gb); // log2_min_transform_block_size_minus2 ++ get_ue_golomb_long(gb); // log2_diff_max_min_transform_block_size ++ get_ue_golomb_long(gb); // max_transform_hierarchy_depth_inter ++ get_ue_golomb_long(gb); // max_transform_hierarchy_depth_intra ++ ++ if (get_bits1(gb) && // scaling_list_enabled_flag ++ get_bits1(gb)) // sps_scaling_list_data_present_flag ++ skip_scaling_list_data(gb); ++ ++ skip_bits1(gb); // amp_enabled_flag ++ skip_bits1(gb); // sample_adaptive_offset_enabled_flag ++ ++ if (get_bits1(gb)) { // pcm_enabled_flag ++ skip_bits (gb, 4); // pcm_sample_bit_depth_luma_minus1 ++ skip_bits (gb, 4); // pcm_sample_bit_depth_chroma_minus1 ++ get_ue_golomb_long(gb); // log2_min_pcm_luma_coding_block_size_minus3 ++ get_ue_golomb_long(gb); // log2_diff_max_min_pcm_luma_coding_block_size ++ skip_bits1 (gb); // pcm_loop_filter_disabled_flag ++ } ++ ++ num_short_term_ref_pic_sets = get_ue_golomb_long(gb); ++ if (num_short_term_ref_pic_sets > HEVC_MAX_SHORT_TERM_REF_PIC_SETS) ++ return AVERROR_INVALIDDATA; ++ ++ for (i = 0; i < num_short_term_ref_pic_sets; i++) { ++ int ret = parse_rps(gb, i, num_short_term_ref_pic_sets, num_delta_pocs); ++ if (ret < 0) ++ return ret; ++ } ++ ++ if (get_bits1(gb)) { // long_term_ref_pics_present_flag ++ unsigned num_long_term_ref_pics_sps = get_ue_golomb_long(gb); ++ if (num_long_term_ref_pics_sps > 31U) ++ return AVERROR_INVALIDDATA; ++ for (i = 0; i < num_long_term_ref_pics_sps; i++) { // num_long_term_ref_pics_sps ++ int len = FFMIN(log2_max_pic_order_cnt_lsb_minus4 + 4, 16); ++ skip_bits (gb, len); // lt_ref_pic_poc_lsb_sps[i] ++ skip_bits1(gb); // used_by_curr_pic_lt_sps_flag[i] ++ } ++ } ++ ++ skip_bits1(gb); // sps_temporal_mvp_enabled_flag ++ skip_bits1(gb); // strong_intra_smoothing_enabled_flag ++ ++ if (get_bits1(gb)) // vui_parameters_present_flag ++ hvcc_parse_vui(gb, hvcc, sps_max_sub_layers_minus1); ++ ++ /* nothing useful for hvcC past this point */ ++ return 0; ++} ++ ++static int hvcc_parse_pps(GetBitContext *gb, ++ HEVCDecoderConfigurationRecord *hvcc) ++{ ++ uint8_t tiles_enabled_flag, entropy_coding_sync_enabled_flag; ++ ++ get_ue_golomb_long(gb); // pps_pic_parameter_set_id ++ get_ue_golomb_long(gb); // pps_seq_parameter_set_id ++ ++ /* ++ * dependent_slice_segments_enabled_flag u(1) ++ * output_flag_present_flag u(1) ++ * num_extra_slice_header_bits u(3) ++ * sign_data_hiding_enabled_flag u(1) ++ * cabac_init_present_flag u(1) ++ */ ++ skip_bits(gb, 7); ++ ++ get_ue_golomb_long(gb); // num_ref_idx_l0_default_active_minus1 ++ get_ue_golomb_long(gb); // num_ref_idx_l1_default_active_minus1 ++ get_se_golomb_long(gb); // init_qp_minus26 ++ ++ /* ++ * constrained_intra_pred_flag u(1) ++ * transform_skip_enabled_flag u(1) ++ */ ++ skip_bits(gb, 2); ++ ++ if (get_bits1(gb)) // cu_qp_delta_enabled_flag ++ get_ue_golomb_long(gb); // diff_cu_qp_delta_depth ++ ++ get_se_golomb_long(gb); // pps_cb_qp_offset ++ get_se_golomb_long(gb); // pps_cr_qp_offset ++ ++ /* ++ * pps_slice_chroma_qp_offsets_present_flag u(1) ++ * weighted_pred_flag u(1) ++ * weighted_bipred_flag u(1) ++ * transquant_bypass_enabled_flag u(1) ++ */ ++ skip_bits(gb, 4); ++ ++ tiles_enabled_flag = get_bits1(gb); ++ entropy_coding_sync_enabled_flag = get_bits1(gb); ++ ++ if (entropy_coding_sync_enabled_flag && tiles_enabled_flag) ++ hvcc->parallelismType = 0; // mixed-type parallel decoding ++ else if (entropy_coding_sync_enabled_flag) ++ hvcc->parallelismType = 3; // wavefront-based parallel decoding ++ else if (tiles_enabled_flag) ++ hvcc->parallelismType = 2; // tile-based parallel decoding ++ else ++ hvcc->parallelismType = 1; // slice-based parallel decoding ++ ++ /* nothing useful for hvcC past this point */ ++ return 0; ++} ++ ++static void nal_unit_parse_header(GetBitContext *gb, uint8_t *nal_type) ++{ ++ skip_bits1(gb); // forbidden_zero_bit ++ ++ *nal_type = get_bits(gb, 6); ++ ++ /* ++ * nuh_layer_id u(6) ++ * nuh_temporal_id_plus1 u(3) ++ */ ++ skip_bits(gb, 9); ++} ++ ++static int hvcc_array_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size, ++ uint8_t nal_type, int ps_array_completeness, ++ HEVCDecoderConfigurationRecord *hvcc) ++{ ++ int ret; ++ uint8_t index; ++ uint16_t numNalus; ++ HVCCNALUnitArray *array; ++ ++ for (index = 0; index < hvcc->numOfArrays; index++) ++ if (hvcc->array[index].NAL_unit_type == nal_type) ++ break; ++ ++ if (index >= hvcc->numOfArrays) { ++ uint8_t i; ++ ++ ret = av_reallocp_array(&hvcc->array, index + 1, sizeof(HVCCNALUnitArray)); ++ if (ret < 0) ++ return ret; ++ ++ for (i = hvcc->numOfArrays; i <= index; i++) ++ memset(&hvcc->array[i], 0, sizeof(HVCCNALUnitArray)); ++ hvcc->numOfArrays = index + 1; ++ } ++ ++ array = &hvcc->array[index]; ++ numNalus = array->numNalus; ++ ++ ret = av_reallocp_array(&array->nalUnit, numNalus + 1, sizeof(uint8_t*)); ++ if (ret < 0) ++ return ret; ++ ++ ret = av_reallocp_array(&array->nalUnitLength, numNalus + 1, sizeof(uint16_t)); ++ if (ret < 0) ++ return ret; ++ ++ array->nalUnit [numNalus] = nal_buf; ++ array->nalUnitLength[numNalus] = nal_size; ++ array->NAL_unit_type = nal_type; ++ array->numNalus++; ++ ++ /* ++ * When the sample entry name is ‘hvc1’, the default and mandatory value of ++ * array_completeness is 1 for arrays of all types of parameter sets, and 0 ++ * for all other arrays. When the sample entry name is ‘hev1’, the default ++ * value of array_completeness is 0 for all arrays. ++ */ ++ if (nal_type == HEVC_NAL_VPS || nal_type == HEVC_NAL_SPS || nal_type == HEVC_NAL_PPS) ++ array->array_completeness = ps_array_completeness; ++ ++ return 0; ++} ++ ++static int hvcc_add_nal_unit(uint8_t *nal_buf, uint32_t nal_size, ++ int ps_array_completeness, ++ HEVCDecoderConfigurationRecord *hvcc) ++{ ++ int ret = 0; ++ GetBitContext gbc; ++ uint8_t nal_type; ++ uint8_t *rbsp_buf; ++ uint32_t rbsp_size; ++ ++ rbsp_buf = ff_nal_unit_extract_rbsp(nal_buf, nal_size, &rbsp_size, 2); ++ if (!rbsp_buf) { ++ ret = AVERROR(ENOMEM); ++ goto end; ++ } ++ ++ ret = init_get_bits8(&gbc, rbsp_buf, rbsp_size); ++ if (ret < 0) ++ goto end; ++ ++ nal_unit_parse_header(&gbc, &nal_type); ++ ++ /* ++ * Note: only 'declarative' SEI messages are allowed in ++ * hvcC. Perhaps the SEI playload type should be checked ++ * and non-declarative SEI messages discarded? ++ */ ++ switch (nal_type) { ++ case HEVC_NAL_VPS: ++ case HEVC_NAL_SPS: ++ case HEVC_NAL_PPS: ++ case HEVC_NAL_SEI_PREFIX: ++ case HEVC_NAL_SEI_SUFFIX: ++ ret = hvcc_array_add_nal_unit(nal_buf, nal_size, nal_type, ++ ps_array_completeness, hvcc); ++ if (ret < 0) ++ goto end; ++ else if (nal_type == HEVC_NAL_VPS) ++ ret = hvcc_parse_vps(&gbc, hvcc); ++ else if (nal_type == HEVC_NAL_SPS) ++ ret = hvcc_parse_sps(&gbc, hvcc); ++ else if (nal_type == HEVC_NAL_PPS) ++ ret = hvcc_parse_pps(&gbc, hvcc); ++ if (ret < 0) ++ goto end; ++ break; ++ default: ++ ret = AVERROR_INVALIDDATA; ++ goto end; ++ } ++ ++end: ++ av_free(rbsp_buf); ++ return ret; ++} ++ ++static void hvcc_init(HEVCDecoderConfigurationRecord *hvcc) ++{ ++ memset(hvcc, 0, sizeof(HEVCDecoderConfigurationRecord)); ++ hvcc->configurationVersion = 1; ++ hvcc->lengthSizeMinusOne = 3; // 4 bytes ++ ++ /* ++ * The following fields have all their valid bits set by default, ++ * the ProfileTierLevel parsing code will unset them when needed. ++ */ ++ hvcc->general_profile_compatibility_flags = 0xffffffff; ++ hvcc->general_constraint_indicator_flags = 0xffffffffffff; ++ ++ /* ++ * Initialize this field with an invalid value which can be used to detect ++ * whether we didn't see any VUI (in which case it should be reset to zero). ++ */ ++ hvcc->min_spatial_segmentation_idc = MAX_SPATIAL_SEGMENTATION + 1; ++} ++ ++static void hvcc_close(HEVCDecoderConfigurationRecord *hvcc) ++{ ++ uint8_t i; ++ ++ for (i = 0; i < hvcc->numOfArrays; i++) { ++ hvcc->array[i].numNalus = 0; ++ av_freep(&hvcc->array[i].nalUnit); ++ av_freep(&hvcc->array[i].nalUnitLength); ++ } ++ ++ hvcc->numOfArrays = 0; ++ av_freep(&hvcc->array); ++} ++ ++static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc) ++{ ++ uint8_t i; ++ uint16_t j, vps_count = 0, sps_count = 0, pps_count = 0; ++ ++ /* ++ * We only support writing HEVCDecoderConfigurationRecord version 1. ++ */ ++ hvcc->configurationVersion = 1; ++ ++ /* ++ * If min_spatial_segmentation_idc is invalid, reset to 0 (unspecified). ++ */ ++ if (hvcc->min_spatial_segmentation_idc > MAX_SPATIAL_SEGMENTATION) ++ hvcc->min_spatial_segmentation_idc = 0; ++ ++ /* ++ * parallelismType indicates the type of parallelism that is used to meet ++ * the restrictions imposed by min_spatial_segmentation_idc when the value ++ * of min_spatial_segmentation_idc is greater than 0. ++ */ ++ if (!hvcc->min_spatial_segmentation_idc) ++ hvcc->parallelismType = 0; ++ ++ /* ++ * It's unclear how to properly compute these fields, so ++ * let's always set them to values meaning 'unspecified'. ++ */ ++ hvcc->avgFrameRate = 0; ++ hvcc->constantFrameRate = 0; ++ ++ av_log(NULL, AV_LOG_TRACE, "configurationVersion: %"PRIu8"\n", ++ hvcc->configurationVersion); ++ av_log(NULL, AV_LOG_TRACE, "general_profile_space: %"PRIu8"\n", ++ hvcc->general_profile_space); ++ av_log(NULL, AV_LOG_TRACE, "general_tier_flag: %"PRIu8"\n", ++ hvcc->general_tier_flag); ++ av_log(NULL, AV_LOG_TRACE, "general_profile_idc: %"PRIu8"\n", ++ hvcc->general_profile_idc); ++ av_log(NULL, AV_LOG_TRACE, "general_profile_compatibility_flags: 0x%08"PRIx32"\n", ++ hvcc->general_profile_compatibility_flags); ++ av_log(NULL, AV_LOG_TRACE, "general_constraint_indicator_flags: 0x%012"PRIx64"\n", ++ hvcc->general_constraint_indicator_flags); ++ av_log(NULL, AV_LOG_TRACE, "general_level_idc: %"PRIu8"\n", ++ hvcc->general_level_idc); ++ av_log(NULL, AV_LOG_TRACE, "min_spatial_segmentation_idc: %"PRIu16"\n", ++ hvcc->min_spatial_segmentation_idc); ++ av_log(NULL, AV_LOG_TRACE, "parallelismType: %"PRIu8"\n", ++ hvcc->parallelismType); ++ av_log(NULL, AV_LOG_TRACE, "chromaFormat: %"PRIu8"\n", ++ hvcc->chromaFormat); ++ av_log(NULL, AV_LOG_TRACE, "bitDepthLumaMinus8: %"PRIu8"\n", ++ hvcc->bitDepthLumaMinus8); ++ av_log(NULL, AV_LOG_TRACE, "bitDepthChromaMinus8: %"PRIu8"\n", ++ hvcc->bitDepthChromaMinus8); ++ av_log(NULL, AV_LOG_TRACE, "avgFrameRate: %"PRIu16"\n", ++ hvcc->avgFrameRate); ++ av_log(NULL, AV_LOG_TRACE, "constantFrameRate: %"PRIu8"\n", ++ hvcc->constantFrameRate); ++ av_log(NULL, AV_LOG_TRACE, "numTemporalLayers: %"PRIu8"\n", ++ hvcc->numTemporalLayers); ++ av_log(NULL, AV_LOG_TRACE, "temporalIdNested: %"PRIu8"\n", ++ hvcc->temporalIdNested); ++ av_log(NULL, AV_LOG_TRACE, "lengthSizeMinusOne: %"PRIu8"\n", ++ hvcc->lengthSizeMinusOne); ++ av_log(NULL, AV_LOG_TRACE, "numOfArrays: %"PRIu8"\n", ++ hvcc->numOfArrays); ++ for (i = 0; i < hvcc->numOfArrays; i++) { ++ av_log(NULL, AV_LOG_TRACE, "array_completeness[%"PRIu8"]: %"PRIu8"\n", ++ i, hvcc->array[i].array_completeness); ++ av_log(NULL, AV_LOG_TRACE, "NAL_unit_type[%"PRIu8"]: %"PRIu8"\n", ++ i, hvcc->array[i].NAL_unit_type); ++ av_log(NULL, AV_LOG_TRACE, "numNalus[%"PRIu8"]: %"PRIu16"\n", ++ i, hvcc->array[i].numNalus); ++ for (j = 0; j < hvcc->array[i].numNalus; j++) ++ av_log(NULL, AV_LOG_TRACE, ++ "nalUnitLength[%"PRIu8"][%"PRIu16"]: %"PRIu16"\n", ++ i, j, hvcc->array[i].nalUnitLength[j]); ++ } ++ ++ /* ++ * We need at least one of each: VPS, SPS and PPS. ++ */ ++ for (i = 0; i < hvcc->numOfArrays; i++) ++ switch (hvcc->array[i].NAL_unit_type) { ++ case HEVC_NAL_VPS: ++ vps_count += hvcc->array[i].numNalus; ++ break; ++ case HEVC_NAL_SPS: ++ sps_count += hvcc->array[i].numNalus; ++ break; ++ case HEVC_NAL_PPS: ++ pps_count += hvcc->array[i].numNalus; ++ break; ++ default: ++ break; ++ } ++ if (!vps_count || vps_count > HEVC_MAX_VPS_COUNT || ++ !sps_count || sps_count > HEVC_MAX_SPS_COUNT || ++ !pps_count || pps_count > HEVC_MAX_PPS_COUNT) ++ return AVERROR_INVALIDDATA; ++ ++ /* unsigned int(8) configurationVersion = 1; */ ++ avio_w8(pb, hvcc->configurationVersion); ++ ++ /* ++ * unsigned int(2) general_profile_space; ++ * unsigned int(1) general_tier_flag; ++ * unsigned int(5) general_profile_idc; ++ */ ++ avio_w8(pb, hvcc->general_profile_space << 6 | ++ hvcc->general_tier_flag << 5 | ++ hvcc->general_profile_idc); ++ ++ /* unsigned int(32) general_profile_compatibility_flags; */ ++ avio_wb32(pb, hvcc->general_profile_compatibility_flags); ++ ++ /* unsigned int(48) general_constraint_indicator_flags; */ ++ avio_wb32(pb, hvcc->general_constraint_indicator_flags >> 16); ++ avio_wb16(pb, hvcc->general_constraint_indicator_flags); ++ ++ /* unsigned int(8) general_level_idc; */ ++ avio_w8(pb, hvcc->general_level_idc); ++ ++ /* ++ * bit(4) reserved = ‘1111’b; ++ * unsigned int(12) min_spatial_segmentation_idc; ++ */ ++ avio_wb16(pb, hvcc->min_spatial_segmentation_idc | 0xf000); ++ ++ /* ++ * bit(6) reserved = ‘111111’b; ++ * unsigned int(2) parallelismType; ++ */ ++ avio_w8(pb, hvcc->parallelismType | 0xfc); ++ ++ /* ++ * bit(6) reserved = ‘111111’b; ++ * unsigned int(2) chromaFormat; ++ */ ++ avio_w8(pb, hvcc->chromaFormat | 0xfc); ++ ++ /* ++ * bit(5) reserved = ‘11111’b; ++ * unsigned int(3) bitDepthLumaMinus8; ++ */ ++ avio_w8(pb, hvcc->bitDepthLumaMinus8 | 0xf8); ++ ++ /* ++ * bit(5) reserved = ‘11111’b; ++ * unsigned int(3) bitDepthChromaMinus8; ++ */ ++ avio_w8(pb, hvcc->bitDepthChromaMinus8 | 0xf8); ++ ++ /* bit(16) avgFrameRate; */ ++ avio_wb16(pb, hvcc->avgFrameRate); ++ ++ /* ++ * bit(2) constantFrameRate; ++ * bit(3) numTemporalLayers; ++ * bit(1) temporalIdNested; ++ * unsigned int(2) lengthSizeMinusOne; ++ */ ++ avio_w8(pb, hvcc->constantFrameRate << 6 | ++ hvcc->numTemporalLayers << 3 | ++ hvcc->temporalIdNested << 2 | ++ hvcc->lengthSizeMinusOne); ++ ++ /* unsigned int(8) numOfArrays; */ ++ avio_w8(pb, hvcc->numOfArrays); ++ ++ for (i = 0; i < hvcc->numOfArrays; i++) { ++ /* ++ * bit(1) array_completeness; ++ * unsigned int(1) reserved = 0; ++ * unsigned int(6) NAL_unit_type; ++ */ ++ avio_w8(pb, hvcc->array[i].array_completeness << 7 | ++ hvcc->array[i].NAL_unit_type & 0x3f); ++ ++ /* unsigned int(16) numNalus; */ ++ avio_wb16(pb, hvcc->array[i].numNalus); ++ ++ for (j = 0; j < hvcc->array[i].numNalus; j++) { ++ /* unsigned int(16) nalUnitLength; */ ++ avio_wb16(pb, hvcc->array[i].nalUnitLength[j]); ++ ++ /* bit(8*nalUnitLength) nalUnit; */ ++ avio_write(pb, hvcc->array[i].nalUnit[j], ++ hvcc->array[i].nalUnitLength[j]); ++ } ++ } ++ ++ return 0; ++} ++ ++int ff_hevc_annexb2mp4(AVIOContext *pb, const uint8_t *buf_in, ++ int size, int filter_ps, int *ps_count) ++{ ++ int num_ps = 0, ret = 0; ++ uint8_t *buf, *end, *start = NULL; ++ ++ if (!filter_ps) { ++ ret = ff_avc_parse_nal_units(pb, buf_in, size); ++ goto end; ++ } ++ ++ ret = ff_avc_parse_nal_units_buf(buf_in, &start, &size); ++ if (ret < 0) ++ goto end; ++ ++ ret = 0; ++ buf = start; ++ end = start + size; ++ ++ while (end - buf > 4) { ++ uint32_t len = FFMIN(AV_RB32(buf), end - buf - 4); ++ uint8_t type = (buf[4] >> 1) & 0x3f; ++ ++ buf += 4; ++ ++ switch (type) { ++ case HEVC_NAL_VPS: ++ case HEVC_NAL_SPS: ++ case HEVC_NAL_PPS: ++ num_ps++; ++ break; ++ default: ++ ret += 4 + len; ++ avio_wb32(pb, len); ++ avio_write(pb, buf, len); ++ break; ++ } ++ ++ buf += len; ++ } ++ ++end: ++ av_free(start); ++ if (ps_count) ++ *ps_count = num_ps; ++ return ret; ++} ++ ++int ff_hevc_annexb2mp4_buf(const uint8_t *buf_in, uint8_t **buf_out, ++ int *size, int filter_ps, int *ps_count) ++{ ++ AVIOContext *pb; ++ int ret; ++ ++ ret = avio_open_dyn_buf(&pb); ++ if (ret < 0) ++ return ret; ++ ++ ret = ff_hevc_annexb2mp4(pb, buf_in, *size, filter_ps, ps_count); ++ if (ret < 0) { ++ ffio_free_dyn_buf(&pb); ++ return ret; ++ } ++ ++ *size = avio_close_dyn_buf(pb, buf_out); ++ ++ return 0; ++} ++ ++int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data, ++ int size, int ps_array_completeness) ++{ ++ int ret = 0; ++ uint8_t *buf, *end, *start = NULL; ++ HEVCDecoderConfigurationRecord hvcc; ++ ++ hvcc_init(&hvcc); ++ ++ if (size < 6) { ++ /* We can't write a valid hvcC from the provided data */ ++ ret = AVERROR_INVALIDDATA; ++ goto end; ++ } else if (*data == 1) { ++ /* Data is already hvcC-formatted */ ++ avio_write(pb, data, size); ++ goto end; ++ } else if (!(AV_RB24(data) == 1 || AV_RB32(data) == 1)) { ++ /* Not a valid Annex B start code prefix */ ++ ret = AVERROR_INVALIDDATA; ++ goto end; ++ } ++ ++ ret = ff_avc_parse_nal_units_buf(data, &start, &size); ++ if (ret < 0) ++ goto end; ++ ++ buf = start; ++ end = start + size; ++ ++ while (end - buf > 4) { ++ uint32_t len = FFMIN(AV_RB32(buf), end - buf - 4); ++ uint8_t type = (buf[4] >> 1) & 0x3f; ++ ++ buf += 4; ++ ++ switch (type) { ++ case HEVC_NAL_VPS: ++ case HEVC_NAL_SPS: ++ case HEVC_NAL_PPS: ++ case HEVC_NAL_SEI_PREFIX: ++ case HEVC_NAL_SEI_SUFFIX: ++ ret = hvcc_add_nal_unit(buf, len, ps_array_completeness, &hvcc); ++ if (ret < 0) ++ goto end; ++ break; ++ default: ++ break; ++ } ++ ++ buf += len; ++ } ++ ++ ret = hvcc_write(pb, &hvcc); ++ ++end: ++ hvcc_close(&hvcc); ++ av_free(start); ++ return ret; ++}