• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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