From b8dce95006838ad3d9818a69e1669ee00ec1b447 Mon Sep 17 00:00:00 2001 From: Danil Chapovalov Date: Mon, 6 Sep 2021 14:18:05 +0200 Subject: [PATCH] Migrate VideoRtpDepacketizerVp9 implementation from BitBuffer to BitstreamReader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new version is subjectivly cleaner and objectively generates smaller binary size Bug: None Change-Id: I662596c41f30690f7e81a51804dd7feb263510c3 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/231130 Reviewed-by: Åsa Persson Commit-Queue: Danil Chapovalov Cr-Commit-Position: refs/heads/main@{#34935} --- modules/rtp_rtcp/BUILD.gn | 1 + .../source/video_rtp_depacketizer_vp9.cc | 187 ++++++------------ 2 files changed, 64 insertions(+), 124 deletions(-) diff --git a/modules/rtp_rtcp/BUILD.gn b/modules/rtp_rtcp/BUILD.gn index f9bc1ffc01..d3f2fe07fb 100644 --- a/modules/rtp_rtcp/BUILD.gn +++ b/modules/rtp_rtcp/BUILD.gn @@ -287,6 +287,7 @@ rtc_library("rtp_rtcp") { "../../logging:rtc_event_audio", "../../logging:rtc_event_rtp_rtcp", "../../modules/audio_coding:audio_coding_module_typedefs", + "../../rtc_base:bitstream_reader", "../../rtc_base:checks", "../../rtc_base:divide_round", "../../rtc_base:gtest_prod", diff --git a/modules/rtp_rtcp/source/video_rtp_depacketizer_vp9.cc b/modules/rtp_rtcp/source/video_rtp_depacketizer_vp9.cc index be05009807..cd5ebe7235 100644 --- a/modules/rtp_rtcp/source/video_rtp_depacketizer_vp9.cc +++ b/modules/rtp_rtcp/source/video_rtp_depacketizer_vp9.cc @@ -15,20 +15,13 @@ #include "api/video/video_codec_constants.h" #include "modules/rtp_rtcp/source/rtp_packet_to_send.h" #include "modules/video_coding/codecs/interface/common_constants.h" -#include "rtc_base/bit_buffer.h" +#include "rtc_base/bitstream_reader.h" #include "rtc_base/checks.h" #include "rtc_base/logging.h" -#define RETURN_FALSE_ON_ERROR(x) \ - if (!(x)) { \ - return false; \ - } - namespace webrtc { namespace { -constexpr int kFailedToParse = 0; - // Picture ID: // // +-+-+-+-+-+-+-+-+ @@ -37,66 +30,37 @@ constexpr int kFailedToParse = 0; // M: | EXTENDED PID | // +-+-+-+-+-+-+-+-+ // -bool ParsePictureId(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { - uint32_t picture_id; - uint32_t m_bit; - RETURN_FALSE_ON_ERROR(parser->ReadBits(1, m_bit)); - if (m_bit) { - RETURN_FALSE_ON_ERROR(parser->ReadBits(15, picture_id)); +void ParsePictureId(BitstreamReader& parser, RTPVideoHeaderVP9* vp9) { + if (parser.ReadBit()) { // m_bit + vp9->picture_id = parser.ReadBits(15); vp9->max_picture_id = kMaxTwoBytePictureId; } else { - RETURN_FALSE_ON_ERROR(parser->ReadBits(7, picture_id)); + vp9->picture_id = parser.ReadBits(7); vp9->max_picture_id = kMaxOneBytePictureId; } - vp9->picture_id = picture_id; - return true; } -// Layer indices (flexible mode): +// Layer indices : // // +-+-+-+-+-+-+-+-+ // L: | T |U| S |D| // +-+-+-+-+-+-+-+-+ -// -bool ParseLayerInfoCommon(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { - uint32_t t, u_bit, s, d_bit; - RETURN_FALSE_ON_ERROR(parser->ReadBits(3, t)); - RETURN_FALSE_ON_ERROR(parser->ReadBits(1, u_bit)); - RETURN_FALSE_ON_ERROR(parser->ReadBits(3, s)); - RETURN_FALSE_ON_ERROR(parser->ReadBits(1, d_bit)); - vp9->temporal_idx = t; - vp9->temporal_up_switch = u_bit ? true : false; - if (s >= kMaxSpatialLayers) - return false; - vp9->spatial_idx = s; - vp9->inter_layer_predicted = d_bit ? true : false; - return true; -} - -// Layer indices (non-flexible mode): -// -// +-+-+-+-+-+-+-+-+ -// L: | T |U| S |D| -// +-+-+-+-+-+-+-+-+ -// | TL0PICIDX | +// | TL0PICIDX | (non-flexible mode only) // +-+-+-+-+-+-+-+-+ // -bool ParseLayerInfoNonFlexibleMode(rtc::BitBuffer* parser, - RTPVideoHeaderVP9* vp9) { - uint8_t tl0picidx; - RETURN_FALSE_ON_ERROR(parser->ReadUInt8(tl0picidx)); - vp9->tl0_pic_idx = tl0picidx; - return true; -} +void ParseLayerInfo(BitstreamReader& parser, RTPVideoHeaderVP9* vp9) { + vp9->temporal_idx = parser.ReadBits(3); + vp9->temporal_up_switch = parser.Read(); + vp9->spatial_idx = parser.ReadBits(3); + vp9->inter_layer_predicted = parser.Read(); + if (vp9->spatial_idx >= kMaxSpatialLayers) { + parser.Invalidate(); + return; + } -bool ParseLayerInfo(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { - if (!ParseLayerInfoCommon(parser, vp9)) - return false; - - if (vp9->flexible_mode) - return true; - - return ParseLayerInfoNonFlexibleMode(parser, vp9); + if (!vp9->flexible_mode) { + vp9->tl0_pic_idx = parser.Read(); + } } // Reference indices: @@ -106,19 +70,22 @@ bool ParseLayerInfo(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { // +-+-+-+-+-+-+-+-+ N=1: An additional P_DIFF follows // current P_DIFF. // -bool ParseRefIndices(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { - if (vp9->picture_id == kNoPictureId) - return false; +void ParseRefIndices(BitstreamReader& parser, RTPVideoHeaderVP9* vp9) { + if (vp9->picture_id == kNoPictureId) { + parser.Invalidate(); + return; + } vp9->num_ref_pics = 0; - uint32_t n_bit; + bool n_bit; do { - if (vp9->num_ref_pics == kMaxVp9RefPics) - return false; + if (vp9->num_ref_pics == kMaxVp9RefPics) { + parser.Invalidate(); + return; + } - uint32_t p_diff; - RETURN_FALSE_ON_ERROR(parser->ReadBits(7, p_diff)); - RETURN_FALSE_ON_ERROR(parser->ReadBits(1, n_bit)); + uint8_t p_diff = parser.ReadBits(7); + n_bit = parser.Read(); vp9->pid_diff[vp9->num_ref_pics] = p_diff; uint32_t scaled_pid = vp9->picture_id; @@ -128,8 +95,6 @@ bool ParseRefIndices(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { } vp9->ref_picture_id[vp9->num_ref_pics++] = scaled_pid - p_diff; } while (n_bit); - - return true; } // Scalability structure (SS). @@ -152,54 +117,40 @@ bool ParseRefIndices(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { // | P_DIFF | (OPTIONAL) . R times . // +-+-+-+-+-+-+-+-+ -| -| // -bool ParseSsData(rtc::BitBuffer* parser, RTPVideoHeaderVP9* vp9) { - uint32_t n_s, y_bit, g_bit; - RETURN_FALSE_ON_ERROR(parser->ReadBits(3, n_s)); - RETURN_FALSE_ON_ERROR(parser->ReadBits(1, y_bit)); - RETURN_FALSE_ON_ERROR(parser->ReadBits(1, g_bit)); - RETURN_FALSE_ON_ERROR(parser->ConsumeBits(3)); - vp9->num_spatial_layers = n_s + 1; - vp9->spatial_layer_resolution_present = y_bit ? true : false; +void ParseSsData(BitstreamReader& parser, RTPVideoHeaderVP9* vp9) { + vp9->num_spatial_layers = parser.ReadBits(3) + 1; + vp9->spatial_layer_resolution_present = parser.Read(); + bool g_bit = parser.Read(); + parser.ConsumeBits(3); vp9->gof.num_frames_in_gof = 0; - if (y_bit) { + if (vp9->spatial_layer_resolution_present) { for (size_t i = 0; i < vp9->num_spatial_layers; ++i) { - RETURN_FALSE_ON_ERROR(parser->ReadUInt16(vp9->width[i])); - RETURN_FALSE_ON_ERROR(parser->ReadUInt16(vp9->height[i])); + vp9->width[i] = parser.Read(); + vp9->height[i] = parser.Read(); } } if (g_bit) { - uint8_t n_g; - RETURN_FALSE_ON_ERROR(parser->ReadUInt8(n_g)); - vp9->gof.num_frames_in_gof = n_g; + vp9->gof.num_frames_in_gof = parser.Read(); } for (size_t i = 0; i < vp9->gof.num_frames_in_gof; ++i) { - uint32_t t, u_bit, r; - RETURN_FALSE_ON_ERROR(parser->ReadBits(3, t)); - RETURN_FALSE_ON_ERROR(parser->ReadBits(1, u_bit)); - RETURN_FALSE_ON_ERROR(parser->ReadBits(2, r)); - RETURN_FALSE_ON_ERROR(parser->ConsumeBits(2)); - vp9->gof.temporal_idx[i] = t; - vp9->gof.temporal_up_switch[i] = u_bit ? true : false; - vp9->gof.num_ref_pics[i] = r; + vp9->gof.temporal_idx[i] = parser.ReadBits(3); + vp9->gof.temporal_up_switch[i] = parser.Read(); + vp9->gof.num_ref_pics[i] = parser.ReadBits(2); + parser.ConsumeBits(2); for (uint8_t p = 0; p < vp9->gof.num_ref_pics[i]; ++p) { - uint8_t p_diff; - RETURN_FALSE_ON_ERROR(parser->ReadUInt8(p_diff)); - vp9->gof.pid_diff[i][p] = p_diff; + vp9->gof.pid_diff[i][p] = parser.Read(); } } - return true; } } // namespace absl::optional VideoRtpDepacketizerVp9::Parse(rtc::CopyOnWriteBuffer rtp_payload) { - rtc::ArrayView payload(rtp_payload.cdata(), - rtp_payload.size()); absl::optional result(absl::in_place); - int offset = ParseRtpPayload(payload, &result->video_header); - if (offset == kFailedToParse) + int offset = ParseRtpPayload(rtp_payload, &result->video_header); + if (offset == 0) return absl::nullopt; RTC_DCHECK_LT(offset, rtp_payload.size()); result->video_payload = @@ -212,12 +163,8 @@ int VideoRtpDepacketizerVp9::ParseRtpPayload( RTPVideoHeader* video_header) { RTC_DCHECK(video_header); // Parse mandatory first byte of payload descriptor. - rtc::BitBuffer parser(rtp_payload.data(), rtp_payload.size()); - uint8_t first_byte; - if (!parser.ReadUInt8(first_byte)) { - RTC_LOG(LS_ERROR) << "Payload length is zero."; - return kFailedToParse; - } + BitstreamReader parser(rtp_payload); + uint8_t first_byte = parser.Read(); bool i_bit = first_byte & 0b1000'0000; // PictureId present . bool p_bit = first_byte & 0b0100'0000; // Inter-picture predicted. bool l_bit = first_byte & 0b0010'0000; // Layer indices present. @@ -247,23 +194,17 @@ int VideoRtpDepacketizerVp9::ParseRtpPayload( vp9_header.non_ref_for_inter_layer_pred = z_bit; // Parse fields that are present. - if (i_bit && !ParsePictureId(&parser, &vp9_header)) { - RTC_LOG(LS_ERROR) << "Failed parsing VP9 picture id."; - return kFailedToParse; + if (i_bit) { + ParsePictureId(parser, &vp9_header); } - if (l_bit && !ParseLayerInfo(&parser, &vp9_header)) { - RTC_LOG(LS_ERROR) << "Failed parsing VP9 layer info."; - return kFailedToParse; + if (l_bit) { + ParseLayerInfo(parser, &vp9_header); } - if (p_bit && f_bit && !ParseRefIndices(&parser, &vp9_header)) { - RTC_LOG(LS_ERROR) << "Failed parsing VP9 ref indices."; - return kFailedToParse; + if (p_bit && f_bit) { + ParseRefIndices(parser, &vp9_header); } if (v_bit) { - if (!ParseSsData(&parser, &vp9_header)) { - RTC_LOG(LS_ERROR) << "Failed parsing VP9 SS data."; - return kFailedToParse; - } + ParseSsData(parser, &vp9_header); if (vp9_header.spatial_layer_resolution_present) { // TODO(asapersson): Add support for spatial layers. video_header->width = vp9_header.width[0]; @@ -273,15 +214,13 @@ int VideoRtpDepacketizerVp9::ParseRtpPayload( video_header->is_first_packet_in_frame = b_bit && (!l_bit || !vp9_header.inter_layer_predicted); - size_t byte_offset; - size_t bit_offset; - parser.GetCurrentOffset(&byte_offset, &bit_offset); - RTC_DCHECK_EQ(bit_offset, 0); - if (byte_offset == rtp_payload.size()) { - // Empty vp9 payload data. - return kFailedToParse; + int num_remaining_bits = parser.RemainingBitCount(); + if (num_remaining_bits <= 0) { + // Failed to parse or empty vp9 payload data. + return 0; } - - return byte_offset; + // vp9 descriptor is byte aligned. + RTC_DCHECK_EQ(num_remaining_bits % 8, 0); + return rtp_payload.size() - num_remaining_bits / 8; } } // namespace webrtc