| /* |
| * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include <cstddef> |
| #include <cstdint> |
| #include <cstring> |
| #include <memory> |
| #include <optional> |
| #include <utility> |
| |
| #include "api/rtp_packet_infos.h" |
| #include "api/video/encoded_image.h" |
| #include "api/video/video_codec_type.h" |
| #include "api/video/video_content_type.h" |
| #include "api/video/video_frame_type.h" |
| #include "api/video/video_rotation.h" |
| #include "api/video/video_timing.h" |
| #include "modules/rtp_rtcp/source/frame_object.h" |
| #include "modules/rtp_rtcp/source/rtp_video_header.h" |
| #include "modules/video_coding/codecs/h264/include/h264_globals.h" |
| #include "modules/video_coding/codecs/vp8/include/vp8_globals.h" |
| #include "modules/video_coding/codecs/vp9/include/vp9_globals.h" |
| #include "modules/video_coding/rtp_frame_reference_finder.h" |
| #include "test/fuzzers/fuzz_data_helper.h" |
| |
| namespace webrtc { |
| |
| namespace { |
| class DataReader { |
| public: |
| DataReader(FuzzDataHelper fuzz_data) : data_(fuzz_data) {} |
| |
| template <typename T> |
| void CopyTo(T& object) { |
| return data_.CopyTo(object); |
| } |
| |
| template <typename T> |
| T GetNum() { |
| return data_.Read<T>(); |
| } |
| bool MoreToRead() { return data_.BytesLeft() > 0; } |
| |
| private: |
| FuzzDataHelper data_; |
| }; |
| |
| RTPVideoHeaderH264 GenerateRTPVideoHeaderH264(DataReader* reader) { |
| RTPVideoHeaderH264 result; |
| result.nalu_type = reader->GetNum<uint8_t>(); |
| result.packetization_type = reader->GetNum<H264PacketizationTypes>(); |
| int nalus_length = reader->GetNum<uint8_t>(); |
| for (int i = 0; i < nalus_length; ++i) { |
| reader->CopyTo(result.nalus.emplace_back()); |
| } |
| result.packetization_mode = reader->GetNum<H264PacketizationMode>(); |
| return result; |
| } |
| |
| std::optional<RTPVideoHeader::GenericDescriptorInfo> |
| GenerateGenericFrameDependencies(DataReader* reader) { |
| std::optional<RTPVideoHeader::GenericDescriptorInfo> result; |
| uint8_t flags = reader->GetNum<uint8_t>(); |
| if (flags & 0b1000'0000) { |
| // i.e. with 50% chance there are no generic dependencies. |
| // in such case codec-specfic code path of the RtpFrameReferenceFinder will |
| // be validated. |
| return result; |
| } |
| |
| result.emplace(); |
| result->frame_id = reader->GetNum<int32_t>(); |
| result->spatial_index = (flags & 0b0111'0000) >> 4; |
| result->temporal_index = (flags & 0b0000'1110) >> 1; |
| |
| // Larger than supported by the RtpFrameReferenceFinder. |
| int num_diffs = (reader->GetNum<uint8_t>() % 16); |
| for (int i = 0; i < num_diffs; ++i) { |
| result->dependencies.push_back(result->frame_id - |
| (reader->GetNum<uint16_t>() % (1 << 14))); |
| } |
| |
| return result; |
| } |
| } // namespace |
| |
| void FuzzOneInput(FuzzDataHelper fuzz_data) { |
| DataReader reader(fuzz_data); |
| RtpFrameReferenceFinder reference_finder; |
| |
| auto codec = static_cast<VideoCodecType>(reader.GetNum<uint8_t>() % 5); |
| |
| while (reader.MoreToRead()) { |
| uint16_t first_seq_num = reader.GetNum<uint16_t>(); |
| uint16_t last_seq_num = reader.GetNum<uint16_t>(); |
| bool marker_bit = reader.GetNum<uint8_t>(); |
| |
| RTPVideoHeader video_header; |
| switch (reader.GetNum<uint8_t>() % 3) { |
| case 0: |
| video_header.frame_type = VideoFrameType::kEmptyFrame; |
| break; |
| case 1: |
| video_header.frame_type = VideoFrameType::kVideoFrameKey; |
| break; |
| case 2: |
| video_header.frame_type = VideoFrameType::kVideoFrameDelta; |
| break; |
| } |
| |
| switch (codec) { |
| case kVideoCodecVP8: |
| reader.CopyTo( |
| video_header.video_type_header.emplace<RTPVideoHeaderVP8>()); |
| break; |
| case kVideoCodecVP9: |
| reader.CopyTo( |
| video_header.video_type_header.emplace<RTPVideoHeaderVP9>()); |
| break; |
| case kVideoCodecH264: |
| video_header.video_type_header = GenerateRTPVideoHeaderH264(&reader); |
| break; |
| case kVideoCodecH265: |
| // TODO(bugs.webrtc.org/13485) |
| break; |
| default: |
| break; |
| } |
| |
| video_header.generic = GenerateGenericFrameDependencies(&reader); |
| |
| // clang-format off |
| auto frame = std::make_unique<RtpFrameObject>( |
| first_seq_num, |
| last_seq_num, |
| marker_bit, |
| /*times_nacked=*/0, |
| /*first_packet_received_time=*/0, |
| /*last_packet_received_time=*/0, |
| /*rtp_timestamp=*/0, |
| /*ntp_time_ms=*/0, |
| VideoSendTiming(), |
| /*payload_type=*/0, |
| codec, |
| kVideoRotation_0, |
| VideoContentType::UNSPECIFIED, |
| video_header, |
| /*color_space=*/std::nullopt, |
| /*frame_instrumentation_data=*/std::nullopt, |
| RtpPacketInfos(), |
| EncodedImageBuffer::Create(/*size=*/0)); |
| // clang-format on |
| |
| reference_finder.ManageFrame(std::move(frame)); |
| } |
| } |
| |
| } // namespace webrtc |