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