1 /*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "dcamera_stream_data_process_producer.h"
17
18 #include <chrono>
19 #include <securec.h>
20
21 #include "anonymous_string.h"
22 #include "dcamera_buffer_handle.h"
23 #include "dcamera_hidumper.h"
24 #include "dcamera_utils_tools.h"
25 #include "distributed_camera_constants.h"
26 #include "distributed_camera_errno.h"
27 #include "distributed_hardware_log.h"
28 #include <sys/prctl.h>
29 #include "dcamera_frame_info.h"
30
31 namespace OHOS {
32 namespace DistributedHardware {
DCameraStreamDataProcessProducer(std::string devId,std::string dhId,int32_t streamId,DCStreamType streamType)33 DCameraStreamDataProcessProducer::DCameraStreamDataProcessProducer(std::string devId, std::string dhId,
34 int32_t streamId, DCStreamType streamType)
35 : devId_(devId), dhId_(dhId), streamId_(streamId), streamType_(streamType), eventHandler_(nullptr),
36 camHdiProvider_(nullptr)
37 {
38 DHLOGI("DCameraStreamDataProcessProducer Constructor devId %{public}s dhId %{public}s streamType: %{public}d "
39 "streamId: %{public}d", GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamType_, streamId_);
40 state_ = DCAMERA_PRODUCER_STATE_STOP;
41 interval_ = DCAMERA_PRODUCER_ONE_MINUTE_MS / DCAMERA_PRODUCER_FPS_DEFAULT;
42 photoCount_ = COUNT_INIT_NUM;
43 }
44
~DCameraStreamDataProcessProducer()45 DCameraStreamDataProcessProducer::~DCameraStreamDataProcessProducer()
46 {
47 DHLOGI("DCameraStreamDataProcessProducer Destructor devId %{public}s dhId %{public}s state: %{public}d streamType"
48 ": %{public}d streamId: %{public}d", GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), state_,
49 streamType_, streamId_);
50 if (state_ == DCAMERA_PRODUCER_STATE_START) {
51 Stop();
52 }
53 }
54
Start()55 void DCameraStreamDataProcessProducer::Start()
56 {
57 DHLOGI("DCameraStreamDataProcessProducer Start producer devId: %{public}s dhId: %{public}s streamType: %{public}d "
58 "streamId: %{public}d", GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamType_, streamId_);
59 camHdiProvider_ = IDCameraProvider::Get(HDF_DCAMERA_EXT_SERVICE);
60 if (camHdiProvider_ == nullptr) {
61 DHLOGE("camHdiProvider_ is null.");
62 }
63 state_ = DCAMERA_PRODUCER_STATE_START;
64 if (streamType_ == CONTINUOUS_FRAME) {
65 eventThread_ = std::thread([this]() { this->StartEvent(); });
66 std::unique_lock<std::mutex> lock(eventMutex_);
67 eventCon_.wait(lock, [this] {
68 return eventHandler_ != nullptr;
69 });
70 smoother_ = std::make_unique<DCameraFeedingSmoother>();
71 smootherListener_ = std::make_shared<FeedingSmootherListener>(shared_from_this());
72 smoother_->RegisterListener(smootherListener_);
73 smoother_->StartSmooth();
74 } else {
75 producerThread_ = std::thread([this]() { this->LooperSnapShot(); });
76 }
77 }
78
Stop()79 void DCameraStreamDataProcessProducer::Stop()
80 {
81 DHLOGI("DCameraStreamDataProcessProducer Stop devId: %{public}s dhId: %{public}s streamType: %{public}d "
82 "streamId: %{public}d state: %{public}d", GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(),
83 streamType_, streamId_, state_);
84 {
85 std::lock_guard<std::mutex> lock(bufferMutex_);
86 state_ = DCAMERA_PRODUCER_STATE_STOP;
87 }
88 if (streamType_ == CONTINUOUS_FRAME) {
89 if (smoother_ != nullptr) {
90 smoother_->StopSmooth();
91 smoother_ = nullptr;
92 }
93 smootherListener_ = nullptr;
94 if ((eventHandler_ != nullptr) && (eventHandler_->GetEventRunner() != nullptr)) {
95 eventHandler_->GetEventRunner()->Stop();
96 }
97 eventThread_.join();
98 eventHandler_ = nullptr;
99 } else {
100 producerCon_.notify_one();
101 producerThread_.join();
102 }
103 camHdiProvider_ = nullptr;
104 DHLOGI("DCameraStreamDataProcessProducer Stop end devId: %{public}s dhId: %{public}s streamType: %{public}d "
105 "streamId: %{public}d state: %{public}d", GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(),
106 streamType_, streamId_, state_);
107 }
108
FeedStream(const std::shared_ptr<DataBuffer> & buffer)109 void DCameraStreamDataProcessProducer::FeedStream(const std::shared_ptr<DataBuffer>& buffer)
110 {
111 CHECK_AND_RETURN_LOG(buffer == nullptr, "buffer is nullptr.");
112 buffer->frameInfo_.timePonit.startSmooth = GetNowTimeStampUs();
113 {
114 std::lock_guard<std::mutex> lock(bufferMutex_);
115 uint64_t buffersSize = static_cast<uint64_t>(buffer->Size());
116 DHLOGD("DCameraStreamDataProcessProducer FeedStream devId %{public}s dhId %{public}s streamId: %{public}d "
117 "streamType: %{public}d streamSize: %{public}" PRIu64, GetAnonyString(devId_).c_str(),
118 GetAnonyString(dhId_).c_str(), streamId_, streamType_, buffersSize);
119 if (buffers_.size() >= DCAMERA_PRODUCER_MAX_BUFFER_SIZE) {
120 buffersSize = static_cast<uint64_t>(buffer->Size());
121 DHLOGD("DCameraStreamDataProcessProducer FeedStream OverSize devId %{public}s dhId %{public}s streamType: "
122 "%{public}d streamSize: %{public}" PRIu64, GetAnonyString(devId_).c_str(),
123 GetAnonyString(dhId_).c_str(), streamType_, buffersSize);
124 buffers_.pop_front();
125 }
126 if (streamType_ == SNAPSHOT_FRAME) {
127 buffers_.push_back(buffer);
128 producerCon_.notify_one();
129 }
130 }
131 CHECK_AND_RETURN_LOG(smoother_ == nullptr, "smoother_ is null.");
132 if (streamType_ == CONTINUOUS_FRAME) {
133 smoother_->PushData(buffer);
134 }
135 }
136
StartEvent()137 void DCameraStreamDataProcessProducer::StartEvent()
138 {
139 prctl(PR_SET_NAME, SOURCE_START_EVENT.c_str());
140 auto runner = AppExecFwk::EventRunner::Create(false);
141 {
142 std::lock_guard<std::mutex> lock(eventMutex_);
143 eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
144 }
145 eventCon_.notify_one();
146 runner->Run();
147 }
148
LooperSnapShot()149 void DCameraStreamDataProcessProducer::LooperSnapShot()
150 {
151 std::string name = PRODUCER + std::to_string(streamType_);
152 prctl(PR_SET_NAME, name.c_str());
153 DHBase dhBase;
154 dhBase.deviceId_ = devId_;
155 dhBase.dhId_ = dhId_;
156 while (state_ == DCAMERA_PRODUCER_STATE_START) {
157 std::shared_ptr<DataBuffer> buffer = nullptr;
158 {
159 std::unique_lock<std::mutex> lock(bufferMutex_);
160 producerCon_.wait(lock, [this] {
161 return (!buffers_.empty() || state_ == DCAMERA_PRODUCER_STATE_STOP);
162 });
163 if (state_ == DCAMERA_PRODUCER_STATE_STOP) {
164 continue;
165 }
166 if (!buffers_.empty()) {
167 DHLOGI("LooperSnapShot producer get buffer devId: %{public}s dhId: %{public}s streamType: %{public}d "
168 "streamId: %{public}d state: %{public}d",
169 GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamType_, streamId_, state_);
170 buffer = buffers_.front();
171 }
172 }
173 if (buffer == nullptr) {
174 DHLOGI("LooperSnapShot producer get buffer failed devId: %{public}s dhId: %{public}s streamType:"
175 " %{public}d streamId: %{public}d state: %{public}d",
176 GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamType_, streamId_, state_);
177 continue;
178 }
179 #ifdef DUMP_DCAMERA_FILE
180 std::string fileName = DUMP_PHOTO_PATH +
181 "SourceCapture_streamId(" + std::to_string(streamId_) + ")_" + std::to_string(photoCount_++) + ".jpg";
182 if (DcameraHidumper::GetInstance().GetDumpFlag() && (IsUnderDumpMaxSize(fileName) == DCAMERA_OK)) {
183 DumpBufferToFile(fileName, buffer->Data(), buffer->Size());
184 }
185 #endif
186 int32_t ret = FeedStreamToDriver(dhBase, buffer);
187 if (ret != DCAMERA_OK) {
188 std::this_thread::sleep_for(std::chrono::milliseconds(DCAMERA_PRODUCER_RETRY_SLEEP_MS));
189 continue;
190 }
191 {
192 std::lock_guard<std::mutex> lock(bufferMutex_);
193 buffers_.pop_front();
194 }
195 }
196 DHLOGI("LooperSnapShot producer end devId: %s dhId: %s streamType: %{public}d streamId: %{public}d state: "
197 "%{public}d", GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamType_, streamId_, state_);
198 }
199
FeedStreamToDriver(const DHBase & dhBase,const std::shared_ptr<DataBuffer> & buffer)200 int32_t DCameraStreamDataProcessProducer::FeedStreamToDriver(const DHBase& dhBase,
201 const std::shared_ptr<DataBuffer>& buffer)
202 {
203 if (camHdiProvider_ == nullptr) {
204 DHLOGI("camHdiProvider is nullptr");
205 return DCAMERA_BAD_VALUE;
206 }
207 DCameraBuffer sharedMemory;
208 int32_t ret = camHdiProvider_->AcquireBuffer(dhBase, streamId_, sharedMemory);
209 if (ret != SUCCESS) {
210 DHLOGE("AcquireBuffer devId: %{public}s dhId: %{public}s streamId: %{public}d ret: %{public}d",
211 GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamId_, ret);
212 return DCAMERA_BAD_OPERATE;
213 }
214 do {
215 ret = CheckSharedMemory(sharedMemory, buffer);
216 if (ret != DCAMERA_OK) {
217 DHLOGE("CheckSharedMemory failed devId: %{public}s dhId: %{public}s", GetAnonyString(devId_).c_str(),
218 GetAnonyString(dhId_).c_str());
219 break;
220 }
221 sharedMemory.bufferHandle_->GetBufferHandle()->virAddr =
222 DCameraMemoryMap(sharedMemory.bufferHandle_->GetBufferHandle());
223 if (sharedMemory.bufferHandle_->GetBufferHandle()->virAddr == nullptr) {
224 DHLOGE("mmap failed devId: %{public}s dhId: %{public}s", GetAnonyString(devId_).c_str(),
225 GetAnonyString(dhId_).c_str());
226 break;
227 }
228 ret = memcpy_s(sharedMemory.bufferHandle_->GetBufferHandle()->virAddr, sharedMemory.size_, buffer->Data(),
229 buffer->Size());
230 if (ret != EOK) {
231 DHLOGE("memcpy_s devId: %s dhId: %s streamId: %{public}d bufSize: %zu, addressSize: %{public}d",
232 GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamId_,
233 buffer->Size(), sharedMemory.size_);
234 break;
235 }
236 sharedMemory.size_ = buffer->Size();
237 } while (0);
238 ret = camHdiProvider_->ShutterBuffer(dhBase, streamId_, sharedMemory);
239 if (sharedMemory.bufferHandle_ != nullptr) {
240 DCameraMemoryUnmap(sharedMemory.bufferHandle_->GetBufferHandle());
241 }
242 if (ret != SUCCESS) {
243 DHLOGE("ShutterBuffer devId: %{public}s dhId: %{public}s streamId: %{public}d ret: %{public}d",
244 GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamId_, ret);
245 return DCAMERA_BAD_OPERATE;
246 }
247 return ret;
248 }
249
CheckSharedMemory(const DCameraBuffer & sharedMemory,const std::shared_ptr<DataBuffer> & buffer)250 int32_t DCameraStreamDataProcessProducer::CheckSharedMemory(const DCameraBuffer& sharedMemory,
251 const std::shared_ptr<DataBuffer>& buffer)
252 {
253 if (sharedMemory.bufferHandle_ == nullptr || sharedMemory.bufferHandle_->GetBufferHandle() == nullptr) {
254 DHLOGE("bufferHandle read failed devId: %{public}s dhId: %{public}s", GetAnonyString(devId_).c_str(),
255 GetAnonyString(dhId_).c_str());
256 return DCAMERA_MEMORY_OPT_ERROR;
257 }
258
259 if (buffer->Size() > sharedMemory.size_) {
260 uint64_t buffersSize = static_cast<uint64_t>(buffer->Size());
261 DHLOGE("sharedMemory devId: %{public}s dhId: %{public}s streamId: %{public}d bufSize: %{public}" PRIu64
262 ", addressSize: %{public}d", GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamId_,
263 buffersSize, sharedMemory.size_);
264 return DCAMERA_MEMORY_OPT_ERROR;
265 }
266
267 return DCAMERA_OK;
268 }
269
OnSmoothFinished(const std::shared_ptr<IFeedableData> & data)270 void DCameraStreamDataProcessProducer::OnSmoothFinished(const std::shared_ptr<IFeedableData>& data)
271 {
272 std::shared_ptr<DataBuffer> buffer = std::reinterpret_pointer_cast<DataBuffer>(data);
273 CHECK_AND_RETURN_LOG(buffer == nullptr, "buffer is nullptr.");
274 DHBase dhBase;
275 dhBase.deviceId_ = devId_;
276 dhBase.dhId_ = dhId_;
277 #ifdef DUMP_DCAMERA_FILE
278 if (DcameraHidumper::GetInstance().GetDumpFlag() &&
279 (IsUnderDumpMaxSize(DUMP_PATH + TO_DISPLAY) == DCAMERA_OK)) {
280 DumpBufferToFile(DUMP_PATH + TO_DISPLAY, buffer->Data(), buffer->Size());
281 }
282 #endif
283 auto feedFunc = [this, dhBase, buffer]() {
284 FeedStreamToDriver(dhBase, buffer);
285 };
286 if (eventHandler_ != nullptr) {
287 eventHandler_->PostTask(feedFunc);
288 }
289 }
290 } // namespace DistributedHardware
291 } // namespace OHOS
292