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 buffer->frameInfo_.timePonit.startSmooth = GetNowTimeStampUs();
112 {
113 std::lock_guard<std::mutex> lock(bufferMutex_);
114 uint64_t buffersSize = static_cast<uint64_t>(buffer->Size());
115 DHLOGD("DCameraStreamDataProcessProducer FeedStream devId %{public}s dhId %{public}s streamId: %{public}d "
116 "streamType: %{public}d streamSize: %{public}" PRIu64, GetAnonyString(devId_).c_str(),
117 GetAnonyString(dhId_).c_str(), streamId_, streamType_, buffersSize);
118 if (buffers_.size() >= DCAMERA_PRODUCER_MAX_BUFFER_SIZE) {
119 buffersSize = static_cast<uint64_t>(buffer->Size());
120 DHLOGD("DCameraStreamDataProcessProducer FeedStream OverSize devId %{public}s dhId %{public}s streamType: "
121 "%{public}d streamSize: %{public}" PRIu64, GetAnonyString(devId_).c_str(),
122 GetAnonyString(dhId_).c_str(), streamType_, buffersSize);
123 buffers_.pop_front();
124 }
125 if (streamType_ == SNAPSHOT_FRAME) {
126 buffers_.push_back(buffer);
127 producerCon_.notify_one();
128 }
129 }
130 CHECK_AND_RETURN_LOG(smoother_ == nullptr, "smoother_ is null.");
131 if (streamType_ == CONTINUOUS_FRAME) {
132 smoother_->PushData(buffer);
133 }
134 }
135
StartEvent()136 void DCameraStreamDataProcessProducer::StartEvent()
137 {
138 prctl(PR_SET_NAME, SOURCE_START_EVENT.c_str());
139 auto runner = AppExecFwk::EventRunner::Create(false);
140 {
141 std::lock_guard<std::mutex> lock(eventMutex_);
142 eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
143 }
144 eventCon_.notify_one();
145 runner->Run();
146 }
147
LooperSnapShot()148 void DCameraStreamDataProcessProducer::LooperSnapShot()
149 {
150 std::string name = PRODUCER + std::to_string(streamType_);
151 prctl(PR_SET_NAME, name.c_str());
152 DHBase dhBase;
153 dhBase.deviceId_ = devId_;
154 dhBase.dhId_ = dhId_;
155 while (state_ == DCAMERA_PRODUCER_STATE_START) {
156 std::shared_ptr<DataBuffer> buffer = nullptr;
157 {
158 std::unique_lock<std::mutex> lock(bufferMutex_);
159 producerCon_.wait(lock, [this] {
160 return (!buffers_.empty() || state_ == DCAMERA_PRODUCER_STATE_STOP);
161 });
162 if (state_ == DCAMERA_PRODUCER_STATE_STOP) {
163 continue;
164 }
165 if (!buffers_.empty()) {
166 DHLOGI("LooperSnapShot producer get buffer devId: %{public}s dhId: %{public}s streamType: %{public}d "
167 "streamId: %{public}d state: %{public}d",
168 GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamType_, streamId_, state_);
169 buffer = buffers_.front();
170 }
171 }
172 if (buffer == nullptr) {
173 DHLOGI("LooperSnapShot producer get buffer failed devId: %{public}s dhId: %{public}s streamType:"
174 " %{public}d streamId: %{public}d state: %{public}d",
175 GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamType_, streamId_, state_);
176 continue;
177 }
178 #ifdef DUMP_DCAMERA_FILE
179 std::string fileName = DUMP_PHOTO_PATH +
180 "SourceCapture_streamId(" + std::to_string(streamId_) + ")_" + std::to_string(photoCount_++) + ".jpg";
181 if (DcameraHidumper::GetInstance().GetDumpFlag() && (IsUnderDumpMaxSize(fileName) == DCAMERA_OK)) {
182 DumpBufferToFile(fileName, buffer->Data(), buffer->Size());
183 }
184 #endif
185 int32_t ret = FeedStreamToDriver(dhBase, buffer);
186 if (ret != DCAMERA_OK) {
187 std::this_thread::sleep_for(std::chrono::milliseconds(DCAMERA_PRODUCER_RETRY_SLEEP_MS));
188 continue;
189 }
190 {
191 std::lock_guard<std::mutex> lock(bufferMutex_);
192 buffers_.pop_front();
193 }
194 }
195 DHLOGI("LooperSnapShot producer end devId: %s dhId: %s streamType: %{public}d streamId: %{public}d state: "
196 "%{public}d", GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamType_, streamId_, state_);
197 }
198
FeedStreamToDriver(const DHBase & dhBase,const std::shared_ptr<DataBuffer> & buffer)199 int32_t DCameraStreamDataProcessProducer::FeedStreamToDriver(const DHBase& dhBase,
200 const std::shared_ptr<DataBuffer>& buffer)
201 {
202 if (camHdiProvider_ == nullptr) {
203 DHLOGI("camHdiProvider is nullptr");
204 return DCAMERA_BAD_VALUE;
205 }
206 DCameraBuffer sharedMemory;
207 int32_t ret = camHdiProvider_->AcquireBuffer(dhBase, streamId_, sharedMemory);
208 if (ret != SUCCESS) {
209 DHLOGE("AcquireBuffer devId: %{public}s dhId: %{public}s streamId: %{public}d ret: %{public}d",
210 GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamId_, ret);
211 return DCAMERA_BAD_OPERATE;
212 }
213 do {
214 ret = CheckSharedMemory(sharedMemory, buffer);
215 if (ret != DCAMERA_OK) {
216 DHLOGE("CheckSharedMemory failed devId: %{public}s dhId: %{public}s", GetAnonyString(devId_).c_str(),
217 GetAnonyString(dhId_).c_str());
218 break;
219 }
220 sharedMemory.bufferHandle_->GetBufferHandle()->virAddr =
221 DCameraMemoryMap(sharedMemory.bufferHandle_->GetBufferHandle());
222 if (sharedMemory.bufferHandle_->GetBufferHandle()->virAddr == nullptr) {
223 DHLOGE("mmap failed devId: %{public}s dhId: %{public}s", GetAnonyString(devId_).c_str(),
224 GetAnonyString(dhId_).c_str());
225 break;
226 }
227 ret = memcpy_s(sharedMemory.bufferHandle_->GetBufferHandle()->virAddr, sharedMemory.size_, buffer->Data(),
228 buffer->Size());
229 if (ret != EOK) {
230 DHLOGE("memcpy_s devId: %s dhId: %s streamId: %{public}d bufSize: %zu, addressSize: %{public}d",
231 GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamId_,
232 buffer->Size(), sharedMemory.size_);
233 break;
234 }
235 sharedMemory.size_ = buffer->Size();
236 } while (0);
237 ret = camHdiProvider_->ShutterBuffer(dhBase, streamId_, sharedMemory);
238 if (sharedMemory.bufferHandle_ != nullptr) {
239 DCameraMemoryUnmap(sharedMemory.bufferHandle_->GetBufferHandle());
240 }
241 if (ret != SUCCESS) {
242 DHLOGE("ShutterBuffer devId: %{public}s dhId: %{public}s streamId: %{public}d ret: %{public}d",
243 GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamId_, ret);
244 return DCAMERA_BAD_OPERATE;
245 }
246 return ret;
247 }
248
CheckSharedMemory(const DCameraBuffer & sharedMemory,const std::shared_ptr<DataBuffer> & buffer)249 int32_t DCameraStreamDataProcessProducer::CheckSharedMemory(const DCameraBuffer& sharedMemory,
250 const std::shared_ptr<DataBuffer>& buffer)
251 {
252 if (sharedMemory.bufferHandle_ == nullptr || sharedMemory.bufferHandle_->GetBufferHandle() == nullptr) {
253 DHLOGE("bufferHandle read failed devId: %{public}s dhId: %{public}s", GetAnonyString(devId_).c_str(),
254 GetAnonyString(dhId_).c_str());
255 return DCAMERA_MEMORY_OPT_ERROR;
256 }
257
258 if (buffer->Size() > sharedMemory.size_) {
259 uint64_t buffersSize = static_cast<uint64_t>(buffer->Size());
260 DHLOGE("sharedMemory devId: %{public}s dhId: %{public}s streamId: %{public}d bufSize: %{public}" PRIu64
261 ", addressSize: %{public}d", GetAnonyString(devId_).c_str(), GetAnonyString(dhId_).c_str(), streamId_,
262 buffersSize, sharedMemory.size_);
263 return DCAMERA_MEMORY_OPT_ERROR;
264 }
265
266 return DCAMERA_OK;
267 }
268
OnSmoothFinished(const std::shared_ptr<IFeedableData> & data)269 void DCameraStreamDataProcessProducer::OnSmoothFinished(const std::shared_ptr<IFeedableData>& data)
270 {
271 std::shared_ptr<DataBuffer> buffer = std::reinterpret_pointer_cast<DataBuffer>(data);
272 DHBase dhBase;
273 dhBase.deviceId_ = devId_;
274 dhBase.dhId_ = dhId_;
275 #ifdef DUMP_DCAMERA_FILE
276 if (DcameraHidumper::GetInstance().GetDumpFlag() &&
277 (IsUnderDumpMaxSize(DUMP_PATH + TO_DISPLAY) == DCAMERA_OK)) {
278 DumpBufferToFile(DUMP_PATH + TO_DISPLAY, buffer->Data(), buffer->Size());
279 }
280 #endif
281 auto feedFunc = [this, dhBase, buffer]() {
282 FeedStreamToDriver(dhBase, buffer);
283 };
284 if (eventHandler_ != nullptr) {
285 eventHandler_->PostTask(feedFunc);
286 }
287 }
288 } // namespace DistributedHardware
289 } // namespace OHOS
290