1 /*
2 * Copyright (c) 2021-2022 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 <unistd.h>
17 #include "input/camera_input.h"
18 #include "input/camera_manager.h"
19 #include "media_errors.h"
20 #include "camera_log.h"
21 #include "recorder.h"
22 #include "surface.h"
23 #include "test_common.h"
24
25 #include "ipc_skeleton.h"
26 #include "access_token.h"
27 #include "hap_token_info.h"
28 #include "accesstoken_kit.h"
29 #include "nativetoken_kit.h"
30 #include "token_setproc.h"
31
32 using namespace std;
33 using namespace OHOS;
34 using namespace OHOS::CameraStandard;
35 using namespace OHOS::Media;
36
37 namespace {
38 int32_t g_videoFd = -1;
39 class TestVideoRecorderCallback : public RecorderCallback {
40 public:
OnError(RecorderErrorType errorType,int32_t errorCode)41 void OnError(RecorderErrorType errorType, int32_t errorCode)
42 {
43 MEDIA_DEBUG_LOG("OnError errorType is %{public}d, errorCode is %{public}d", errorType, errorCode);
44 }
OnInfo(int32_t type,int32_t extra)45 void OnInfo(int32_t type, int32_t extra)
46 {
47 MEDIA_DEBUG_LOG("OnInfo Type is %{public}d, extra is %{public}d", type, extra);
48 }
49 };
50
ConfigureVideoParams(const std::shared_ptr<Recorder> & recorder,int32_t videoSourceId,int32_t width,int32_t height)51 bool ConfigureVideoParams(const std::shared_ptr<Recorder> &recorder,
52 int32_t videoSourceId, int32_t width, int32_t height)
53 {
54 int32_t encodingBitRate = 48000;
55 int32_t frameRate = 30;
56 int32_t captureRate = 30;
57
58 if (recorder->SetVideoEncoder(videoSourceId, Media::H264)) {
59 MEDIA_DEBUG_LOG("Set Video Encoder Failed");
60 return false;
61 }
62
63 if (recorder->SetVideoSize(videoSourceId, width, height)) {
64 MEDIA_DEBUG_LOG("Set Video Size Failed");
65 return false;
66 }
67
68 if (recorder->SetVideoFrameRate(videoSourceId, frameRate)) {
69 MEDIA_DEBUG_LOG("Set Video Frame Rate Failed");
70 return false;
71 }
72
73 if (recorder->SetVideoEncodingBitRate(videoSourceId, encodingBitRate)) {
74 MEDIA_DEBUG_LOG("Set Video Encoding Bit Rate Failed");
75 return false;
76 }
77
78 if (recorder->SetCaptureRate(videoSourceId, captureRate)) {
79 MEDIA_DEBUG_LOG("Set Capture Rate Failed");
80 return false;
81 }
82
83 return true;
84 }
85
ConfigureAudioParams(const std::shared_ptr<Recorder> & recorder,int32_t audioSourceId)86 bool ConfigureAudioParams(const std::shared_ptr<Recorder> &recorder, int32_t audioSourceId)
87 {
88 int32_t channelCount = 2;
89 int32_t sampleRate = 48000;
90 int32_t encodingBitRate = 48000;
91
92 if (recorder->SetAudioEncoder(audioSourceId, Media::AAC_LC)) {
93 MEDIA_DEBUG_LOG("Set Audio Encoder Failed");
94 return false;
95 }
96
97 if (recorder->SetAudioSampleRate(audioSourceId, sampleRate)) {
98 MEDIA_DEBUG_LOG("Set Audio Sample Rate Failed");
99 return false;
100 }
101
102 if (recorder->SetAudioChannels(audioSourceId, channelCount)) {
103 MEDIA_DEBUG_LOG("Set Audio Channels Failed");
104 return false;
105 }
106
107 if (recorder->SetAudioEncodingBitRate(audioSourceId, encodingBitRate)) {
108 MEDIA_DEBUG_LOG("Set Audio Encoding Bit Rate Failed");
109 return false;
110 }
111
112 return true;
113 }
114
CreateAndConfigureRecorder(std::shared_ptr<Recorder> & recorder,int32_t & videoSourceId,int32_t width,int32_t height)115 bool CreateAndConfigureRecorder(std::shared_ptr<Recorder> &recorder,
116 int32_t &videoSourceId, int32_t width, int32_t height)
117 {
118 int32_t maxDuration = 36000;
119
120 recorder = RecorderFactory::CreateRecorder();
121 if (recorder == nullptr) {
122 MEDIA_DEBUG_LOG("Create Recorder Failed");
123 return false;
124 }
125
126 int32_t audioSourceId = 0;
127 if (recorder->SetVideoSource(Media::VIDEO_SOURCE_SURFACE_ES, videoSourceId)) {
128 MEDIA_DEBUG_LOG("Set Video Source Failed");
129 return false;
130 }
131
132 if (recorder->SetAudioSource(Media::AUDIO_MIC, audioSourceId)) {
133 MEDIA_DEBUG_LOG("Set Audio Source Failed");
134 return false;
135 }
136
137 if (recorder->SetOutputFormat(Media::FORMAT_MPEG_4)) {
138 MEDIA_DEBUG_LOG("Set Output Format Failed");
139 return false;
140 }
141
142 if (!ConfigureVideoParams(recorder, videoSourceId, width, height)) {
143 MEDIA_DEBUG_LOG("Failed to configure video for recorder");
144 return false;
145 }
146
147 if (!ConfigureAudioParams(recorder, audioSourceId)) {
148 MEDIA_DEBUG_LOG("Failed to configure audio for recorder");
149 return false;
150 }
151
152 if (recorder->SetMaxDuration(maxDuration)) {
153 MEDIA_DEBUG_LOG("Set Max Duration Failed");
154 return false;
155 }
156
157 // need use fd not path
158
159 if (recorder->SetRecorderCallback(std::make_shared<TestVideoRecorderCallback>())) {
160 MEDIA_DEBUG_LOG("Set Recorder Callback Failed");
161 return false;
162 }
163 return true;
164 }
165 }
166
main(int argc,char ** argv)167 int main(int argc, char **argv)
168 {
169 const int32_t previewFormatIndex = 1;
170 const int32_t previewWidthIndex = 2;
171 const int32_t previewHeightIndex = 3;
172 const int32_t videoFormatIndex = 4;
173 const int32_t videoWidthIndex = 5;
174 const int32_t videoHeightIndex = 6;
175 const int32_t validArgCount = 7;
176 const int32_t videoCaptureDuration = 5; // Sleep for 5 sec
177 const int32_t videoPauseDuration = 2; // Sleep for 2 sec
178 const int32_t previewVideoGap = 2; // Sleep for 2 sec
179 const char* testName = "camera_video";
180 int32_t ret = -1;
181 int32_t previewFd = -1;
182 int32_t previewFormat = CAMERA_FORMAT_YUV_420_SP;
183 int32_t previewWidth = 640;
184 int32_t previewHeight = 480;
185 int32_t videoFormat = CAMERA_FORMAT_YUV_420_SP;
186 int32_t videoWidth = 640;
187 int32_t videoHeight = 360;
188 bool isResolutionConfigured = false;
189 bool isRecorder = false;
190 Size previewsize;
191 Size videosize;
192 std::vector<int32_t> videoframerates;
193
194 MEDIA_DEBUG_LOG("Camera new sample begin without recorder");
195 // Update sizes if enough number of valid arguments are passed
196 if (argc == validArgCount) {
197 // Validate arguments and consider if valid
198 for (int counter = 1; counter < argc; counter++) {
199 if (!TestUtils::IsNumber(argv[counter])) {
200 cout << "Invalid argument: " << argv[counter] << endl;
201 cout << "Retry by giving proper sizes" << endl;
202 return 0;
203 }
204 }
205 previewFormat = atoi(argv[previewFormatIndex]);
206 previewWidth = atoi(argv[previewWidthIndex]);
207 previewHeight = atoi(argv[previewHeightIndex]);
208 videoFormat = atoi(argv[videoFormatIndex]);
209 videoWidth = atoi(argv[videoWidthIndex]);
210 videoHeight = atoi(argv[videoHeightIndex]);
211 isResolutionConfigured = true;
212 } else if (argc != 1) {
213 cout << "Pass " << (validArgCount - 1) << "arguments" << endl;
214 cout << "PreviewFormat, PreviewWidth, PreviewHeight, VideoFormat, VideoWidth, VideoHeight" << endl;
215 return 0;
216 }
217
218 uint64_t tokenId;
219 const char *perms[0];
220 perms[0] = "ohos.permission.CAMERA";
221 NativeTokenInfoParams infoInstance = {
222 .dcapsNum = 0,
223 .permsNum = 1,
224 .aclsNum = 0,
225 .dcaps = NULL,
226 .perms = perms,
227 .acls = NULL,
228 .processName = "camera_video",
229 .aplStr = "system_basic",
230 };
231 tokenId = GetAccessTokenId(&infoInstance);
232 SetSelfTokenID(tokenId);
233 OHOS::Security::AccessToken::AccessTokenKit::ReloadNativeTokenInfo();
234
235 sptr<CameraManager> camManagerObj = CameraManager::GetInstance();
236 MEDIA_DEBUG_LOG("Setting callback to listen camera status and flash status");
237 camManagerObj->SetCallback(std::make_shared<TestCameraMngerCallback>(testName));
238 std::vector<sptr<CameraDevice>> cameraObjList = camManagerObj->GetSupportedCameras();
239 if (cameraObjList.size() == 0) {
240 MEDIA_DEBUG_LOG("No camera devices");
241 return 0;
242 }
243
244 MEDIA_DEBUG_LOG("Camera ID count: %{public}zu", cameraObjList.size());
245 for (auto& it : cameraObjList) {
246 MEDIA_DEBUG_LOG("Camera ID: %{public}s", it->GetID().c_str());
247 }
248
249 sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession();
250 if (captureSession == nullptr) {
251 MEDIA_DEBUG_LOG("Failed to create capture session");
252 return 0;
253 }
254
255 captureSession->BeginConfig();
256
257 sptr<CaptureInput> captureInput = camManagerObj->CreateCameraInput(cameraObjList[0]);
258 if (captureInput == nullptr) {
259 MEDIA_DEBUG_LOG("Failed to create camera input");
260 return 0;
261 }
262
263 sptr<CameraInput> cameraInput = (sptr<CameraInput> &)captureInput;
264 cameraInput->Open();
265 if (!isResolutionConfigured) {
266 std::vector<CameraFormat> previewFormats;
267 std::vector<CameraFormat> videoFormats;
268 std::vector<Size> previewSizes;
269 std::vector<Size> videoSizes;
270 sptr<CameraOutputCapability> outputcapability = camManagerObj->GetSupportedOutputCapability(cameraObjList[0]);
271 std::vector<Profile> previewProfiles = outputcapability->GetPreviewProfiles();
272 for (auto i : previewProfiles) {
273 previewFormats.push_back(i.GetCameraFormat());
274 previewSizes.push_back(i.GetSize());
275 }
276 MEDIA_DEBUG_LOG("Supported preview formats:");
277 for (auto &formatPreview : previewFormats) {
278 MEDIA_DEBUG_LOG("format : %{public}d", formatPreview);
279 }
280 if (std::find(previewFormats.begin(), previewFormats.end(), CAMERA_FORMAT_YUV_420_SP)
281 != previewFormats.end()) {
282 previewFormat = CAMERA_FORMAT_YUV_420_SP;
283 MEDIA_DEBUG_LOG("CAMERA_FORMAT_YUV_420_SP format is present in supported preview formats");
284 } else if (!previewFormats.empty()) {
285 previewFormat = previewFormats[0];
286 MEDIA_DEBUG_LOG("CAMERA_FORMAT_YUV_420_SP format is not present in supported preview formats");
287 }
288 std::vector<VideoProfile> videoProfiles = outputcapability->GetVideoProfiles();
289 for (auto i : videoProfiles) {
290 videoFormats.push_back(i.GetCameraFormat());
291 videoSizes.push_back(i.GetSize());
292 videoframerates = i.GetFrameRates();
293 }
294 MEDIA_DEBUG_LOG("Supported video formats:");
295 for (auto &format : videoFormats) {
296 MEDIA_DEBUG_LOG("format : %{public}d", format);
297 }
298 if (std::find(videoFormats.begin(), videoFormats.end(), CAMERA_FORMAT_YUV_420_SP)
299 != videoFormats.end()) {
300 videoFormat = CAMERA_FORMAT_YUV_420_SP;
301 MEDIA_DEBUG_LOG("CAMERA_FORMAT_YUV_420_SP format is present in supported video formats");
302 } else if (!videoFormats.empty()) {
303 videoFormat = videoFormats[0];
304 MEDIA_DEBUG_LOG("CAMERA_FORMAT_YUV_420_SP format is not present in supported video formats");
305 }
306 MEDIA_DEBUG_LOG("Supported sizes for preview:");
307 for (auto &size : previewSizes) {
308 MEDIA_DEBUG_LOG("width: %{public}d, height: %{public}d", size.width, size.height);
309 }
310 MEDIA_DEBUG_LOG("Supported sizes for video:");
311 for (auto &sizeVideo : videoSizes) {
312 MEDIA_DEBUG_LOG("width: %{public}d, height: %{public}d", sizeVideo.width, sizeVideo.height);
313 }
314 if (!previewSizes.empty()) {
315 previewWidth = previewSizes[0].width;
316 previewHeight = previewSizes[0].height;
317 }
318 if (!videoSizes.empty()) {
319 videoWidth = videoSizes[0].width;
320 videoHeight = videoSizes[0].height;
321 }
322 }
323
324 MEDIA_DEBUG_LOG("previewFormat: %{public}d, previewWidth: %{public}d, previewHeight: %{public}d",
325 previewFormat, previewWidth, previewHeight);
326 MEDIA_DEBUG_LOG("videoFormat: %{public}d, videoWidth: %{public}d, videoHeight: %{public}d",
327 videoFormat, videoWidth, videoHeight);
328
329 cameraInput->SetErrorCallback(std::make_shared<TestDeviceCallback>(testName));
330 ret = captureSession->AddInput(captureInput);
331 if (ret != 0) {
332 MEDIA_DEBUG_LOG("Add input to session is failed, ret: %{public}d", ret);
333 return 0;
334 }
335
336 sptr<Surface> previewSurface = Surface::CreateSurfaceAsConsumer();
337 previewSurface->SetDefaultWidthAndHeight(previewWidth, previewHeight);
338 previewSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(previewFormat));
339 previewsize.width = previewWidth;
340 previewsize.height = previewHeight;
341 Profile previewprofile = Profile(static_cast<CameraFormat>(previewFormat), previewsize);
342 sptr<SurfaceListener> listener = new SurfaceListener("Preview", SurfaceType::PREVIEW, previewFd, previewSurface);
343 previewSurface->RegisterConsumerListener((sptr<IBufferConsumerListener> &)listener);
344
345 sptr<CaptureOutput> previewOutput = camManagerObj->CreatePreviewOutput(previewprofile, previewSurface);
346 if (previewOutput == nullptr) {
347 MEDIA_DEBUG_LOG("Failed to create preview output");
348 return 0;
349 }
350
351 MEDIA_DEBUG_LOG("Setting preview callback");
352 ((sptr<PreviewOutput> &)previewOutput)->SetCallback(std::make_shared<TestPreviewOutputCallback>(testName));
353 ret = captureSession->AddOutput(previewOutput);
354 if (ret != 0) {
355 MEDIA_DEBUG_LOG("Failed to Add output to session, ret: %{public}d", ret);
356 return 0;
357 }
358
359 sptr<Surface> videoSurface = nullptr;
360 std::shared_ptr<Recorder> recorder = nullptr;
361 if (isRecorder) {
362 int32_t videoSourceId = 0;
363 if (!CreateAndConfigureRecorder(recorder, videoSourceId, videoWidth, videoHeight)) {
364 MEDIA_DEBUG_LOG("Failed to create and configure recorder");
365 return 0;
366 }
367
368 if (recorder->Prepare()) {
369 MEDIA_DEBUG_LOG("Failed to prepare recorder");
370 return 0;
371 }
372
373 videoSurface = recorder->GetSurface(videoSourceId);
374 if (videoSurface == nullptr) {
375 MEDIA_DEBUG_LOG("Failed to get surface from recorder");
376 return 0;
377 }
378 videoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(videoFormat));
379 } else {
380 videoSurface = Surface::CreateSurfaceAsConsumer();
381 sptr<SurfaceListener> videoListener = new SurfaceListener("Video", SurfaceType::VIDEO, g_videoFd, videoSurface);
382 videoSurface->RegisterConsumerListener((sptr<IBufferConsumerListener> &)videoListener);
383 }
384 videosize.width = videoWidth;
385 videosize.height = videoHeight;
386 VideoProfile videoprofile = VideoProfile(static_cast<CameraFormat>(videoFormat), videosize, videoframerates);
387
388 sptr<CaptureOutput> videoOutput = camManagerObj->CreateVideoOutput(videoprofile, videoSurface);
389 if (videoOutput == nullptr) {
390 MEDIA_DEBUG_LOG("Failed to create video output");
391 return 0;
392 }
393
394 MEDIA_DEBUG_LOG("Setting video callback");
395 ((sptr<VideoOutput> &)videoOutput)->SetCallback(std::make_shared<TestVideoOutputCallback>(testName));
396 ret = captureSession->AddOutput(videoOutput);
397 if (ret != 0) {
398 MEDIA_DEBUG_LOG("Failed to Add output to session, ret: %{public}d", ret);
399 return 0;
400 }
401
402 ret = captureSession->CommitConfig();
403 if (ret != 0) {
404 MEDIA_DEBUG_LOG("Failed to commit session config, ret: %{public}d", ret);
405 return 0;
406 }
407
408 ret = captureSession->Start();
409 if (ret != 0) {
410 MEDIA_DEBUG_LOG("Failed to start session, ret: %{public}d", ret);
411 return 0;
412 }
413 sleep(previewVideoGap);
414
415 MEDIA_DEBUG_LOG("Preview started");
416 sleep(previewVideoGap);
417 MEDIA_DEBUG_LOG("Start video recording");
418
419 ret = ((sptr<VideoOutput> &)videoOutput)->Start();
420 if (ret != 0) {
421 MEDIA_DEBUG_LOG("Failed to start video output, ret: %{public}d", ret);
422 return 0;
423 }
424
425 if (recorder != nullptr) {
426 ret = recorder->Start();
427 if (ret != 0) {
428 MEDIA_DEBUG_LOG("Failed to start recorder, return: %{public}s",
429 OHOS::Media::MSErrorToString(static_cast<OHOS::Media::MediaServiceErrCode>(ret)).c_str());
430 return 0;
431 }
432 }
433
434 MEDIA_DEBUG_LOG("Wait for 5 seconds after start");
435 sleep(videoCaptureDuration);
436 MEDIA_DEBUG_LOG("Pause video recording for 2 sec");
437 ret = ((sptr<VideoOutput> &)videoOutput)->Pause();
438 if (ret != 0) {
439 MEDIA_DEBUG_LOG("Failed to pause video output, ret: %{public}d", ret);
440 return 0;
441 }
442
443 if (recorder != nullptr) {
444 ret = recorder->Pause();
445 if (ret != 0) {
446 MEDIA_DEBUG_LOG("Failed to pause recorder, return: %{public}s",
447 OHOS::Media::MSErrorToString(static_cast<OHOS::Media::MediaServiceErrCode>(ret)).c_str());
448 }
449 }
450 sleep(videoPauseDuration);
451 MEDIA_DEBUG_LOG("Resume video recording");
452 ret = ((sptr<VideoOutput> &)videoOutput)->Resume();
453 if (ret != 0) {
454 MEDIA_DEBUG_LOG("Failed to resume video output, ret: %{public}d", ret);
455 return 0;
456 }
457
458 if (recorder != nullptr) {
459 ret = recorder->Resume();
460 if (ret != 0) {
461 MEDIA_DEBUG_LOG("Failed to resume recorder, return: %{public}s",
462 OHOS::Media::MSErrorToString(static_cast<OHOS::Media::MediaServiceErrCode>(ret)).c_str());
463 }
464 }
465 MEDIA_DEBUG_LOG("Wait for 5 seconds before stop");
466 sleep(videoCaptureDuration);
467 MEDIA_DEBUG_LOG("Stop video recording");
468 ret = ((sptr<VideoOutput> &)videoOutput)->Stop();
469 if (ret != 0) {
470 MEDIA_DEBUG_LOG("Failed to stop video output, ret: %{public}d", ret);
471 return 0;
472 }
473
474 if (recorder != nullptr) {
475 ret = recorder->Stop(false);
476 if (ret != 0) {
477 MEDIA_DEBUG_LOG("Failed to stop recorder, return: %{public}s",
478 OHOS::Media::MSErrorToString(static_cast<OHOS::Media::MediaServiceErrCode>(ret)).c_str());
479 }
480
481 ret = recorder->Reset();
482 if (ret != 0) {
483 MEDIA_DEBUG_LOG("Failed to reset recorder, return: %{public}s",
484 OHOS::Media::MSErrorToString(static_cast<OHOS::Media::MediaServiceErrCode>(ret)).c_str());
485 }
486
487 ret = recorder->Release();
488 if (ret != 0) {
489 MEDIA_DEBUG_LOG("Failed to release recorder, return: %{public}s",
490 OHOS::Media::MSErrorToString(static_cast<OHOS::Media::MediaServiceErrCode>(ret)).c_str());
491 }
492 }
493
494 MEDIA_DEBUG_LOG("Closing the session");
495 ret = captureSession->Stop();
496 if (ret != 0) {
497 MEDIA_DEBUG_LOG("Failed to stop session, ret: %{public}d", ret);
498 return 0;
499 }
500
501 MEDIA_DEBUG_LOG("Releasing the session");
502 captureSession->Release();
503
504 // Close video file
505 TestUtils::SaveVideoFile(nullptr, 0, VideoSaveMode::CLOSE, g_videoFd);
506 cameraInput->Release();
507 camManagerObj->SetCallback(nullptr);
508 MEDIA_DEBUG_LOG("Camera new sample end.");
509 return 0;
510 }
511