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