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<IConsumerSurface> previewSurface = IConsumerSurface::Create();
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<IBufferProducer> bp = previewSurface->GetProducer();
346 sptr<Surface> pSurface = Surface::CreateSurfaceAsProducer(bp);
347 sptr<CaptureOutput> previewOutput = camManagerObj->CreatePreviewOutput(previewprofile, pSurface);
348 if (previewOutput == nullptr) {
349 MEDIA_DEBUG_LOG("Failed to create preview output");
350 return 0;
351 }
352
353 MEDIA_DEBUG_LOG("Setting preview callback");
354 ((sptr<PreviewOutput> &)previewOutput)->SetCallback(std::make_shared<TestPreviewOutputCallback>(testName));
355 ret = captureSession->AddOutput(previewOutput);
356 if (ret != 0) {
357 MEDIA_DEBUG_LOG("Failed to Add output to session, ret: %{public}d", ret);
358 return 0;
359 }
360
361 sptr<Surface> videoSurface = nullptr;
362 std::shared_ptr<Recorder> recorder = nullptr;
363 if (isRecorder) {
364 int32_t videoSourceId = 0;
365 if (!CreateAndConfigureRecorder(recorder, videoSourceId, videoWidth, videoHeight)) {
366 MEDIA_DEBUG_LOG("Failed to create and configure recorder");
367 return 0;
368 }
369
370 if (recorder->Prepare()) {
371 MEDIA_DEBUG_LOG("Failed to prepare recorder");
372 return 0;
373 }
374
375 videoSurface = recorder->GetSurface(videoSourceId);
376 if (videoSurface == nullptr) {
377 MEDIA_DEBUG_LOG("Failed to get surface from recorder");
378 return 0;
379 }
380 videoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(videoFormat));
381 } else {
382 sptr<IConsumerSurface> cSurface = IConsumerSurface::Create();
383 sptr<SurfaceListener> videoListener = new SurfaceListener("Video", SurfaceType::VIDEO, g_videoFd, cSurface);
384 cSurface->RegisterConsumerListener((sptr<IBufferConsumerListener> &)videoListener);
385 sptr<IBufferProducer> videoProducer = cSurface->GetProducer();
386 videoSurface = Surface::CreateSurfaceAsProducer(videoProducer);
387 }
388 videosize.width = videoWidth;
389 videosize.height = videoHeight;
390 VideoProfile videoprofile = VideoProfile(static_cast<CameraFormat>(videoFormat), videosize, videoframerates);
391
392 sptr<CaptureOutput> videoOutput = camManagerObj->CreateVideoOutput(videoprofile, videoSurface);
393 if (videoOutput == nullptr) {
394 MEDIA_DEBUG_LOG("Failed to create video output");
395 return 0;
396 }
397
398 MEDIA_DEBUG_LOG("Setting video callback");
399 ((sptr<VideoOutput> &)videoOutput)->SetCallback(std::make_shared<TestVideoOutputCallback>(testName));
400 ret = captureSession->AddOutput(videoOutput);
401 if (ret != 0) {
402 MEDIA_DEBUG_LOG("Failed to Add output to session, ret: %{public}d", ret);
403 return 0;
404 }
405
406 ret = captureSession->CommitConfig();
407 if (ret != 0) {
408 MEDIA_DEBUG_LOG("Failed to commit session config, ret: %{public}d", ret);
409 return 0;
410 }
411
412 ret = captureSession->Start();
413 if (ret != 0) {
414 MEDIA_DEBUG_LOG("Failed to start session, ret: %{public}d", ret);
415 return 0;
416 }
417 sleep(previewVideoGap);
418
419 MEDIA_DEBUG_LOG("Preview started");
420 sleep(previewVideoGap);
421 MEDIA_DEBUG_LOG("Start video recording");
422
423 ret = ((sptr<VideoOutput> &)videoOutput)->Start();
424 if (ret != 0) {
425 MEDIA_DEBUG_LOG("Failed to start video output, ret: %{public}d", ret);
426 return 0;
427 }
428
429 if (recorder != nullptr) {
430 ret = recorder->Start();
431 if (ret != 0) {
432 MEDIA_DEBUG_LOG("Failed to start recorder, return: %{public}s",
433 OHOS::Media::MSErrorToString(static_cast<OHOS::Media::MediaServiceErrCode>(ret)).c_str());
434 return 0;
435 }
436 }
437
438 MEDIA_DEBUG_LOG("Wait for 5 seconds after start");
439 sleep(videoCaptureDuration);
440 MEDIA_DEBUG_LOG("Pause video recording for 2 sec");
441 ret = ((sptr<VideoOutput> &)videoOutput)->Pause();
442 if (ret != 0) {
443 MEDIA_DEBUG_LOG("Failed to pause video output, ret: %{public}d", ret);
444 return 0;
445 }
446
447 if (recorder != nullptr) {
448 ret = recorder->Pause();
449 if (ret != 0) {
450 MEDIA_DEBUG_LOG("Failed to pause recorder, return: %{public}s",
451 OHOS::Media::MSErrorToString(static_cast<OHOS::Media::MediaServiceErrCode>(ret)).c_str());
452 }
453 }
454 sleep(videoPauseDuration);
455 MEDIA_DEBUG_LOG("Resume video recording");
456 ret = ((sptr<VideoOutput> &)videoOutput)->Resume();
457 if (ret != 0) {
458 MEDIA_DEBUG_LOG("Failed to resume video output, ret: %{public}d", ret);
459 return 0;
460 }
461
462 if (recorder != nullptr) {
463 ret = recorder->Resume();
464 if (ret != 0) {
465 MEDIA_DEBUG_LOG("Failed to resume recorder, return: %{public}s",
466 OHOS::Media::MSErrorToString(static_cast<OHOS::Media::MediaServiceErrCode>(ret)).c_str());
467 }
468 }
469 MEDIA_DEBUG_LOG("Wait for 5 seconds before stop");
470 sleep(videoCaptureDuration);
471 MEDIA_DEBUG_LOG("Stop video recording");
472 ret = ((sptr<VideoOutput> &)videoOutput)->Stop();
473 if (ret != 0) {
474 MEDIA_DEBUG_LOG("Failed to stop video output, ret: %{public}d", ret);
475 return 0;
476 }
477
478 if (recorder != nullptr) {
479 ret = recorder->Stop(false);
480 if (ret != 0) {
481 MEDIA_DEBUG_LOG("Failed to stop recorder, return: %{public}s",
482 OHOS::Media::MSErrorToString(static_cast<OHOS::Media::MediaServiceErrCode>(ret)).c_str());
483 }
484
485 ret = recorder->Reset();
486 if (ret != 0) {
487 MEDIA_DEBUG_LOG("Failed to reset recorder, return: %{public}s",
488 OHOS::Media::MSErrorToString(static_cast<OHOS::Media::MediaServiceErrCode>(ret)).c_str());
489 }
490
491 ret = recorder->Release();
492 if (ret != 0) {
493 MEDIA_DEBUG_LOG("Failed to release recorder, return: %{public}s",
494 OHOS::Media::MSErrorToString(static_cast<OHOS::Media::MediaServiceErrCode>(ret)).c_str());
495 }
496 }
497
498 MEDIA_DEBUG_LOG("Closing the session");
499 ret = captureSession->Stop();
500 if (ret != 0) {
501 MEDIA_DEBUG_LOG("Failed to stop session, ret: %{public}d", ret);
502 return 0;
503 }
504
505 MEDIA_DEBUG_LOG("Releasing the session");
506 captureSession->Release();
507
508 // Close video file
509 TestUtils::SaveVideoFile(nullptr, 0, VideoSaveMode::CLOSE, g_videoFd);
510 cameraInput->Release();
511 camManagerObj->SetCallback(nullptr);
512 MEDIA_DEBUG_LOG("Camera new sample end.");
513 return 0;
514 }
515