1 /*
2 * Copyright (c) 2013 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 "test/fake_decoder.h"
12
13 #include <string.h>
14
15 #include <memory>
16
17 #include "api/scoped_refptr.h"
18 #include "api/video/i420_buffer.h"
19 #include "api/video/video_frame.h"
20 #include "api/video/video_frame_buffer.h"
21 #include "api/video/video_rotation.h"
22 #include "modules/video_coding/include/video_error_codes.h"
23 #include "rtc_base/checks.h"
24 #include "rtc_base/task_queue.h"
25 #include "rtc_base/time_utils.h"
26
27 namespace webrtc {
28 namespace test {
29
30 namespace {
31 const int kDefaultWidth = 320;
32 const int kDefaultHeight = 180;
33 } // namespace
34
FakeDecoder()35 FakeDecoder::FakeDecoder() : FakeDecoder(nullptr) {}
36
FakeDecoder(TaskQueueFactory * task_queue_factory)37 FakeDecoder::FakeDecoder(TaskQueueFactory* task_queue_factory)
38 : callback_(nullptr),
39 width_(kDefaultWidth),
40 height_(kDefaultHeight),
41 task_queue_factory_(task_queue_factory),
42 decode_delay_ms_(0) {}
43
InitDecode(const VideoCodec * config,int32_t number_of_cores)44 int32_t FakeDecoder::InitDecode(const VideoCodec* config,
45 int32_t number_of_cores) {
46 return WEBRTC_VIDEO_CODEC_OK;
47 }
48
Decode(const EncodedImage & input,bool missing_frames,int64_t render_time_ms)49 int32_t FakeDecoder::Decode(const EncodedImage& input,
50 bool missing_frames,
51 int64_t render_time_ms) {
52 if (input._encodedWidth > 0 && input._encodedHeight > 0) {
53 width_ = input._encodedWidth;
54 height_ = input._encodedHeight;
55 }
56
57 rtc::scoped_refptr<I420Buffer> buffer = I420Buffer::Create(width_, height_);
58 I420Buffer::SetBlack(buffer);
59 VideoFrame frame = VideoFrame::Builder()
60 .set_video_frame_buffer(buffer)
61 .set_rotation(webrtc::kVideoRotation_0)
62 .set_timestamp_ms(render_time_ms)
63 .build();
64 frame.set_timestamp(input.Timestamp());
65 frame.set_ntp_time_ms(input.ntp_time_ms_);
66
67 if (decode_delay_ms_ == 0 || !task_queue_) {
68 callback_->Decoded(frame);
69 } else {
70 task_queue_->PostDelayedTask(
71 [frame, this]() {
72 VideoFrame copy = frame;
73 callback_->Decoded(copy);
74 },
75 decode_delay_ms_);
76 }
77
78 return WEBRTC_VIDEO_CODEC_OK;
79 }
80
SetDelayedDecoding(int decode_delay_ms)81 void FakeDecoder::SetDelayedDecoding(int decode_delay_ms) {
82 RTC_CHECK(task_queue_factory_);
83 if (!task_queue_) {
84 task_queue_ =
85 std::make_unique<rtc::TaskQueue>(task_queue_factory_->CreateTaskQueue(
86 "fake_decoder", TaskQueueFactory::Priority::NORMAL));
87 }
88 decode_delay_ms_ = decode_delay_ms;
89 }
90
RegisterDecodeCompleteCallback(DecodedImageCallback * callback)91 int32_t FakeDecoder::RegisterDecodeCompleteCallback(
92 DecodedImageCallback* callback) {
93 callback_ = callback;
94 return WEBRTC_VIDEO_CODEC_OK;
95 }
96
Release()97 int32_t FakeDecoder::Release() {
98 return WEBRTC_VIDEO_CODEC_OK;
99 }
100
101 const char* FakeDecoder::kImplementationName = "fake_decoder";
ImplementationName() const102 const char* FakeDecoder::ImplementationName() const {
103 return kImplementationName;
104 }
105
Decode(const EncodedImage & input,bool missing_frames,int64_t render_time_ms)106 int32_t FakeH264Decoder::Decode(const EncodedImage& input,
107 bool missing_frames,
108 int64_t render_time_ms) {
109 uint8_t value = 0;
110 for (size_t i = 0; i < input.size(); ++i) {
111 uint8_t kStartCode[] = {0, 0, 0, 1};
112 if (i < input.size() - sizeof(kStartCode) &&
113 !memcmp(&input.data()[i], kStartCode, sizeof(kStartCode))) {
114 i += sizeof(kStartCode) + 1; // Skip start code and NAL header.
115 }
116 if (input.data()[i] != value) {
117 RTC_CHECK_EQ(value, input.data()[i])
118 << "Bitstream mismatch between sender and receiver.";
119 return -1;
120 }
121 ++value;
122 }
123 return FakeDecoder::Decode(input, missing_frames, render_time_ms);
124 }
125
126 } // namespace test
127 } // namespace webrtc
128