diff --git a/common_video/h264/h264_bitstream_parser.cc b/common_video/h264/h264_bitstream_parser.cc index 5a75f48f88..b0ada92d74 100644 --- a/common_video/h264/h264_bitstream_parser.cc +++ b/common_video/h264/h264_bitstream_parser.cc @@ -296,35 +296,24 @@ void H264BitstreamParser::ParseSlice(const uint8_t* slice, size_t length) { } } -void H264BitstreamParser::ParseBitstream(const uint8_t* bitstream, - size_t length) { - std::vector nalu_indices = - H264::FindNaluIndices(bitstream, length); - for (const H264::NaluIndex& index : nalu_indices) - ParseSlice(&bitstream[index.payload_start_offset], index.payload_size); -} - -bool H264BitstreamParser::GetLastSliceQp(int* qp) const { - if (!last_slice_qp_delta_ || !pps_) - return false; - const int parsed_qp = 26 + pps_->pic_init_qp_minus26 + *last_slice_qp_delta_; - if (parsed_qp < kMinQpValue || parsed_qp > kMaxQpValue) { - RTC_LOG(LS_ERROR) << "Parsed invalid QP from bitstream."; - return false; - } - *qp = parsed_qp; - return true; -} - void H264BitstreamParser::ParseBitstream( rtc::ArrayView bitstream) { - ParseBitstream(bitstream.data(), bitstream.size()); + std::vector nalu_indices = + H264::FindNaluIndices(bitstream.data(), bitstream.size()); + for (const H264::NaluIndex& index : nalu_indices) + ParseSlice(bitstream.data() + index.payload_start_offset, + index.payload_size); } absl::optional H264BitstreamParser::GetLastSliceQp() const { - int qp; - bool success = GetLastSliceQp(&qp); - return success ? absl::optional(qp) : absl::nullopt; + if (!last_slice_qp_delta_ || !pps_) + return absl::nullopt; + const int qp = 26 + pps_->pic_init_qp_minus26 + *last_slice_qp_delta_; + if (qp < kMinQpValue || qp > kMaxQpValue) { + RTC_LOG(LS_ERROR) << "Parsed invalid QP from bitstream."; + return absl::nullopt; + } + return qp; } } // namespace webrtc diff --git a/common_video/h264/h264_bitstream_parser.h b/common_video/h264/h264_bitstream_parser.h index 48190665f0..05427825ac 100644 --- a/common_video/h264/h264_bitstream_parser.h +++ b/common_video/h264/h264_bitstream_parser.h @@ -31,11 +31,6 @@ class H264BitstreamParser : public BitstreamParser { H264BitstreamParser(); ~H264BitstreamParser() override; - // These are here for backwards-compatability for the time being. - void ParseBitstream(const uint8_t* bitstream, size_t length); - bool GetLastSliceQp(int* qp) const; - - // New interface. void ParseBitstream(rtc::ArrayView bitstream) override; absl::optional GetLastSliceQp() const override; diff --git a/common_video/h264/h264_bitstream_parser_unittest.cc b/common_video/h264/h264_bitstream_parser_unittest.cc index 1509d67753..3f4f202af2 100644 --- a/common_video/h264/h264_bitstream_parser_unittest.cc +++ b/common_video/h264/h264_bitstream_parser_unittest.cc @@ -46,43 +46,39 @@ uint8_t kH264BitstreamNextImageSliceChunkCabac[] = { TEST(H264BitstreamParserTest, ReportsNoQpWithoutParsedSlices) { H264BitstreamParser h264_parser; - int qp; - EXPECT_FALSE(h264_parser.GetLastSliceQp(&qp)); + EXPECT_FALSE(h264_parser.GetLastSliceQp().has_value()); } TEST(H264BitstreamParserTest, ReportsNoQpWithOnlyParsedPpsAndSpsSlices) { H264BitstreamParser h264_parser; - h264_parser.ParseBitstream(kH264SpsPps, sizeof(kH264SpsPps)); - int qp; - EXPECT_FALSE(h264_parser.GetLastSliceQp(&qp)); + h264_parser.ParseBitstream(kH264SpsPps); + EXPECT_FALSE(h264_parser.GetLastSliceQp().has_value()); } TEST(H264BitstreamParserTest, ReportsLastSliceQpForImageSlices) { H264BitstreamParser h264_parser; - h264_parser.ParseBitstream(kH264BitstreamChunk, sizeof(kH264BitstreamChunk)); - int qp; - ASSERT_TRUE(h264_parser.GetLastSliceQp(&qp)); - EXPECT_EQ(35, qp); + h264_parser.ParseBitstream(kH264BitstreamChunk); + absl::optional qp = h264_parser.GetLastSliceQp(); + ASSERT_TRUE(qp.has_value()); + EXPECT_EQ(35, *qp); // Parse an additional image slice. - h264_parser.ParseBitstream(kH264BitstreamNextImageSliceChunk, - sizeof(kH264BitstreamNextImageSliceChunk)); - ASSERT_TRUE(h264_parser.GetLastSliceQp(&qp)); - EXPECT_EQ(37, qp); + h264_parser.ParseBitstream(kH264BitstreamNextImageSliceChunk); + qp = h264_parser.GetLastSliceQp(); + ASSERT_TRUE(qp.has_value()); + EXPECT_EQ(37, *qp); } TEST(H264BitstreamParserTest, ReportsLastSliceQpForCABACImageSlices) { H264BitstreamParser h264_parser; - h264_parser.ParseBitstream(kH264BitstreamChunkCabac, - sizeof(kH264BitstreamChunkCabac)); - int qp; - EXPECT_FALSE(h264_parser.GetLastSliceQp(&qp)); + h264_parser.ParseBitstream(kH264BitstreamChunkCabac); + EXPECT_FALSE(h264_parser.GetLastSliceQp().has_value()); // Parse an additional image slice. - h264_parser.ParseBitstream(kH264BitstreamNextImageSliceChunkCabac, - sizeof(kH264BitstreamNextImageSliceChunkCabac)); - ASSERT_TRUE(h264_parser.GetLastSliceQp(&qp)); - EXPECT_EQ(24, qp); + h264_parser.ParseBitstream(kH264BitstreamNextImageSliceChunkCabac); + absl::optional qp = h264_parser.GetLastSliceQp(); + ASSERT_TRUE(qp.has_value()); + EXPECT_EQ(24, *qp); } } // namespace webrtc diff --git a/modules/video_coding/codecs/h264/h264_decoder_impl.cc b/modules/video_coding/codecs/h264/h264_decoder_impl.cc index 9002b87461..8c7a39b609 100644 --- a/modules/video_coding/codecs/h264/h264_decoder_impl.cc +++ b/modules/video_coding/codecs/h264/h264_decoder_impl.cc @@ -294,13 +294,9 @@ int32_t H264DecoderImpl::Decode(const EncodedImage& input_image, // the input one. RTC_DCHECK_EQ(av_frame_->reordered_opaque, frame_timestamp_us); - absl::optional qp; // TODO(sakal): Maybe it is possible to get QP directly from FFmpeg. - h264_bitstream_parser_.ParseBitstream(input_image.data(), input_image.size()); - int qp_int; - if (h264_bitstream_parser_.GetLastSliceQp(&qp_int)) { - qp.emplace(qp_int); - } + h264_bitstream_parser_.ParseBitstream(input_image); + absl::optional qp = h264_bitstream_parser_.GetLastSliceQp(); // Obtain the |video_frame| containing the decoded image. VideoFrame* input_frame = diff --git a/modules/video_coding/codecs/h264/h264_encoder_impl.cc b/modules/video_coding/codecs/h264/h264_encoder_impl.cc index ea784c19ef..3f4f660ffa 100644 --- a/modules/video_coding/codecs/h264/h264_encoder_impl.cc +++ b/modules/video_coding/codecs/h264/h264_encoder_impl.cc @@ -481,9 +481,9 @@ int32_t H264EncoderImpl::Encode( // |encoded_images_[i]._length| == 0. if (encoded_images_[i].size() > 0) { // Parse QP. - h264_bitstream_parser_.ParseBitstream(encoded_images_[i].data(), - encoded_images_[i].size()); - h264_bitstream_parser_.GetLastSliceQp(&encoded_images_[i].qp_); + h264_bitstream_parser_.ParseBitstream(encoded_images_[i]); + encoded_images_[i].qp_ = + h264_bitstream_parser_.GetLastSliceQp().value_or(-1); // Deliver encoded image. CodecSpecificInfo codec_specific; diff --git a/sdk/android/src/jni/video_decoder_wrapper.cc b/sdk/android/src/jni/video_decoder_wrapper.cc index 3aa18abbd7..4eb70f7fcc 100644 --- a/sdk/android/src/jni/video_decoder_wrapper.cc +++ b/sdk/android/src/jni/video_decoder_wrapper.cc @@ -249,12 +249,8 @@ absl::optional VideoDecoderWrapper::ParseQP( break; } case kVideoCodecH264: { - h264_bitstream_parser_.ParseBitstream(input_image.data(), - input_image.size()); - int qp_int; - if (h264_bitstream_parser_.GetLastSliceQp(&qp_int)) { - qp = qp_int; - } + h264_bitstream_parser_.ParseBitstream(input_image); + qp = h264_bitstream_parser_.GetLastSliceQp(); break; } default: diff --git a/sdk/android/src/jni/video_encoder_wrapper.cc b/sdk/android/src/jni/video_encoder_wrapper.cc index 3bdfdc3d35..4a1faeb0bd 100644 --- a/sdk/android/src/jni/video_encoder_wrapper.cc +++ b/sdk/android/src/jni/video_encoder_wrapper.cc @@ -309,8 +309,9 @@ int VideoEncoderWrapper::ParseQp(rtc::ArrayView buffer) { success = vp9::GetQp(buffer.data(), buffer.size(), &qp); break; case kVideoCodecH264: - h264_bitstream_parser_.ParseBitstream(buffer.data(), buffer.size()); - success = h264_bitstream_parser_.GetLastSliceQp(&qp); + h264_bitstream_parser_.ParseBitstream(buffer); + qp = h264_bitstream_parser_.GetLastSliceQp().value_or(-1); + success = (qp >= 0); break; default: // Default is to not provide QP. success = false; diff --git a/sdk/objc/components/video_codec/RTCVideoEncoderH264.mm b/sdk/objc/components/video_codec/RTCVideoEncoderH264.mm index 03a792672c..01d48c1749 100644 --- a/sdk/objc/components/video_codec/RTCVideoEncoderH264.mm +++ b/sdk/objc/components/video_codec/RTCVideoEncoderH264.mm @@ -802,10 +802,8 @@ NSUInteger GetMaxSampleRate(const webrtc::H264::ProfileLevelId &profile_level_id RTCVideoContentTypeUnspecified; frame.flags = webrtc::VideoSendTiming::kInvalid; - int qp; - _h264BitstreamParser.ParseBitstream(buffer->data(), buffer->size()); - _h264BitstreamParser.GetLastSliceQp(&qp); - frame.qp = @(qp); + _h264BitstreamParser.ParseBitstream(*buffer); + frame.qp = @(_h264BitstreamParser.GetLastSliceQp().value_or(-1)); BOOL res = _callback(frame, codecSpecificInfo); if (!res) { diff --git a/test/fuzzers/h264_bitstream_parser_fuzzer.cc b/test/fuzzers/h264_bitstream_parser_fuzzer.cc index a9384d73f3..cd1128c0b4 100644 --- a/test/fuzzers/h264_bitstream_parser_fuzzer.cc +++ b/test/fuzzers/h264_bitstream_parser_fuzzer.cc @@ -14,8 +14,8 @@ namespace webrtc { void FuzzOneInput(const uint8_t* data, size_t size) { H264BitstreamParser h264_bitstream_parser; - h264_bitstream_parser.ParseBitstream(data, size); - int qp; - h264_bitstream_parser.GetLastSliceQp(&qp); + h264_bitstream_parser.ParseBitstream( + rtc::ArrayView(data, size)); + h264_bitstream_parser.GetLastSliceQp(); } } // namespace webrtc