/* * 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 #include "api/rtp_packet_infos.h" #include "modules/video_coding/frame_object.h" #include "modules/video_coding/rtp_frame_reference_finder.h" namespace webrtc { namespace { class DataReader { public: DataReader(const uint8_t* data, size_t size) : data_(data), size_(size) {} template void CopyTo(T* object) { static_assert(std::is_pod(), ""); uint8_t* destination = reinterpret_cast(object); size_t object_size = sizeof(T); size_t num_bytes = std::min(size_ - offset_, object_size); memcpy(destination, data_ + offset_, num_bytes); offset_ += num_bytes; // If we did not have enough data, fill the rest with 0. object_size -= num_bytes; memset(destination + num_bytes, 0, object_size); } template T GetNum() { T res; if (offset_ + sizeof(res) < size_) { memcpy(&res, data_ + offset_, sizeof(res)); offset_ += sizeof(res); return res; } offset_ = size_; return T(0); } bool MoreToRead() { return offset_ < size_; } private: const uint8_t* data_; size_t size_; size_t offset_ = 0; }; absl::optional GenerateGenericFrameDependencies(DataReader* reader) { absl::optional result; uint8_t flags = reader->GetNum(); 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(); 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() % 16); for (int i = 0; i < num_diffs; ++i) { result->dependencies.push_back(result->frame_id - (reader->GetNum() % (1 << 14))); } return result; } } // namespace void FuzzOneInput(const uint8_t* data, size_t size) { DataReader reader(data, size); RtpFrameReferenceFinder reference_finder; auto codec = static_cast(reader.GetNum() % 5); while (reader.MoreToRead()) { uint16_t first_seq_num = reader.GetNum(); uint16_t last_seq_num = reader.GetNum(); bool marker_bit = reader.GetNum(); RTPVideoHeader video_header; switch (reader.GetNum() % 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()); break; case kVideoCodecVP9: reader.CopyTo( &video_header.video_type_header.emplace()); break; case kVideoCodecH264: reader.CopyTo( &video_header.video_type_header.emplace()); break; default: break; } video_header.generic = GenerateGenericFrameDependencies(&reader); // clang-format off auto frame = std::make_unique( 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=*/absl::nullopt, RtpPacketInfos(), EncodedImageBuffer::Create(/*size=*/0)); // clang-format on reference_finder.ManageFrame(std::move(frame)); } } } // namespace webrtc