blob: bc23c32dd2987395c5d74f8cb595b108a2cea1b3 [file] [log] [blame]
stefan@webrtc.org360e3762013-08-22 09:29:56 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "test/fake_encoder.h"
stefan@webrtc.org360e3762013-08-22 09:29:56 +000012
brandtre78d2662017-01-16 05:57:16 -080013#include <string.h>
14
palmkviste75f2042016-09-28 06:19:48 -070015#include <algorithm>
brandtre78d2662017-01-16 05:57:16 -080016#include <memory>
palmkviste75f2042016-09-28 06:19:48 -070017
Mirko Bonadei71207422017-09-15 13:58:09 +020018#include "common_types.h" // NOLINT(build/include)
Erik Språng8abd56c2018-10-01 18:47:03 +020019#include "modules/video_coding/codecs/vp8/include/vp8_temporal_layers.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "modules/video_coding/include/video_codec_interface.h"
21#include "rtc_base/checks.h"
22#include "system_wrappers/include/sleep.h"
pbos@webrtc.orgab990ae2014-09-17 09:02:25 +000023
stefan@webrtc.org360e3762013-08-22 09:29:56 +000024namespace webrtc {
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +000025namespace test {
stefan@webrtc.org360e3762013-08-22 09:29:56 +000026
sprang4847ae62017-06-27 07:06:52 -070027const int kKeyframeSizeFactor = 10;
28
stefan@webrtc.org360e3762013-08-22 09:29:56 +000029FakeEncoder::FakeEncoder(Clock* clock)
30 : clock_(clock),
brandtre78d2662017-01-16 05:57:16 -080031 callback_(nullptr),
sprang4847ae62017-06-27 07:06:52 -070032 configured_input_framerate_(-1),
pbos@webrtc.org3349ae02014-03-13 12:52:27 +000033 max_target_bitrate_kbps_(-1),
sprang4847ae62017-06-27 07:06:52 -070034 pending_keyframe_(true),
35 debt_bytes_(0) {
sprang@webrtc.org40709352013-11-26 11:41:59 +000036 // Generate some arbitrary not-all-zero data
37 for (size_t i = 0; i < sizeof(encoded_buffer_); ++i) {
38 encoded_buffer_[i] = static_cast<uint8_t>(i);
39 }
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +020040 for (bool& used : used_layers_) {
41 used = false;
42 }
stefan@webrtc.org360e3762013-08-22 09:29:56 +000043}
44
pbos@webrtc.org3349ae02014-03-13 12:52:27 +000045void FakeEncoder::SetMaxBitrate(int max_kbps) {
perkj26091b12016-09-01 01:17:40 -070046 RTC_DCHECK_GE(max_kbps, -1); // max_kbps == -1 disables it.
brandtre78d2662017-01-16 05:57:16 -080047 rtc::CritScope cs(&crit_sect_);
pbos@webrtc.org3349ae02014-03-13 12:52:27 +000048 max_target_bitrate_kbps_ = max_kbps;
49}
50
stefan@webrtc.org360e3762013-08-22 09:29:56 +000051int32_t FakeEncoder::InitEncode(const VideoCodec* config,
52 int32_t number_of_cores,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000053 size_t max_payload_size) {
brandtre78d2662017-01-16 05:57:16 -080054 rtc::CritScope cs(&crit_sect_);
stefan@webrtc.org360e3762013-08-22 09:29:56 +000055 config_ = *config;
Erik Språng08127a92016-11-16 16:41:30 +010056 target_bitrate_.SetBitrate(0, 0, config_.startBitrate * 1000);
sprang4847ae62017-06-27 07:06:52 -070057 configured_input_framerate_ = config_.maxFramerate;
58 pending_keyframe_ = true;
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +020059 last_frame_info_ = FrameInfo();
stefan@webrtc.org360e3762013-08-22 09:29:56 +000060 return 0;
61}
62
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070063int32_t FakeEncoder::Encode(const VideoFrame& input_image,
64 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -070065 const std::vector<FrameType>* frame_types) {
brandtre78d2662017-01-16 05:57:16 -080066 unsigned char max_framerate;
67 unsigned char num_simulcast_streams;
68 SimulcastStream simulcast_streams[kMaxSimulcastStreams];
69 EncodedImageCallback* callback;
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +020070 VideoBitrateAllocation target_bitrate;
sprang4847ae62017-06-27 07:06:52 -070071 int framerate;
ilnik00d802b2017-04-11 10:34:31 -070072 VideoCodecMode mode;
sprang4847ae62017-06-27 07:06:52 -070073 bool keyframe;
brandtre78d2662017-01-16 05:57:16 -080074 {
75 rtc::CritScope cs(&crit_sect_);
76 max_framerate = config_.maxFramerate;
77 num_simulcast_streams = config_.numberOfSimulcastStreams;
78 for (int i = 0; i < num_simulcast_streams; ++i) {
79 simulcast_streams[i] = config_.simulcastStream[i];
80 }
81 callback = callback_;
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +020082 target_bitrate = target_bitrate_;
ilnik00d802b2017-04-11 10:34:31 -070083 mode = config_.mode;
sprang4847ae62017-06-27 07:06:52 -070084 if (configured_input_framerate_ > 0) {
85 framerate = configured_input_framerate_;
86 } else {
87 framerate = max_framerate;
88 }
89 keyframe = pending_keyframe_;
90 pending_keyframe_ = false;
brandtre78d2662017-01-16 05:57:16 -080091 }
92
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +020093 FrameInfo frame_info =
94 NextFrame(frame_types, keyframe, num_simulcast_streams, target_bitrate,
95 simulcast_streams, framerate);
96 for (uint8_t i = 0; i < frame_info.layers.size(); ++i) {
Per Kjellander841c9122018-10-04 18:40:28 +020097 constexpr int kMinPayLoadLength = 10;
98 if (frame_info.layers[i].size < kMinPayLoadLength) {
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +020099 // Drop this temporal layer.
100 continue;
sprang4847ae62017-06-27 07:06:52 -0700101 }
sprang4847ae62017-06-27 07:06:52 -0700102
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000103 CodecSpecificInfo specifics;
104 memset(&specifics, 0, sizeof(specifics));
pbos@webrtc.org0181b5f2013-09-09 08:26:30 +0000105 specifics.codecType = kVideoCodecGeneric;
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +0200106 std::unique_ptr<uint8_t[]> encoded_buffer(
107 new uint8_t[frame_info.layers[i].size]);
108 memcpy(encoded_buffer.get(), encoded_buffer_, frame_info.layers[i].size);
109 EncodedImage encoded(encoded_buffer.get(), frame_info.layers[i].size,
110 sizeof(encoded_buffer_));
Niels Möller72bc8d62018-09-12 10:03:51 +0200111 encoded.SetTimestamp(input_image.timestamp());
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000112 encoded.capture_time_ms_ = input_image.render_time_ms();
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +0200113 encoded._frameType =
114 frame_info.keyframe ? kVideoFrameKey : kVideoFrameDelta;
brandtre78d2662017-01-16 05:57:16 -0800115 encoded._encodedWidth = simulcast_streams[i].width;
116 encoded._encodedHeight = simulcast_streams[i].height;
perkj803d97f2016-11-01 11:45:46 -0700117 encoded.rotation_ = input_image.rotation();
Niels Möllere3cf3d02018-06-13 11:52:16 +0200118 encoded.content_type_ = (mode == VideoCodecMode::kScreensharing)
ilnik00d802b2017-04-11 10:34:31 -0700119 ? VideoContentType::SCREENSHARE
120 : VideoContentType::UNSPECIFIED;
Niels Möllerd3b8c632018-08-27 15:33:42 +0200121 encoded.SetSpatialIndex(i);
perkj275afc52016-09-01 00:21:16 -0700122 specifics.codec_name = ImplementationName();
brandtre78d2662017-01-16 05:57:16 -0800123 if (callback->OnEncodedImage(encoded, &specifics, nullptr).error !=
sergeyu2cb155a2016-11-04 11:39:29 -0700124 EncodedImageCallback::Result::OK) {
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000125 return -1;
sergeyu2cb155a2016-11-04 11:39:29 -0700126 }
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000127 }
128 return 0;
129}
130
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +0200131FakeEncoder::FrameInfo FakeEncoder::NextFrame(
132 const std::vector<FrameType>* frame_types,
133 bool keyframe,
134 uint8_t num_simulcast_streams,
135 const VideoBitrateAllocation& target_bitrate,
136 SimulcastStream simulcast_streams[kMaxSimulcastStreams],
137 int framerate) {
138 FrameInfo frame_info;
139 frame_info.keyframe = keyframe;
140
141 if (frame_types) {
142 for (FrameType frame_type : *frame_types) {
143 if (frame_type == kVideoFrameKey) {
144 frame_info.keyframe = true;
145 break;
146 }
147 }
148 }
149
150 for (uint8_t i = 0; i < num_simulcast_streams; ++i) {
151 if (target_bitrate.GetBitrate(i, 0) > 0) {
152 int temporal_id = last_frame_info_.layers.size() > i
153 ? ++last_frame_info_.layers[i].temporal_id %
154 simulcast_streams[i].numberOfTemporalLayers
155 : 0;
156 frame_info.layers.emplace_back(0, temporal_id);
157 }
158 }
159
160 if (last_frame_info_.layers.size() < frame_info.layers.size()) {
161 // A new keyframe is needed since a new layer will be added.
162 frame_info.keyframe = true;
163 }
164
165 for (uint8_t i = 0; i < frame_info.layers.size(); ++i) {
166 FrameInfo::SpatialLayer& layer_info = frame_info.layers[i];
167 if (frame_info.keyframe) {
168 layer_info.temporal_id = 0;
169 size_t avg_frame_size =
170 (target_bitrate.GetBitrate(i, 0) + 7) / (8 * framerate);
171
172 // The first frame is a key frame and should be larger.
173 // Store the overshoot bytes and distribute them over the coming frames,
174 // so that we on average meet the bitrate target.
175 debt_bytes_ += (kKeyframeSizeFactor - 1) * avg_frame_size;
176 layer_info.size = kKeyframeSizeFactor * avg_frame_size;
177 } else {
178 size_t avg_frame_size =
179 (target_bitrate.GetBitrate(i, layer_info.temporal_id) + 7) /
180 (8 * framerate);
181 layer_info.size = avg_frame_size;
182 if (debt_bytes_ > 0) {
183 // Pay at most half of the frame size for old debts.
184 size_t payment_size = std::min(avg_frame_size / 2, debt_bytes_);
185 debt_bytes_ -= payment_size;
186 layer_info.size -= payment_size;
187 }
188 }
189 }
190 last_frame_info_ = frame_info;
191 return frame_info;
192}
193
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000194int32_t FakeEncoder::RegisterEncodeCompleteCallback(
195 EncodedImageCallback* callback) {
brandtre78d2662017-01-16 05:57:16 -0800196 rtc::CritScope cs(&crit_sect_);
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000197 callback_ = callback;
198 return 0;
199}
200
Yves Gerey665174f2018-06-19 15:03:05 +0200201int32_t FakeEncoder::Release() {
202 return 0;
203}
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000204
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000205int32_t FakeEncoder::SetChannelParameters(uint32_t packet_loss, int64_t rtt) {
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000206 return 0;
207}
208
Erik Språng566124a2018-04-23 12:32:22 +0200209int32_t FakeEncoder::SetRateAllocation(
210 const VideoBitrateAllocation& rate_allocation,
211 uint32_t framerate) {
brandtre78d2662017-01-16 05:57:16 -0800212 rtc::CritScope cs(&crit_sect_);
Erik Språng08127a92016-11-16 16:41:30 +0100213 target_bitrate_ = rate_allocation;
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +0200214 int allocated_bitrate_kbps = target_bitrate_.get_sum_kbps();
215
216 // Scale bitrate allocation to not exceed the given max target bitrate.
217 if (max_target_bitrate_kbps_ > 0 &&
218 allocated_bitrate_kbps > max_target_bitrate_kbps_) {
219 for (uint8_t spatial_idx = 0; spatial_idx < kMaxSpatialLayers;
220 ++spatial_idx) {
221 for (uint8_t temporal_idx = 0; temporal_idx < kMaxTemporalStreams;
222 ++temporal_idx) {
223 if (target_bitrate_.HasBitrate(spatial_idx, temporal_idx)) {
224 uint32_t bitrate =
225 target_bitrate_.GetBitrate(spatial_idx, temporal_idx);
226 bitrate = static_cast<uint32_t>(
227 (bitrate * int64_t{max_target_bitrate_kbps_}) /
228 allocated_bitrate_kbps);
229 target_bitrate_.SetBitrate(spatial_idx, temporal_idx, bitrate);
230 }
231 }
232 }
233 }
234
sprang4847ae62017-06-27 07:06:52 -0700235 configured_input_framerate_ = framerate;
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000236 return 0;
237}
pbos@webrtc.org3349ae02014-03-13 12:52:27 +0000238
Peter Boströmb7d9a972015-12-18 16:01:11 +0100239const char* FakeEncoder::kImplementationName = "fake_encoder";
240const char* FakeEncoder::ImplementationName() const {
241 return kImplementationName;
242}
243
sprang4847ae62017-06-27 07:06:52 -0700244int FakeEncoder::GetConfiguredInputFramerate() const {
245 rtc::CritScope cs(&crit_sect_);
246 return configured_input_framerate_;
247}
248
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000249FakeH264Encoder::FakeH264Encoder(Clock* clock)
brandtre78d2662017-01-16 05:57:16 -0800250 : FakeEncoder(clock), callback_(nullptr), idr_counter_(0) {
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000251 FakeEncoder::RegisterEncodeCompleteCallback(this);
252}
253
254int32_t FakeH264Encoder::RegisterEncodeCompleteCallback(
255 EncodedImageCallback* callback) {
brandtre78d2662017-01-16 05:57:16 -0800256 rtc::CritScope cs(&local_crit_sect_);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000257 callback_ = callback;
258 return 0;
259}
260
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700261EncodedImageCallback::Result FakeH264Encoder::OnEncodedImage(
262 const EncodedImage& encoded_image,
263 const CodecSpecificInfo* codec_specific_info,
264 const RTPFragmentationHeader* fragments) {
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000265 const size_t kSpsSize = 8;
266 const size_t kPpsSize = 11;
267 const int kIdrFrequency = 10;
brandtre78d2662017-01-16 05:57:16 -0800268 EncodedImageCallback* callback;
269 int current_idr_counter;
270 {
271 rtc::CritScope cs(&local_crit_sect_);
272 callback = callback_;
273 current_idr_counter = idr_counter_;
274 ++idr_counter_;
275 }
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000276 RTPFragmentationHeader fragmentation;
brandtre78d2662017-01-16 05:57:16 -0800277 if (current_idr_counter % kIdrFrequency == 0 &&
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000278 encoded_image._length > kSpsSize + kPpsSize + 1) {
279 const size_t kNumSlices = 3;
280 fragmentation.VerifyAndAllocateFragmentationHeader(kNumSlices);
281 fragmentation.fragmentationOffset[0] = 0;
282 fragmentation.fragmentationLength[0] = kSpsSize;
283 fragmentation.fragmentationOffset[1] = kSpsSize;
284 fragmentation.fragmentationLength[1] = kPpsSize;
285 fragmentation.fragmentationOffset[2] = kSpsSize + kPpsSize;
286 fragmentation.fragmentationLength[2] =
287 encoded_image._length - (kSpsSize + kPpsSize);
glaznev@webrtc.orge69220c2015-02-05 17:56:15 +0000288 const size_t kSpsNalHeader = 0x67;
289 const size_t kPpsNalHeader = 0x68;
290 const size_t kIdrNalHeader = 0x65;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000291 encoded_image._buffer[fragmentation.fragmentationOffset[0]] = kSpsNalHeader;
292 encoded_image._buffer[fragmentation.fragmentationOffset[1]] = kPpsNalHeader;
293 encoded_image._buffer[fragmentation.fragmentationOffset[2]] = kIdrNalHeader;
294 } else {
295 const size_t kNumSlices = 1;
296 fragmentation.VerifyAndAllocateFragmentationHeader(kNumSlices);
297 fragmentation.fragmentationOffset[0] = 0;
298 fragmentation.fragmentationLength[0] = encoded_image._length;
glaznev@webrtc.orge69220c2015-02-05 17:56:15 +0000299 const size_t kNalHeader = 0x41;
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000300 encoded_image._buffer[fragmentation.fragmentationOffset[0]] = kNalHeader;
301 }
302 uint8_t value = 0;
303 int fragment_counter = 0;
304 for (size_t i = 0; i < encoded_image._length; ++i) {
305 if (fragment_counter == fragmentation.fragmentationVectorSize ||
306 i != fragmentation.fragmentationOffset[fragment_counter]) {
307 encoded_image._buffer[i] = value++;
308 } else {
309 ++fragment_counter;
310 }
311 }
palmkviste75f2042016-09-28 06:19:48 -0700312 CodecSpecificInfo specifics;
313 memset(&specifics, 0, sizeof(specifics));
314 specifics.codecType = kVideoCodecH264;
hta9aa96882016-12-06 05:36:03 -0800315 specifics.codecSpecific.H264.packetization_mode =
316 H264PacketizationMode::NonInterleaved;
brandtre78d2662017-01-16 05:57:16 -0800317 RTC_DCHECK(callback);
318 return callback->OnEncodedImage(encoded_image, &specifics, &fragmentation);
stefan@webrtc.org79c33592014-08-06 09:24:53 +0000319}
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000320
321DelayedEncoder::DelayedEncoder(Clock* clock, int delay_ms)
brandtr49ce67c2017-02-11 00:25:18 -0800322 : test::FakeEncoder(clock), delay_ms_(delay_ms) {
323 // The encoder could be created on a different thread than
324 // it is being used on.
325 sequence_checker_.Detach();
326}
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000327
perkj803d97f2016-11-01 11:45:46 -0700328void DelayedEncoder::SetDelay(int delay_ms) {
brandtr49ce67c2017-02-11 00:25:18 -0800329 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
perkj803d97f2016-11-01 11:45:46 -0700330 delay_ms_ = delay_ms;
331}
332
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700333int32_t DelayedEncoder::Encode(const VideoFrame& input_image,
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000334 const CodecSpecificInfo* codec_specific_info,
pbos22993e12015-10-19 02:39:06 -0700335 const std::vector<FrameType>* frame_types) {
brandtr49ce67c2017-02-11 00:25:18 -0800336 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
337
338 SleepMs(delay_ms_);
339
asapersson@webrtc.org049e4ec2014-11-20 10:19:46 +0000340 return FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
341}
brandtr696c9c62016-12-19 05:47:28 -0800342
brandtre78d2662017-01-16 05:57:16 -0800343MultithreadedFakeH264Encoder::MultithreadedFakeH264Encoder(Clock* clock)
brandtr696c9c62016-12-19 05:47:28 -0800344 : test::FakeH264Encoder(clock),
345 current_queue_(0),
brandtr49ce67c2017-02-11 00:25:18 -0800346 queue1_(nullptr),
347 queue2_(nullptr) {
348 // The encoder could be created on a different thread than
349 // it is being used on.
350 sequence_checker_.Detach();
351}
brandtr696c9c62016-12-19 05:47:28 -0800352
brandtr49ce67c2017-02-11 00:25:18 -0800353int32_t MultithreadedFakeH264Encoder::InitEncode(const VideoCodec* config,
354 int32_t number_of_cores,
355 size_t max_payload_size) {
356 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
357
358 queue1_.reset(new rtc::TaskQueue("Queue 1"));
359 queue2_.reset(new rtc::TaskQueue("Queue 2"));
360
361 return FakeH264Encoder::InitEncode(config, number_of_cores, max_payload_size);
362}
brandtr696c9c62016-12-19 05:47:28 -0800363
brandtre78d2662017-01-16 05:57:16 -0800364class MultithreadedFakeH264Encoder::EncodeTask : public rtc::QueuedTask {
brandtr696c9c62016-12-19 05:47:28 -0800365 public:
brandtre78d2662017-01-16 05:57:16 -0800366 EncodeTask(MultithreadedFakeH264Encoder* encoder,
brandtr696c9c62016-12-19 05:47:28 -0800367 const VideoFrame& input_image,
368 const CodecSpecificInfo* codec_specific_info,
369 const std::vector<FrameType>* frame_types)
370 : encoder_(encoder),
371 input_image_(input_image),
372 codec_specific_info_(),
373 frame_types_(*frame_types) {
374 if (codec_specific_info)
375 codec_specific_info_ = *codec_specific_info;
376 }
377
378 private:
379 bool Run() override {
380 encoder_->EncodeCallback(input_image_, &codec_specific_info_,
381 &frame_types_);
382 return true;
383 }
384
brandtre78d2662017-01-16 05:57:16 -0800385 MultithreadedFakeH264Encoder* const encoder_;
brandtr696c9c62016-12-19 05:47:28 -0800386 VideoFrame input_image_;
387 CodecSpecificInfo codec_specific_info_;
388 std::vector<FrameType> frame_types_;
389};
390
brandtre78d2662017-01-16 05:57:16 -0800391int32_t MultithreadedFakeH264Encoder::Encode(
brandtr696c9c62016-12-19 05:47:28 -0800392 const VideoFrame& input_image,
393 const CodecSpecificInfo* codec_specific_info,
394 const std::vector<FrameType>* frame_types) {
brandtr49ce67c2017-02-11 00:25:18 -0800395 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
brandtr696c9c62016-12-19 05:47:28 -0800396
brandtr49ce67c2017-02-11 00:25:18 -0800397 std::unique_ptr<rtc::TaskQueue>& queue =
398 (current_queue_++ % 2 == 0) ? queue1_ : queue2_;
399
400 if (!queue) {
401 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
402 }
403
404 queue->PostTask(std::unique_ptr<rtc::QueuedTask>(
brandtr696c9c62016-12-19 05:47:28 -0800405 new EncodeTask(this, input_image, codec_specific_info, frame_types)));
406
brandtr49ce67c2017-02-11 00:25:18 -0800407 return WEBRTC_VIDEO_CODEC_OK;
brandtr696c9c62016-12-19 05:47:28 -0800408}
409
brandtre78d2662017-01-16 05:57:16 -0800410int32_t MultithreadedFakeH264Encoder::EncodeCallback(
brandtr696c9c62016-12-19 05:47:28 -0800411 const VideoFrame& input_image,
412 const CodecSpecificInfo* codec_specific_info,
413 const std::vector<FrameType>* frame_types) {
414 return FakeH264Encoder::Encode(input_image, codec_specific_info, frame_types);
415}
416
brandtr49ce67c2017-02-11 00:25:18 -0800417int32_t MultithreadedFakeH264Encoder::Release() {
418 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
419
420 queue1_.reset();
421 queue2_.reset();
422
423 return FakeH264Encoder::Release();
424}
425
pbos@webrtc.orgcb5118c2013-09-03 09:10:37 +0000426} // namespace test
stefan@webrtc.org360e3762013-08-22 09:29:56 +0000427} // namespace webrtc