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