From 28bcaf876c196a261e55d7cff7bbf6b274868a21 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Tue, 6 Jul 2021 09:52:13 +0200 Subject: [PATCH] MPEG 1/2 packetizer: use rationals for calculation of aspect ratio --- src/common/mpeg1_2.cpp | 34 ++++++++++++---------------------- src/common/mpeg1_2.h | 4 +++- src/output/p_mpeg1_2.cpp | 8 ++++---- 3 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/common/mpeg1_2.cpp b/src/common/mpeg1_2.cpp index 12d142c29..eacc50818 100644 --- a/src/common/mpeg1_2.cpp +++ b/src/common/mpeg1_2.cpp @@ -75,17 +75,16 @@ extract_fps_idx(unsigned char const *buffer, \return \c true if a MPEG sequence header was found and \c false otherwise. */ -bool -extract_ar(unsigned char const *buffer, - int buffer_size, - double &ar) { +std::optional +extract_aspect_ratio(unsigned char const *buffer, + int buffer_size) { uint32_t marker; int idx; mxdebug_if(s_debug, fmt::format("mpeg_video_ar: start search in {0} bytes\n", buffer_size)); if (buffer_size < 8) { mxdebug_if(s_debug, "mpeg_video_ar: sequence header too small\n"); - return false; + return {}; } marker = get_uint32_be(buffer); idx = 4; @@ -96,33 +95,24 @@ extract_ar(unsigned char const *buffer, } if (idx >= buffer_size) { mxdebug_if(s_debug, "mpeg_video_ar: no sequence header start code found\n"); - return false; + return {}; } mxdebug_if(s_debug, fmt::format("mpeg_video_ar: found sequence header start code at {0}\n", idx - 4)); idx += 3; // width and height if (idx >= buffer_size) { mxdebug_if(s_debug, "mpeg_video_ar: sequence header too small\n"); - return false; + return {}; } switch (buffer[idx] & 0xf0) { - case AR_1_1: - ar = 1.0; - break; - case AR_4_3: - ar = 4.0 / 3.0; - break; - case AR_16_9: - ar = 16.0 / 9.0; - break; - case AR_2_21: - ar = 2.21; - break; - default: - ar = -1.0; + case AR_1_1: return mtx::rational(1, 1); + case AR_4_3: return mtx::rational(4, 3); + case AR_16_9: return mtx::rational(16, 9); + case AR_2_21: return mtx::rational(221, 100); } - return true; + + return {}; } /** \brief Get the number of frames per second diff --git a/src/common/mpeg1_2.h b/src/common/mpeg1_2.h index 298e76cf9..3fd97eba5 100644 --- a/src/common/mpeg1_2.h +++ b/src/common/mpeg1_2.h @@ -16,6 +16,8 @@ #include "common/common_pch.h" +#include "common/math_fwd.h" + namespace mtx::mpeg1_2 { // MPEG-1/-2 video start codes @@ -65,7 +67,7 @@ constexpr auto FOURCC_MPEG2 = 0x10000002u; int extract_fps_idx(const unsigned char *buffer, int buffer_size); double get_fps(int idx); -bool extract_ar(const unsigned char *buffer, int buffer_size, double &ar); +std::optional extract_aspect_ratio(const unsigned char *buffer, int buffer_size); bool is_fourcc(uint32_t fourcc); } diff --git a/src/output/p_mpeg1_2.cpp b/src/output/p_mpeg1_2.cpp index be1b9a53d..8b6de855b 100644 --- a/src/output/p_mpeg1_2.cpp +++ b/src/output/p_mpeg1_2.cpp @@ -271,15 +271,15 @@ mpeg1_2_video_packetizer_c::extract_fps(const unsigned char *buffer, void mpeg1_2_video_packetizer_c::extract_aspect_ratio(const unsigned char *buffer, int size) { - double ar; - if (display_dimensions_or_aspect_ratio_set()) return; - if (!mtx::mpeg1_2::extract_ar(buffer, size, ar)) + auto aspect_ratio = mtx::mpeg1_2::extract_aspect_ratio(buffer, size); + + if (!aspect_ratio) return; - set_video_display_dimensions((0 >= ar) || (1 == ar) ? m_width : (int)(m_height * ar), m_height, generic_packetizer_c::ddu_pixels, OPTION_SOURCE_BITSTREAM); + set_video_display_dimensions(1 == *aspect_ratio ? m_width : mtx::to_int(m_height * *aspect_ratio), m_height, generic_packetizer_c::ddu_pixels, OPTION_SOURCE_BITSTREAM); rerender_track_headers(); m_aspect_ratio_extracted = true;