From cf823173966fb92d21c08abffc46cd9c8d886109 Mon Sep 17 00:00:00 2001 From: jeffqjiangNew <142832361+jeffqjiangNew@users.noreply.github.com> Date: Thu, 18 Jan 2024 14:31:54 -0500 Subject: [PATCH] Fixed display aspect ratio calculation for both AVC and HEVC. (#187) * * rocDecode: Fixed display aspect ratio calculation. - We were assigning sample aspect ration (SAR) from VUI directly to display aspect ratio (DAR). Now we follow the correct procedure. * * rocDecode: Fixed an error in display aspect ratio calculation. Should include sample aspect ratio in the final step. --- src/parser/avc_parser.cpp | 29 ++++++++++++++++++++++++----- src/parser/hevc_parser.cpp | 28 +++++++++++++++++++++++----- src/parser/roc_video_parser.h | 10 ++++++---- 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/src/parser/avc_parser.cpp b/src/parser/avc_parser.cpp index e5318b1056..1f79bc91e4 100644 --- a/src/parser/avc_parser.cpp +++ b/src/parser/avc_parser.cpp @@ -20,6 +20,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include #include "avc_parser.h" AvcVideoParser::AvcVideoParser() { @@ -228,15 +229,33 @@ ParserResult AvcVideoParser::NotifyNewSps(AvcSeqParameterSet *p_sps) { } video_format_params_.bitrate = 0; + + // Dispaly aspect ratio + // Table E-1. + static const Rational avc_sar[] = { + {0, 0}, // unspecified + {1, 1}, {12, 11}, {10, 11}, {16, 11}, {40, 33}, {24, 11}, {20, 11}, {32, 11}, + {80, 33}, {18, 11}, {15, 11}, {64, 33}, {160, 99}, {4, 3}, {3, 2}, {2, 1}, + }; + Rational sar; + sar.numerator = 1; // set to square pixel if not present or unspecified + sar.denominator = 1; // set to square pixel if not present or unspecified if (p_sps->vui_parameters_present_flag) { if (p_sps->vui_seq_parameters.aspect_ratio_info_present_flag) { - video_format_params_.display_aspect_ratio.x = p_sps->vui_seq_parameters.sar_width; - video_format_params_.display_aspect_ratio.y = p_sps->vui_seq_parameters.sar_height; - } else { // default values - video_format_params_.display_aspect_ratio.x = 0; - video_format_params_.display_aspect_ratio.y = 0; + if (p_sps->vui_seq_parameters.aspect_ratio_idc == 255 /*Extended_SAR*/) { + sar.numerator = p_sps->vui_seq_parameters.sar_width; + sar.denominator = p_sps->vui_seq_parameters.sar_height; + } else if (p_sps->vui_seq_parameters.aspect_ratio_idc > 0 && p_sps->vui_seq_parameters.aspect_ratio_idc < 17) { + sar = avc_sar[p_sps->vui_seq_parameters.aspect_ratio_idc]; + } } } + int disp_width = (video_format_params_.display_area.right - video_format_params_.display_area.left) * sar.numerator; + int disp_height = (video_format_params_.display_area.bottom - video_format_params_.display_area.top) * sar.denominator; + int gcd = std::__gcd(disp_width, disp_height); // greatest common divisor + video_format_params_.display_aspect_ratio.x = disp_width / gcd; + video_format_params_.display_aspect_ratio.y = disp_height / gcd; + if (p_sps->vui_parameters_present_flag) { video_format_params_.video_signal_description.video_format = p_sps->vui_seq_parameters.video_format; video_format_params_.video_signal_description.video_full_range_flag = p_sps->vui_seq_parameters.video_full_range_flag; diff --git a/src/parser/hevc_parser.cpp b/src/parser/hevc_parser.cpp index e2ded97de1..9dffcc8784 100644 --- a/src/parser/hevc_parser.cpp +++ b/src/parser/hevc_parser.cpp @@ -203,15 +203,33 @@ int HevcVideoParser::FillSeqCallbackFn(HevcSeqParamSet* sps_data) { } video_format_params_.bitrate = 0; + + // Dispaly aspect ratio + // Table E-1. + static const Rational hevc_sar[] = { + {0, 0}, // unspecified + {1, 1}, {12, 11}, {10, 11}, {16, 11}, {40, 33}, {24, 11}, {20, 11}, {32, 11}, + {80, 33}, {18, 11}, {15, 11}, {64, 33}, {160, 99}, {4, 3}, {3, 2}, {2, 1}, + }; + Rational sar; + sar.numerator = 1; // set to square pixel if not present or unspecified + sar.denominator = 1; // set to square pixel if not present or unspecified if (sps_data->vui_parameters_present_flag) { if (sps_data->vui_parameters.aspect_ratio_info_present_flag) { - video_format_params_.display_aspect_ratio.x = sps_data->vui_parameters.sar_width; - video_format_params_.display_aspect_ratio.y = sps_data->vui_parameters.sar_height; - } else { // default values - video_format_params_.display_aspect_ratio.x = 0; - video_format_params_.display_aspect_ratio.y = 0; + if (sps_data->vui_parameters.aspect_ratio_idc == 255 /*Extended_SAR*/) { + sar.numerator = sps_data->vui_parameters.sar_width; + sar.denominator = sps_data->vui_parameters.sar_height; + } else if (sps_data->vui_parameters.aspect_ratio_idc > 0 && sps_data->vui_parameters.aspect_ratio_idc < 17) { + sar = hevc_sar[sps_data->vui_parameters.aspect_ratio_idc]; + } } } + int disp_width = (video_format_params_.display_area.right - video_format_params_.display_area.left) * sar.numerator; + int disp_height = (video_format_params_.display_area.bottom - video_format_params_.display_area.top) * sar.denominator; + int gcd = std::__gcd(disp_width, disp_height); // greatest common divisor + video_format_params_.display_aspect_ratio.x = disp_width / gcd; + video_format_params_.display_aspect_ratio.y = disp_height / gcd; + if (sps_data->vui_parameters_present_flag) { video_format_params_.video_signal_description.video_format = sps_data->vui_parameters.video_format; video_format_params_.video_signal_description.video_full_range_flag = sps_data->vui_parameters.video_full_range_flag; diff --git a/src/parser/roc_video_parser.h b/src/parser/roc_video_parser.h index cb5f4c5c9d..c82cd9a810 100644 --- a/src/parser/roc_video_parser.h +++ b/src/parser/roc_video_parser.h @@ -68,6 +68,11 @@ typedef enum ParserResult { PARSER_CODEC_NOT_SUPPORTED ,//codec not supported } ParserResult; +typedef struct { + uint32_t numerator; + uint32_t denominator; +} Rational; + #define ZEROBYTES_SHORTSTARTCODE 2 //indicates the number of zero bytes in the short start-code prefix #define RBSP_BUF_SIZE 1024 // enough to parse any parameter sets or slice headers @@ -101,10 +106,7 @@ protected: uint32_t pic_height_; bool new_sps_activated_; - struct { - uint32_t numerator; - uint32_t denominator; - } frame_rate_; + Rational frame_rate_; RocdecVideoFormat video_format_params_; RocdecSeiMessageInfo sei_message_info_params_;