blob: 60bc36c5705f102002c9eed09fe1dcd5deb86704 [file] [log] [blame]
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +02001/*
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 "test/fake_vp8_encoder.h"
12
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <algorithm>
14
15#include "absl/types/optional.h"
Elad Alon370f93a2019-06-11 14:57:57 +020016#include "api/video_codecs/video_encoder.h"
Erik Språng4529fbc2018-10-12 10:30:31 +020017#include "api/video_codecs/vp8_temporal_layers.h"
Elad Aloncde8ab22019-03-20 11:56:20 +010018#include "api/video_codecs/vp8_temporal_layers_factory.h"
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "modules/video_coding/codecs/interface/common_constants.h"
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +020020#include "modules/video_coding/include/video_codec_interface.h"
21#include "modules/video_coding/include/video_error_codes.h"
22#include "modules/video_coding/utility/simulcast_utility.h"
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +020023
Per Kjellander841c9122018-10-04 18:40:28 +020024namespace {
25
26// Write width and height to the payload the same way as the real encoder does.
27// It requires that |payload| has a size of at least kMinPayLoadHeaderLength.
28void WriteFakeVp8(unsigned char* payload,
29 int width,
30 int height,
31 bool key_frame) {
32 payload[0] = key_frame ? 0 : 0x01;
33
34 if (key_frame) {
35 payload[9] = (height & 0x3F00) >> 8;
36 payload[8] = (height & 0x00FF);
37
38 payload[7] = (width & 0x3F00) >> 8;
39 payload[6] = (width & 0x00FF);
40 }
41}
42} // namespace
43
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +020044namespace webrtc {
45
46namespace test {
47
Niels Möllerd7380712019-03-06 10:09:47 +010048FakeVP8Encoder::FakeVP8Encoder(Clock* clock) : FakeEncoder(clock) {
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +020049 sequence_checker_.Detach();
50}
51
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +020052int32_t FakeVP8Encoder::InitEncode(const VideoCodec* config,
Elad Alon370f93a2019-06-11 14:57:57 +020053 const Settings& settings) {
Sebastian Janssonb55015e2019-04-09 13:44:04 +020054 RTC_DCHECK_RUN_ON(&sequence_checker_);
Elad Alon370f93a2019-06-11 14:57:57 +020055 auto result = FakeEncoder::InitEncode(config, settings);
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +020056 if (result != WEBRTC_VIDEO_CODEC_OK) {
57 return result;
58 }
59
Elad Aloncde8ab22019-03-20 11:56:20 +010060 Vp8TemporalLayersFactory factory;
Elad Alon45befc52019-07-02 11:20:09 +020061 frame_buffer_controller_ =
62 factory.Create(*config, settings, &fec_controller_override_);
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +020063
64 return WEBRTC_VIDEO_CODEC_OK;
65}
66
67int32_t FakeVP8Encoder::Release() {
68 auto result = FakeEncoder::Release();
69 sequence_checker_.Detach();
70 return result;
71}
72
Erik Språng59021ba2018-10-03 11:05:16 +020073void FakeVP8Encoder::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
74 size_t size_bytes,
Niels Möller87e2d782019-03-07 10:18:23 +010075 VideoFrameType frame_type,
Erik Språng59021ba2018-10-03 11:05:16 +020076 int stream_idx,
77 uint32_t timestamp) {
Sebastian Janssonb55015e2019-04-09 13:44:04 +020078 RTC_DCHECK_RUN_ON(&sequence_checker_);
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +020079 codec_specific->codecType = kVideoCodecVP8;
philipel9df33532019-03-04 16:37:50 +010080 codec_specific->codecSpecific.VP8.keyIdx = kNoKeyIdx;
81 codec_specific->codecSpecific.VP8.nonReference = false;
Elad Alon6796ec22019-04-15 10:07:50 +020082 if (size_bytes > 0) {
83 frame_buffer_controller_->OnEncodeDone(
84 stream_idx, timestamp, size_bytes,
85 frame_type == VideoFrameType::kVideoFrameKey, -1, codec_specific);
86 } else {
87 frame_buffer_controller_->OnFrameDropped(stream_idx, timestamp);
88 }
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +020089}
90
Niels Möllerd7380712019-03-06 10:09:47 +010091std::unique_ptr<RTPFragmentationHeader> FakeVP8Encoder::EncodeHook(
92 EncodedImage* encoded_image,
93 CodecSpecificInfo* codec_specific) {
Sebastian Janssonb55015e2019-04-09 13:44:04 +020094 RTC_DCHECK_RUN_ON(&sequence_checker_);
Niels Möllerd7380712019-03-06 10:09:47 +010095 uint8_t stream_idx = encoded_image->SpatialIndex().value_or(0);
Elad Alon979c4422019-04-17 12:53:08 +020096 frame_buffer_controller_->NextFrameConfig(stream_idx,
97 encoded_image->Timestamp());
Niels Möllerd7380712019-03-06 10:09:47 +010098 PopulateCodecSpecific(codec_specific, encoded_image->size(),
99 encoded_image->_frameType, stream_idx,
100 encoded_image->Timestamp());
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +0200101
Per Kjellander841c9122018-10-04 18:40:28 +0200102 // Write width and height to the payload the same way as the real encoder
103 // does.
Niels Möllerd7380712019-03-06 10:09:47 +0100104 WriteFakeVp8(encoded_image->data(), encoded_image->_encodedWidth,
105 encoded_image->_encodedHeight,
Niels Möller8f7ce222019-03-21 15:43:58 +0100106 encoded_image->_frameType == VideoFrameType::kVideoFrameKey);
Niels Möllerd7380712019-03-06 10:09:47 +0100107 return nullptr;
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +0200108}
109
Erik Språng86336a52018-11-15 15:38:05 +0100110VideoEncoder::EncoderInfo FakeVP8Encoder::GetEncoderInfo() const {
111 EncoderInfo info;
112 info.implementation_name = "FakeVp8Encoder";
113 return info;
114}
115
Ilya Nikolaevskiyb0588e62018-08-27 14:12:27 +0200116} // namespace test
117} // namespace webrtc