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