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