| /* |
| * Copyright (c) 2017 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 <memory> |
| |
| #include "api/task_queue/task_queue_base.h" |
| #include "modules/video_coding/frame_buffer2.h" |
| #include "modules/video_coding/timing/timing.h" |
| #include "test/scoped_key_value_config.h" |
| #include "test/time_controller/simulated_time_controller.h" |
| |
| namespace webrtc { |
| |
| namespace { |
| |
| // When DataReader runs out of data provided in the constructor it will |
| // just set/return 0 instead. |
| struct DataReader { |
| DataReader(const uint8_t* data, size_t size) : data_(data), size_(size) {} |
| |
| void CopyTo(void* destination, size_t dest_size) { |
| memset(destination, 0, dest_size); |
| |
| size_t bytes_to_copy = std::min(size_ - offset_, dest_size); |
| memcpy(destination, data_ + offset_, bytes_to_copy); |
| offset_ += bytes_to_copy; |
| } |
| |
| template <typename T> |
| 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_; } |
| |
| const uint8_t* const data_; |
| size_t size_; |
| size_t offset_ = 0; |
| }; |
| |
| class FuzzyFrameObject : public EncodedFrame { |
| public: |
| FuzzyFrameObject() {} |
| ~FuzzyFrameObject() {} |
| |
| int64_t ReceivedTime() const override { return 0; } |
| int64_t RenderTime() const override { return _renderTimeMs; } |
| }; |
| } // namespace |
| |
| void FuzzOneInput(const uint8_t* data, size_t size) { |
| if (size > 10000) { |
| return; |
| } |
| DataReader reader(data, size); |
| GlobalSimulatedTimeController time_controller(Timestamp::Seconds(0)); |
| std::unique_ptr<TaskQueueBase, TaskQueueDeleter> task_queue = |
| time_controller.GetTaskQueueFactory()->CreateTaskQueue( |
| "time_tq", TaskQueueFactory::Priority::NORMAL); |
| test::ScopedKeyValueConfig field_trials; |
| VCMTiming timing(time_controller.GetClock(), field_trials); |
| video_coding::FrameBuffer frame_buffer(time_controller.GetClock(), &timing, |
| nullptr, field_trials); |
| |
| bool next_frame_task_running = false; |
| |
| while (reader.MoreToRead()) { |
| if (reader.GetNum<uint8_t>() % 2) { |
| std::unique_ptr<FuzzyFrameObject> frame(new FuzzyFrameObject()); |
| frame->SetId(reader.GetNum<int64_t>()); |
| frame->SetSpatialIndex(reader.GetNum<uint8_t>() % 5); |
| frame->SetTimestamp(reader.GetNum<uint32_t>()); |
| frame->num_references = |
| reader.GetNum<uint8_t>() % EncodedFrame::kMaxFrameReferences; |
| |
| for (size_t r = 0; r < frame->num_references; ++r) |
| frame->references[r] = reader.GetNum<int64_t>(); |
| |
| frame_buffer.InsertFrame(std::move(frame)); |
| } else { |
| if (!next_frame_task_running) { |
| next_frame_task_running = true; |
| bool keyframe_required = reader.GetNum<uint8_t>() % 2; |
| int max_wait_time_ms = reader.GetNum<uint8_t>(); |
| task_queue->PostTask([&task_queue, &frame_buffer, |
| &next_frame_task_running, keyframe_required, |
| max_wait_time_ms] { |
| frame_buffer.NextFrame( |
| max_wait_time_ms, keyframe_required, task_queue.get(), |
| [&next_frame_task_running](std::unique_ptr<EncodedFrame> frame) { |
| next_frame_task_running = false; |
| }); |
| }); |
| } |
| } |
| |
| time_controller.AdvanceTime(TimeDelta::Millis(reader.GetNum<uint8_t>())); |
| } |
| } |
| |
| } // namespace webrtc |