1 /*
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
13 #include <algorithm>
14
15 #include "absl/types/optional.h"
16 #include "api/video_codecs/video_encoder.h"
17 #include "api/video_codecs/vp8_temporal_layers.h"
18 #include "api/video_codecs/vp8_temporal_layers_factory.h"
19 #include "modules/video_coding/codecs/interface/common_constants.h"
20 #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"
23
24 namespace {
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.
WriteFakeVp8(unsigned char * payload,int width,int height,bool key_frame)28 void 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
44 namespace webrtc {
45
46 namespace test {
47
FakeVp8Encoder(Clock * clock)48 FakeVp8Encoder::FakeVp8Encoder(Clock* clock) : FakeEncoder(clock) {
49 sequence_checker_.Detach();
50 }
51
InitEncode(const VideoCodec * config,const Settings & settings)52 int32_t FakeVp8Encoder::InitEncode(const VideoCodec* config,
53 const Settings& settings) {
54 RTC_DCHECK_RUN_ON(&sequence_checker_);
55 auto result = FakeEncoder::InitEncode(config, settings);
56 if (result != WEBRTC_VIDEO_CODEC_OK) {
57 return result;
58 }
59
60 Vp8TemporalLayersFactory factory;
61 frame_buffer_controller_ =
62 factory.Create(*config, settings, &fec_controller_override_);
63
64 return WEBRTC_VIDEO_CODEC_OK;
65 }
66
Release()67 int32_t FakeVp8Encoder::Release() {
68 auto result = FakeEncoder::Release();
69 sequence_checker_.Detach();
70 return result;
71 }
72
PopulateCodecSpecific(CodecSpecificInfo * codec_specific,size_t size_bytes,VideoFrameType frame_type,int stream_idx,uint32_t timestamp)73 void FakeVp8Encoder::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
74 size_t size_bytes,
75 VideoFrameType frame_type,
76 int stream_idx,
77 uint32_t timestamp) {
78 RTC_DCHECK_RUN_ON(&sequence_checker_);
79 codec_specific->codecType = kVideoCodecVP8;
80 codec_specific->codecSpecific.VP8.keyIdx = kNoKeyIdx;
81 codec_specific->codecSpecific.VP8.nonReference = false;
82 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 }
89 }
90
EncodeHook(EncodedImage * encoded_image,CodecSpecificInfo * codec_specific)91 std::unique_ptr<RTPFragmentationHeader> FakeVp8Encoder::EncodeHook(
92 EncodedImage* encoded_image,
93 CodecSpecificInfo* codec_specific) {
94 RTC_DCHECK_RUN_ON(&sequence_checker_);
95 uint8_t stream_idx = encoded_image->SpatialIndex().value_or(0);
96 frame_buffer_controller_->NextFrameConfig(stream_idx,
97 encoded_image->Timestamp());
98 PopulateCodecSpecific(codec_specific, encoded_image->size(),
99 encoded_image->_frameType, stream_idx,
100 encoded_image->Timestamp());
101
102 // Write width and height to the payload the same way as the real encoder
103 // does.
104 WriteFakeVp8(encoded_image->data(), encoded_image->_encodedWidth,
105 encoded_image->_encodedHeight,
106 encoded_image->_frameType == VideoFrameType::kVideoFrameKey);
107 return nullptr;
108 }
109
GetEncoderInfo() const110 VideoEncoder::EncoderInfo FakeVp8Encoder::GetEncoderInfo() const {
111 EncoderInfo info;
112 info.implementation_name = "FakeVp8Encoder";
113 return info;
114 }
115
116 } // namespace test
117 } // namespace webrtc
118