xref: /aosp_15_r20/external/webrtc/test/fake_vp8_encoder.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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(size_t size_bytes,VideoFrameType frame_type,int stream_idx,uint32_t timestamp)73 CodecSpecificInfo FakeVp8Encoder::PopulateCodecSpecific(
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   CodecSpecificInfo codec_specific;
80   codec_specific.codecType = kVideoCodecVP8;
81   codec_specific.codecSpecific.VP8.keyIdx = kNoKeyIdx;
82   codec_specific.codecSpecific.VP8.nonReference = false;
83   if (size_bytes > 0) {
84     frame_buffer_controller_->OnEncodeDone(
85         stream_idx, timestamp, size_bytes,
86         frame_type == VideoFrameType::kVideoFrameKey, -1, &codec_specific);
87   } else {
88     frame_buffer_controller_->OnFrameDropped(stream_idx, timestamp);
89   }
90   return codec_specific;
91 }
92 
EncodeHook(EncodedImage & encoded_image,rtc::scoped_refptr<EncodedImageBuffer> buffer)93 CodecSpecificInfo FakeVp8Encoder::EncodeHook(
94     EncodedImage& encoded_image,
95     rtc::scoped_refptr<EncodedImageBuffer> buffer) {
96   RTC_DCHECK_RUN_ON(&sequence_checker_);
97   uint8_t stream_idx = encoded_image.SpatialIndex().value_or(0);
98   frame_buffer_controller_->NextFrameConfig(stream_idx,
99                                             encoded_image.Timestamp());
100   CodecSpecificInfo codec_specific =
101       PopulateCodecSpecific(encoded_image.size(), encoded_image._frameType,
102                             stream_idx, encoded_image.Timestamp());
103 
104   // Write width and height to the payload the same way as the real encoder
105   // does.
106   WriteFakeVp8(buffer->data(), encoded_image._encodedWidth,
107                encoded_image._encodedHeight,
108                encoded_image._frameType == VideoFrameType::kVideoFrameKey);
109   return codec_specific;
110 }
111 
GetEncoderInfo() const112 VideoEncoder::EncoderInfo FakeVp8Encoder::GetEncoderInfo() const {
113   EncoderInfo info;
114   info.implementation_name = "FakeVp8Encoder";
115   MutexLock lock(&mutex_);
116   for (int sid = 0; sid < config_.numberOfSimulcastStreams; ++sid) {
117     int number_of_temporal_layers =
118         config_.simulcastStream[sid].numberOfTemporalLayers;
119     info.fps_allocation[sid].clear();
120     for (int tid = 0; tid < number_of_temporal_layers; ++tid) {
121       // {1/4, 1/2, 1} allocation for num layers = 3.
122       info.fps_allocation[sid].push_back(255 /
123                                          (number_of_temporal_layers - tid));
124     }
125   }
126   return info;
127 }
128 
129 }  // namespace test
130 }  // namespace webrtc
131