1 /*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <memory>
12
13 #include "api/rtp_packet_infos.h"
14 #include "modules/video_coding/frame_object.h"
15 #include "modules/video_coding/rtp_frame_reference_finder.h"
16
17 namespace webrtc {
18
19 namespace {
20 class DataReader {
21 public:
DataReader(const uint8_t * data,size_t size)22 DataReader(const uint8_t* data, size_t size) : data_(data), size_(size) {}
23
24 template <typename T>
CopyTo(T * object)25 void CopyTo(T* object) {
26 static_assert(std::is_pod<T>(), "");
27 uint8_t* destination = reinterpret_cast<uint8_t*>(object);
28 size_t object_size = sizeof(T);
29 size_t num_bytes = std::min(size_ - offset_, object_size);
30 memcpy(destination, data_ + offset_, num_bytes);
31 offset_ += num_bytes;
32
33 // If we did not have enough data, fill the rest with 0.
34 object_size -= num_bytes;
35 memset(destination + num_bytes, 0, object_size);
36 }
37
38 template <typename T>
GetNum()39 T GetNum() {
40 T res;
41 if (offset_ + sizeof(res) < size_) {
42 memcpy(&res, data_ + offset_, sizeof(res));
43 offset_ += sizeof(res);
44 return res;
45 }
46
47 offset_ = size_;
48 return T(0);
49 }
50
MoreToRead()51 bool MoreToRead() { return offset_ < size_; }
52
53 private:
54 const uint8_t* data_;
55 size_t size_;
56 size_t offset_ = 0;
57 };
58
59 absl::optional<RTPVideoHeader::GenericDescriptorInfo>
GenerateGenericFrameDependencies(DataReader * reader)60 GenerateGenericFrameDependencies(DataReader* reader) {
61 absl::optional<RTPVideoHeader::GenericDescriptorInfo> result;
62 uint8_t flags = reader->GetNum<uint8_t>();
63 if (flags & 0b1000'0000) {
64 // i.e. with 50% chance there are no generic dependencies.
65 // in such case codec-specfic code path of the RtpFrameReferenceFinder will
66 // be validated.
67 return result;
68 }
69
70 result.emplace();
71 result->frame_id = reader->GetNum<int32_t>();
72 result->spatial_index = (flags & 0b0111'0000) >> 4;
73 result->temporal_index = (flags & 0b0000'1110) >> 1;
74
75 // Larger than supported by the RtpFrameReferenceFinder.
76 int num_diffs = (reader->GetNum<uint8_t>() % 16);
77 for (int i = 0; i < num_diffs; ++i) {
78 result->dependencies.push_back(result->frame_id -
79 (reader->GetNum<uint16_t>() % (1 << 14)));
80 }
81
82 return result;
83 }
84 } // namespace
85
FuzzOneInput(const uint8_t * data,size_t size)86 void FuzzOneInput(const uint8_t* data, size_t size) {
87 DataReader reader(data, size);
88 RtpFrameReferenceFinder reference_finder;
89
90 auto codec = static_cast<VideoCodecType>(reader.GetNum<uint8_t>() % 5);
91
92 while (reader.MoreToRead()) {
93 uint16_t first_seq_num = reader.GetNum<uint16_t>();
94 uint16_t last_seq_num = reader.GetNum<uint16_t>();
95 bool marker_bit = reader.GetNum<uint8_t>();
96
97 RTPVideoHeader video_header;
98 switch (reader.GetNum<uint8_t>() % 3) {
99 case 0:
100 video_header.frame_type = VideoFrameType::kEmptyFrame;
101 break;
102 case 1:
103 video_header.frame_type = VideoFrameType::kVideoFrameKey;
104 break;
105 case 2:
106 video_header.frame_type = VideoFrameType::kVideoFrameDelta;
107 break;
108 }
109
110 switch (codec) {
111 case kVideoCodecVP8:
112 reader.CopyTo(
113 &video_header.video_type_header.emplace<RTPVideoHeaderVP8>());
114 break;
115 case kVideoCodecVP9:
116 reader.CopyTo(
117 &video_header.video_type_header.emplace<RTPVideoHeaderVP9>());
118 break;
119 case kVideoCodecH264:
120 reader.CopyTo(
121 &video_header.video_type_header.emplace<RTPVideoHeaderH264>());
122 break;
123 default:
124 break;
125 }
126
127 video_header.generic = GenerateGenericFrameDependencies(&reader);
128
129 // clang-format off
130 auto frame = std::make_unique<RtpFrameObject>(
131 first_seq_num,
132 last_seq_num,
133 marker_bit,
134 /*times_nacked=*/0,
135 /*first_packet_received_time=*/0,
136 /*last_packet_received_time=*/0,
137 /*rtp_timestamp=*/0,
138 /*ntp_time_ms=*/0,
139 VideoSendTiming(),
140 /*payload_type=*/0,
141 codec,
142 kVideoRotation_0,
143 VideoContentType::UNSPECIFIED,
144 video_header,
145 /*color_space=*/absl::nullopt,
146 RtpPacketInfos(),
147 EncodedImageBuffer::Create(/*size=*/0));
148 // clang-format on
149
150 reference_finder.ManageFrame(std::move(frame));
151 }
152 }
153
154 } // namespace webrtc
155