1 // Copyright 2023 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 //#define LOG_NDEBUG 0
6 #define LOG_TAG "V4L2EncodeComponent"
7
8 #include <v4l2_codec2/v4l2/V4L2EncodeComponent.h>
9
10 #include <base/bind_helpers.h>
11
12 #include <cutils/properties.h>
13
14 #include <v4l2_codec2/components/BitstreamBuffer.h>
15 #include <v4l2_codec2/components/EncodeInterface.h>
16 #include <v4l2_codec2/v4l2/V4L2Encoder.h>
17
18 namespace android {
19
20 namespace {
21
22 // Check whether the specified |profile| is an H.264 profile.
IsH264Profile(C2Config::profile_t profile)23 bool IsH264Profile(C2Config::profile_t profile) {
24 return (profile >= C2Config::PROFILE_AVC_BASELINE &&
25 profile <= C2Config::PROFILE_AVC_ENHANCED_MULTIVIEW_DEPTH_HIGH);
26 }
27 } // namespace
28
29 // static
30 std::atomic<int32_t> V4L2EncodeComponent::sConcurrentInstances = 0;
31
32 // static
create(C2String name,c2_node_id_t id,std::shared_ptr<EncodeInterface> intfImpl,C2ComponentFactory::ComponentDeleter deleter)33 std::shared_ptr<C2Component> V4L2EncodeComponent::create(
34 C2String name, c2_node_id_t id, std::shared_ptr<EncodeInterface> intfImpl,
35 C2ComponentFactory::ComponentDeleter deleter) {
36 ALOGV("%s(%s)", __func__, name.c_str());
37
38 static const int32_t kMaxConcurrentInstances =
39 property_get_int32("ro.vendor.v4l2_codec2.encode_concurrent_instances", -1);
40
41 static std::mutex mutex;
42 std::lock_guard<std::mutex> lock(mutex);
43 if (kMaxConcurrentInstances >= 0 && sConcurrentInstances.load() >= kMaxConcurrentInstances) {
44 ALOGW("Cannot create additional encoder, maximum number of instances reached: %d",
45 kMaxConcurrentInstances);
46 return nullptr;
47 }
48
49 return std::shared_ptr<C2Component>(new V4L2EncodeComponent(name, id, std::move(intfImpl)),
50 deleter);
51 }
52
V4L2EncodeComponent(C2String name,c2_node_id_t id,std::shared_ptr<EncodeInterface> interface)53 V4L2EncodeComponent::V4L2EncodeComponent(C2String name, c2_node_id_t id,
54 std::shared_ptr<EncodeInterface> interface)
55 : EncodeComponent(name, id, interface) {
56 ALOGV("%s():", __func__);
57 sConcurrentInstances.fetch_add(1, std::memory_order_relaxed);
58 }
59
~V4L2EncodeComponent()60 V4L2EncodeComponent::~V4L2EncodeComponent() {
61 ALOGV("%s():", __func__);
62 sConcurrentInstances.fetch_sub(1, std::memory_order_relaxed);
63 }
64
initializeEncoder()65 bool V4L2EncodeComponent::initializeEncoder() {
66 ALOGV("%s()", __func__);
67 ALOG_ASSERT(mEncoderTaskRunner->RunsTasksInCurrentSequence());
68 ALOG_ASSERT(!mInputFormatConverter);
69 ALOG_ASSERT(!mEncoder);
70
71 mLastFrameTime = std::nullopt;
72
73 // Get the requested profile and level.
74 C2Config::profile_t outputProfile = mInterface->getOutputProfile();
75
76 // CSD only needs to be extracted when using an H.264 profile.
77 mExtractCSD = IsH264Profile(outputProfile);
78
79 std::optional<uint8_t> h264Level;
80 if (IsH264Profile(outputProfile)) {
81 h264Level = c2LevelToV4L2Level(mInterface->getOutputLevel());
82 }
83
84 // Get the stride used by the C2 framework, as this might be different from the stride used by
85 // the V4L2 encoder.
86 std::optional<uint32_t> stride =
87 getVideoFrameStride(VideoEncoder::kInputPixelFormat, mInterface->getInputVisibleSize());
88 if (!stride) {
89 ALOGE("Failed to get video frame stride");
90 reportError(C2_CORRUPTED);
91 return false;
92 }
93
94 // Get the requested bitrate mode and bitrate. The C2 framework doesn't offer a parameter to
95 // configure the peak bitrate, so we use a multiple of the target bitrate.
96 mBitrateMode = mInterface->getBitrateMode();
97 if (property_get_bool("persist.vendor.v4l2_codec2.disable_vbr", false)) {
98 // NOTE: This is a workaround for b/235771157.
99 ALOGW("VBR is disabled on this device");
100 mBitrateMode = C2Config::BITRATE_CONST;
101 }
102
103 mBitrate = mInterface->getBitrate();
104
105 mEncoder = V4L2Encoder::create(
106 outputProfile, h264Level, mInterface->getInputVisibleSize(), *stride,
107 mInterface->getKeyFramePeriod(), mBitrateMode, mBitrate,
108 mBitrate * VideoEncoder::kPeakBitrateMultiplier,
109 ::base::BindRepeating(&V4L2EncodeComponent::fetchOutputBlock, mWeakThis),
110 ::base::BindRepeating(&V4L2EncodeComponent::onInputBufferDone, mWeakThis),
111 ::base::BindRepeating(&V4L2EncodeComponent::onOutputBufferDone, mWeakThis),
112 ::base::BindRepeating(&V4L2EncodeComponent::onDrainDone, mWeakThis),
113 ::base::BindRepeating(&V4L2EncodeComponent::reportError, mWeakThis, C2_CORRUPTED),
114 mEncoderTaskRunner);
115 if (!mEncoder) {
116 ALOGE("Failed to create V4L2Encoder (profile: %s)", profileToString(outputProfile));
117 return false;
118 }
119
120 return true;
121 }
122
123 } // namespace android