• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 <cstdlib>
17 #include <iomanip>
18 #include <map>
19 #include <string>
20 #include <variant>
21 #include <vector>
22 #include "ffi_remote_data.h"
23 #include "securec.h"
24 
25 #include "camera_error.h"
26 #include "camera_log.h"
27 #include "camera_manager.h"
28 #include "surface_utils.h"
29 #include "video_output_impl.h"
30 
31 using namespace OHOS::FFI;
32 
33 namespace OHOS::CameraStandard {
34 thread_local sptr<VideoOutput> CJVideoOutput::sVideoOutput_ = nullptr;
35 
OnFrameStarted() const36 void CJVideoCallbackListener::OnFrameStarted() const
37 {
38     std::lock_guard<std::mutex> lock(frameStartedMutex);
39     if (frameStartedCallbackList.size() == 0) {
40         return;
41     }
42     for (size_t i = 0; i < frameStartedCallbackList.size(); i++) {
43         if (frameStartedCallbackList[i] != nullptr) {
44             frameStartedCallbackList[i]->ref();
45         }
46     }
47 }
48 
OnFrameEnded(const int32_t frameCount) const49 void CJVideoCallbackListener::OnFrameEnded(const int32_t frameCount) const
50 {
51     std::lock_guard<std::mutex> lock(frameEndedMutex);
52     if (frameEndedCallbackList.size() == 0) {
53         return;
54     }
55     for (size_t i = 0; i < frameEndedCallbackList.size(); i++) {
56         if (frameEndedCallbackList[i] != nullptr) {
57             frameEndedCallbackList[i]->ref();
58         }
59     }
60 }
61 
OnError(const int32_t errorCode) const62 void CJVideoCallbackListener::OnError(const int32_t errorCode) const
63 {
64     std::lock_guard<std::mutex> lock(errorMutex);
65     if (errorCallbackList.size() == 0) {
66         return;
67     }
68     for (size_t i = 0; i < errorCallbackList.size(); i++) {
69         if (errorCallbackList[i] != nullptr) {
70             errorCallbackList[i]->ref(errorCode);
71         }
72     }
73 }
74 
OnDeferredVideoEnhancementInfo(const CaptureEndedInfoExt info) const75 void CJVideoCallbackListener::OnDeferredVideoEnhancementInfo(const CaptureEndedInfoExt info) const
76 {
77 }
78 
CJVideoOutput()79 CJVideoOutput::CJVideoOutput()
80 {
81     videoOutput_ = sVideoOutput_;
82     sVideoOutput_ = nullptr;
83 }
84 
GetCameraOutput()85 sptr<CameraStandard::CaptureOutput> CJVideoOutput::GetCameraOutput()
86 {
87     return videoOutput_;
88 }
89 
Release()90 int32_t CJVideoOutput::Release()
91 {
92     if (videoOutput_ == nullptr) {
93         return CameraError::CAMERA_SERVICE_ERROR;
94     }
95     return videoOutput_->Release();
96 }
97 
CreateVideoOutput(VideoProfile & profile,std::string surfaceId)98 int32_t CJVideoOutput::CreateVideoOutput(VideoProfile &profile, std::string surfaceId)
99 {
100     uint64_t iSurfaceId;
101     std::istringstream iss(surfaceId);
102     iss >> iSurfaceId;
103     sptr<Surface> surface = SurfaceUtils::GetInstance()->GetSurface(iSurfaceId);
104     if (surface == nullptr) {
105         MEDIA_ERR_LOG("failed to get surface from SurfaceUtils");
106         return CameraError::CAMERA_SERVICE_ERROR;
107     }
108     surface->SetUserData(CameraManager::surfaceFormat, std::to_string(profile.GetCameraFormat()));
109     int retCode = CameraManager::GetInstance()->CreateVideoOutput(profile, surface, &sVideoOutput_);
110     if (sVideoOutput_ == nullptr) {
111         MEDIA_ERR_LOG("failed to create VideoOutput");
112         return CameraError::CAMERA_SERVICE_ERROR;
113     }
114     return retCode;
115 }
116 
CreateVideoOutputWithOutProfile(std::string surfaceId)117 int32_t CJVideoOutput::CreateVideoOutputWithOutProfile(std::string surfaceId)
118 {
119     uint64_t iSurfaceId;
120     std::istringstream iss(surfaceId);
121     iss >> iSurfaceId;
122     sptr<Surface> surface = SurfaceUtils::GetInstance()->GetSurface(iSurfaceId);
123     if (surface == nullptr) {
124         MEDIA_ERR_LOG("failed to get surface from SurfaceUtils");
125         return CameraError::CAMERA_SERVICE_ERROR;
126     }
127     int retCode = CameraManager::GetInstance()->CreateVideoOutputWithoutProfile(surface, &sVideoOutput_);
128     if (sVideoOutput_ == nullptr) {
129         MEDIA_ERR_LOG("failed to create VideoOutput");
130         return CameraError::CAMERA_SERVICE_ERROR;
131     }
132     return retCode;
133 }
134 
Start()135 int32_t CJVideoOutput::Start()
136 {
137     if (videoOutput_ == nullptr) {
138         return CameraError::CAMERA_SERVICE_ERROR;
139     }
140     return videoOutput_->Start();
141 }
142 
Stop()143 int32_t CJVideoOutput::Stop()
144 {
145     if (videoOutput_ == nullptr) {
146         return CameraError::CAMERA_SERVICE_ERROR;
147     }
148     return videoOutput_->Stop();
149 }
150 
GetSupportedFrameRates(int32_t * errCode)151 CArrFrameRateRange CJVideoOutput::GetSupportedFrameRates(int32_t *errCode)
152 {
153     MEDIA_INFO_LOG("GetSupportedFrameRates is called!");
154     CArrFrameRateRange cArrFrameRateRange = CArrFrameRateRange{0};
155     if (videoOutput_ == nullptr) {
156         MEDIA_ERR_LOG("videoOutput is nullptr.");
157         *errCode = CameraError::CAMERA_SERVICE_ERROR;
158         return cArrFrameRateRange;
159     }
160     std::vector<std::vector<int32_t>> supportedFrameRatesRange = videoOutput_->GetSupportedFrameRates();
161     MEDIA_INFO_LOG("CJVideoOutput::GetSupportedFrameRates len = %{public}zu", supportedFrameRatesRange.size());
162     if (supportedFrameRatesRange.size() > 0) {
163         FrameRateRange *retArrFrameRateRange =
164             (FrameRateRange *)malloc(sizeof(FrameRateRange) * supportedFrameRatesRange.size());
165         if (retArrFrameRateRange == nullptr) {
166             *errCode = CameraError::CAMERA_SERVICE_ERROR;
167             return cArrFrameRateRange;
168         }
169         for (size_t i = 0; i < supportedFrameRatesRange.size(); i++) {
170             retArrFrameRateRange[i].min = supportedFrameRatesRange[i][0];
171             retArrFrameRateRange[i].max = supportedFrameRatesRange[i][1];
172         }
173         cArrFrameRateRange.head = retArrFrameRateRange;
174         cArrFrameRateRange.size = static_cast<int64_t>(supportedFrameRatesRange.size());
175     } else {
176         MEDIA_ERR_LOG("cArrFrameRateRange is empty!");
177     }
178     return cArrFrameRateRange;
179 }
180 
SetFrameRate(int32_t minFps,int32_t maxFps)181 int32_t CJVideoOutput::SetFrameRate(int32_t minFps, int32_t maxFps)
182 {
183     MEDIA_INFO_LOG("SetFrameRate is called");
184     if (videoOutput_ == nullptr) {
185         MEDIA_ERR_LOG("videoOutput is nullptr.");
186         return CameraError::CAMERA_SERVICE_ERROR;
187     }
188     return videoOutput_->SetFrameRate(minFps, maxFps);
189 }
190 
GetActiveFrameRate(int32_t * errCode)191 FrameRateRange CJVideoOutput::GetActiveFrameRate(int32_t *errCode)
192 {
193     MEDIA_INFO_LOG("GetActiveFrameRate is called");
194     FrameRateRange frameRateRange = FrameRateRange{0};
195     if (videoOutput_ == nullptr) {
196         MEDIA_ERR_LOG("videoOutput is nullptr.");
197         *errCode = CameraError::CAMERA_SERVICE_ERROR;
198         return frameRateRange;
199     }
200     std::vector<int32_t> fRateRange = videoOutput_->GetFrameRateRange();
201     frameRateRange.min = fRateRange[0];
202     frameRateRange.max = fRateRange[1];
203     return frameRateRange;
204 }
205 
GetActiveProfile(int32_t * errCode)206 CJVideoProfile CJVideoOutput::GetActiveProfile(int32_t *errCode)
207 {
208     MEDIA_DEBUG_LOG("VideoOutputNapi::GetActiveProfile is called");
209     CJVideoProfile cjVideoProfile = CJVideoProfile{0};
210     if (videoOutput_ == nullptr) {
211         MEDIA_ERR_LOG("videoOutput is nullptr.");
212         *errCode = CameraError::CAMERA_SERVICE_ERROR;
213         return cjVideoProfile;
214     }
215     auto profile = videoOutput_->GetVideoProfile();
216     if (profile == nullptr) {
217         *errCode = CameraError::CAMERA_SERVICE_ERROR;
218         return cjVideoProfile;
219     }
220     cjVideoProfile.format = profile->GetCameraFormat();
221     Size size = profile->GetSize();
222     cjVideoProfile.width = size.width;
223     cjVideoProfile.height = size.height;
224     std::vector<int32_t> vpi_framerates = profile->GetFrameRates();
225     cjVideoProfile.frameRateRange.min = vpi_framerates[0];
226     cjVideoProfile.frameRateRange.max = vpi_framerates[1];
227     return cjVideoProfile;
228 }
229 
GetVideoRotation(int32_t imageRotation,int32_t * errCode)230 int32_t CJVideoOutput::GetVideoRotation(int32_t imageRotation, int32_t *errCode)
231 {
232     MEDIA_DEBUG_LOG("GetVideoRotation is called!");
233     if (videoOutput_ == nullptr) {
234         MEDIA_ERR_LOG("videoOutput is nullptr.");
235         *errCode = CameraError::CAMERA_SERVICE_ERROR;
236         return -1;
237     }
238     int32_t retCode = videoOutput_->GetVideoRotation(imageRotation);
239     if (retCode == CameraError::CAMERA_SERVICE_ERROR) {
240         *errCode = CameraError::CAMERA_SERVICE_ERROR;
241         return -1;
242     }
243     return retCode;
244 }
245 
OnFrameStart(int64_t callbackId)246 void CJVideoOutput::OnFrameStart(int64_t callbackId)
247 {
248     if (videoCallback_ == nullptr) {
249         videoCallback_ = std::make_shared<CJVideoCallbackListener>();
250         if (videoCallback_ == nullptr || videoOutput_ == nullptr) {
251             return;
252         }
253         videoOutput_->SetCallback(videoCallback_);
254     }
255     auto cFunc = reinterpret_cast<void (*)()>(callbackId);
256     auto callback = [lambda = CJLambda::Create(cFunc)]() -> void { lambda(); };
257     auto callbackRef = std::make_shared<CallbackRef<>>(callback, callbackId);
258 
259     std::lock_guard<std::mutex> lock(videoCallback_->frameStartedMutex);
260     videoCallback_->frameStartedCallbackList.push_back(callbackRef);
261 }
262 
OffFrameStart(int64_t callbackId)263 void CJVideoOutput::OffFrameStart(int64_t callbackId)
264 {
265     if (videoCallback_ == nullptr) {
266         return;
267     }
268     std::lock_guard<std::mutex> lock(videoCallback_->frameStartedMutex);
269     for (auto it = videoCallback_->frameStartedCallbackList.begin();
270         it != videoCallback_->frameStartedCallbackList.end(); it++) {
271         if ((*it)->id == callbackId) {
272             videoCallback_->frameStartedCallbackList.erase(it);
273             break;
274         }
275     }
276 }
277 
OffAllFrameStart()278 void CJVideoOutput::OffAllFrameStart()
279 {
280     if (videoCallback_ == nullptr) {
281         return;
282     }
283     std::lock_guard<std::mutex> lock(videoCallback_->frameStartedMutex);
284     videoCallback_->frameStartedCallbackList.clear();
285 }
286 
OnFrameEnd(int64_t callbackId)287 void CJVideoOutput::OnFrameEnd(int64_t callbackId)
288 {
289     if (videoCallback_ == nullptr) {
290         videoCallback_ = std::make_shared<CJVideoCallbackListener>();
291         if (videoCallback_ == nullptr || videoOutput_ == nullptr) {
292             return;
293         }
294         videoOutput_->SetCallback(videoCallback_);
295     }
296     auto cFunc = reinterpret_cast<void (*)()>(callbackId);
297     auto callback = [lambda = CJLambda::Create(cFunc)]() -> void { lambda(); };
298     auto callbackRef = std::make_shared<CallbackRef<>>(callback, callbackId);
299 
300     std::lock_guard<std::mutex> lock(videoCallback_->frameEndedMutex);
301     videoCallback_->frameEndedCallbackList.push_back(callbackRef);
302 }
303 
OffFrameEnd(int64_t callbackId)304 void CJVideoOutput::OffFrameEnd(int64_t callbackId)
305 {
306     if (videoCallback_ == nullptr) {
307         return;
308     }
309     std::lock_guard<std::mutex> lock(videoCallback_->frameEndedMutex);
310     for (auto it = videoCallback_->frameEndedCallbackList.begin();
311         it != videoCallback_->frameEndedCallbackList.end(); it++) {
312         if ((*it)->id == callbackId) {
313             videoCallback_->frameEndedCallbackList.erase(it);
314             break;
315         }
316     }
317 }
318 
OffAllFrameEnd()319 void CJVideoOutput::OffAllFrameEnd()
320 {
321     if (videoCallback_ == nullptr) {
322         return;
323     }
324     std::lock_guard<std::mutex> lock(videoCallback_->frameEndedMutex);
325     videoCallback_->frameEndedCallbackList.clear();
326 }
327 
OnError(int64_t callbackId)328 void CJVideoOutput::OnError(int64_t callbackId)
329 {
330     if (videoCallback_ == nullptr) {
331         videoCallback_ = std::make_shared<CJVideoCallbackListener>();
332         if (videoCallback_ == nullptr || videoOutput_ == nullptr) {
333             return;
334         }
335         videoOutput_->SetCallback(videoCallback_);
336     }
337     auto cFunc = reinterpret_cast<void (*)(const int32_t errorCode)>(callbackId);
338     auto callback = [lambda = CJLambda::Create(cFunc)](const int32_t errorCode) -> void { lambda(errorCode); };
339     auto callbackRef = std::make_shared<CallbackRef<const int32_t>>(callback, callbackId);
340 
341     std::lock_guard<std::mutex> lock(videoCallback_->errorMutex);
342     videoCallback_->errorCallbackList.push_back(callbackRef);
343 }
344 
OffError(int64_t callbackId)345 void CJVideoOutput::OffError(int64_t callbackId)
346 {
347     if (videoCallback_ == nullptr) {
348         return;
349     }
350     std::lock_guard<std::mutex> lock(videoCallback_->errorMutex);
351     for (auto it = videoCallback_->errorCallbackList.begin(); it != videoCallback_->errorCallbackList.end(); it++) {
352         if ((*it)->id == callbackId) {
353             videoCallback_->errorCallbackList.erase(it);
354             break;
355         }
356     }
357 }
358 
OffAllError()359 void CJVideoOutput::OffAllError()
360 {
361     if (videoCallback_ == nullptr) {
362         return;
363     }
364     std::lock_guard<std::mutex> lock(videoCallback_->errorMutex);
365     videoCallback_->errorCallbackList.clear();
366 }
367 
368 } // namespace OHOS::CameraStandard