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