diff --git a/README.en.md b/README.en.md index 3360f78c3dc29d8ea857075ccc4ad7072e90c8fe..91898886e6e784611e27a72fde44a59a0ec74038 100644 --- a/README.en.md +++ b/README.en.md @@ -23,7 +23,7 @@ This sample demonstrates video playback and recording implemented on AVCodec. ### Preview -| Home page | App usage example | +| Home page | Record page | |-------------------------------------------------------|-----------------------------------------------------| | ![AVCodec_Index.png](screenshots/device/Index.en.png) | ![AVCodecSample.gif](screenshots/device/record.png) | diff --git a/README.md b/README.md index 033697a20f78515ab6b9d4882a456f6cdee66900..14f620d01b0e18e31d4e4ce4bd7d6f75069ecdc8 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ ### 效果预览 -| 应用主界面 | 应用使用展示 | +| 应用主界面 | 录制页面 | |----------------------------------------------------|-----------------------------------------------------| | ![AVCodec_Index.png](screenshots/device/Index.png) | ![AVCodecSample.gif](screenshots/device/record.png) | diff --git a/entry/src/main/ets/entryability/EntryAbility.ets b/entry/src/main/ets/entryability/EntryAbility.ets index 61c02a3d4d43e2852381516046bb0581aee805e1..a91cf616f97e30db51ecd1751daaa99ffaf42550 100644 --- a/entry/src/main/ets/entryability/EntryAbility.ets +++ b/entry/src/main/ets/entryability/EntryAbility.ets @@ -44,15 +44,20 @@ export default class EntryAbility extends UIAbility { Logger.error('Entry', 'requestPre() data: ' + JSON.stringify(err)); } - windowStage.getMainWindowSync().setWindowKeepScreenOn(true); - windowStage.loadContent('pages/Index', (err) => { - if (err.code) { - hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); - return; - } - AppStorage.setOrCreate("context", windowStage.getMainWindowSync().getUIContext()); - hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); - }); + try { + windowStage.getMainWindowSync().setWindowKeepScreenOn(true); + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + AppStorage.setOrCreate("context", windowStage.getMainWindowSync().getUIContext()); + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); + }); + } catch (error) { + hilog.error(0x0000, 'testTag', `getMainWindowSync catch error, code: ${error.code}, message: ${error.message}`); + return; + } } onWindowStageDestroy(): void { diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index 33085dcd7f3d8ebbd85d67c9a076c9d8d12c62dd..a034db9b0aa670cef8d0a3eb3b800c7e8e155581 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -17,6 +17,7 @@ import { fileIo } from '@kit.CoreFileKit'; import { display } from '@kit.ArkUI'; import { camera } from '@kit.CameraKit'; import { photoAccessHelper } from '@kit.MediaLibraryKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; import player from 'libplayer.so'; import recorder from 'librecorder.so'; import Logger from '../common/utils/Logger'; @@ -39,61 +40,75 @@ struct Player { private heightPx = (this.display.width * Const.DEFAULT_HEIGHT / Const.DEFAULT_WIDTH) + Const.PX; selectFile() { - let photoPicker = new photoAccessHelper.PhotoViewPicker(); - photoPicker.select({ - MIMEType: photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE, - maxSelectNumber: 1 - }) - .then((photoSelectResult) => { - this.selectFilePath = photoSelectResult.photoUris[0]; - if (this.selectFilePath === null) { - this.getUIContext().getPromptAction().showToast({ - message: $r('app.string.alert'), - duration: Const.DURATION, - bottom: Const.BOTTOM - }); - } else { - this.play(); - Logger.info(TAG, 'documentViewPicker.select to file succeed and URI is:' + this.selectFilePath); - } - }); + try { + let photoPicker = new photoAccessHelper.PhotoViewPicker(); + photoPicker.select({ + MIMEType: photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE, + maxSelectNumber: 1 + }) + .then((photoSelectResult) => { + this.selectFilePath = photoSelectResult.photoUris[0]; + if (this.selectFilePath === null) { + this.getUIContext().getPromptAction().showToast({ + message: $r('app.string.alert'), + duration: Const.DURATION, + bottom: Const.BOTTOM + }); + } else { + this.play(); + Logger.info(TAG, 'documentViewPicker.select to file succeed and URI is:' + this.selectFilePath); + } + }); + } catch (error) { + hilog.error(0x0000, TAG, `selectFile catch error, code: ${error.code}, message: ${error.message}`); + return; + } } play() { - let inputFile = fileIo.openSync(this.selectFilePath, fileIo.OpenMode.READ_ONLY); - if (!inputFile) { - Logger.error(TAG, 'player inputFile is null'); - } - let inputFileState = fileIo.statSync(inputFile.fd); - if (inputFileState.size <= 0) { - Logger.error(TAG, 'player inputFile size is 0'); + try { + let inputFile = fileIo.openSync(this.selectFilePath, fileIo.OpenMode.READ_ONLY); + if (!inputFile) { + Logger.error(TAG, 'player inputFile is null'); + } + let inputFileState = fileIo.statSync(inputFile.fd); + if (inputFileState.size <= 0) { + Logger.error(TAG, 'player inputFile size is 0'); + } + this.buttonEnabled = false; + player.playNative(inputFile.fd, Const.DEFAULT_VALUE, inputFileState.size, () => { + Logger.info(TAG, 'player JSCallback'); + this.buttonEnabled = true; + fileIo.close(inputFile); + }) + } catch (error) { + hilog.error(0x0000, TAG, `play catch error, code: ${error.code}, message: ${error.message}`); + return; } - this.buttonEnabled = false; - player.playNative(inputFile.fd, Const.DEFAULT_VALUE, inputFileState.size, () => { - Logger.info(TAG, 'player JSCallback'); - this.buttonEnabled = true; - fileIo.close(inputFile); - }) } async checkIsProfileSupport(): Promise { - let cameraManager: camera.CameraManager = camera.getCameraManager(this.getUIContext().getHostContext()); - if (!cameraManager) { - Logger.error(TAG, 'camera.getCameraManager error!'); - } + try { + let cameraManager: camera.CameraManager = camera.getCameraManager(this.getUIContext().getHostContext()); + if (!cameraManager) { + Logger.error(TAG, 'camera.getCameraManager error!'); + } - let videoProfile: undefined | camera.VideoProfile = videoProfileCheck(cameraManager, this.cameraData); - if (!videoProfile) { - Logger.error(TAG, 'videoProfile is not found'); - this.getUIContext().getPromptAction().showToast({ - message: $r('app.string.alert_setting'), - duration: Const.DURATION, - bottom: Const.BOTTOM, - backgroundColor: Color.White, - backgroundBlurStyle: BlurStyle.NONE - }) - this.cameraData = new CameraDataModel(); - return; + let videoProfile: undefined | camera.VideoProfile = videoProfileCheck(cameraManager, this.cameraData); + if (!videoProfile) { + Logger.error(TAG, 'videoProfile is not found'); + this.getUIContext().getPromptAction().showToast({ + message: $r('app.string.alert_setting'), + duration: Const.DURATION, + bottom: Const.BOTTOM, + backgroundColor: Color.White, + backgroundBlurStyle: BlurStyle.NONE + }) + this.cameraData = new CameraDataModel(); + return; + } + } catch (error) { + hilog.error(0x0000, TAG, `checkIsProfileSupport catch error, code: ${error.code}, message: ${error.message}`); } } diff --git a/entry/src/main/ets/pages/Recorder.ets b/entry/src/main/ets/pages/Recorder.ets index b6da2d237e172485dc65f0d337f0c367a526b77b..edfe4cd845741a888f2bb702b71e947ac26c4dc3 100644 --- a/entry/src/main/ets/pages/Recorder.ets +++ b/entry/src/main/ets/pages/Recorder.ets @@ -18,6 +18,7 @@ import { fileIo } from '@kit.CoreFileKit'; import { display } from '@kit.ArkUI'; import { BusinessError } from '@kit.BasicServicesKit'; import { colorSpaceManager } from '@kit.ArkGraphics2D'; +import { hilog } from '@kit.PerformanceAnalysisKit'; import recorder from 'librecorder.so'; import Logger from '../common/utils/Logger'; import { dateTime } from '../common/utils/DateTimeUtils'; @@ -45,19 +46,25 @@ async function releaseCamera(): Promise { Logger.info(TAG, 'Callback invoked to indicate the encoder video output stop success.'); }); } - // Stop the Session. - videoSession.stop(); - // Close file fd. - fileIo.close(params.outputfd); - // Close camera input stream. - cameraInput.close(); - // Release preview output stream. - XComponentPreviewOutput.release(); - // Release the video output stream. - encoderVideoOutput.release(); - Logger.info(TAG, 'encoderVideoOutput release'); - // Release session. - videoSession.release(); + + try { + // Stop the Session. + videoSession.stop(); + // Close file fd. + fileIo.close(params.outputfd); + // Close camera input stream. + cameraInput.close(); + // Release preview output stream. + XComponentPreviewOutput.release(); + // Release the video output stream. + encoderVideoOutput.release(); + Logger.info(TAG, 'encoderVideoOutput release'); + // Release session. + videoSession.release(); + } catch (error) { + hilog.error(0x0000, TAG, `releaseCamera catch error, code: ${error.code}, message: ${error.message}`); + return; + } } // [Start set_video_color] @@ -79,10 +86,14 @@ function setVideoStabilizationMode(session: camera.VideoSession): boolean { let isSupported: boolean = isVideoStabilizationModeSupported(session, mode); if (isSupported) { Logger.info(TAG, `setVideoStabilizationMode: ${mode}`); - // Setting video anti-shake - session.setVideoStabilizationMode(mode); - let activeVideoStabilizationMode = session.getActiveVideoStabilizationMode(); - Logger.info(TAG, `activeVideoStabilizationMode: ${activeVideoStabilizationMode}`); + try { + // Setting video anti-shake + session.setVideoStabilizationMode(mode); + let activeVideoStabilizationMode = session.getActiveVideoStabilizationMode(); + Logger.info(TAG, `activeVideoStabilizationMode: ${activeVideoStabilizationMode}`); + } catch (error) { + hilog.error(0x0000, TAG, `setVideoStabilizationMode catch error, code: ${error.code}, message: ${error.message}`); + } } else { Logger.info(TAG, `videoStabilizationMode: ${mode} is not support`); } @@ -102,16 +113,21 @@ function getSupportedColorSpaces(session: camera.VideoSession): Array = getSupportedColorSpaces(session); - let isSupportedColorSpaces = colorSpaces.indexOf(colorSpace) >= 0; - if (isSupportedColorSpaces) { - Logger.info(TAG, `setColorSpace: ${colorSpace}`); - session.setColorSpace(colorSpace); - let activeColorSpace:colorSpaceManager.ColorSpace = session.getActiveColorSpace(); - Logger.info(TAG, `activeColorSpace: ${activeColorSpace}`); - } else { - Logger.info(TAG, `colorSpace: ${colorSpace} is not support`); + try { + let colorSpace: colorSpaceManager.ColorSpace = + isHdr ? colorSpaceManager.ColorSpace.BT2020_HLG_LIMIT : colorSpaceManager.ColorSpace.BT709_LIMIT; + let colorSpaces: Array = getSupportedColorSpaces(session); + let isSupportedColorSpaces = colorSpaces.indexOf(colorSpace) >= 0; + if (isSupportedColorSpaces) { + Logger.info(TAG, `setColorSpace: ${colorSpace}`); + session.setColorSpace(colorSpace); + let activeColorSpace: colorSpaceManager.ColorSpace = session.getActiveColorSpace(); + Logger.info(TAG, `activeColorSpace: ${activeColorSpace}`); + } else { + Logger.info(TAG, `colorSpace: ${colorSpace} is not support`); + } + } catch (error) { + hilog.error(0x0000, TAG, `setColorSpace catch error, code: ${error.code}, message: ${error.message}`); } } // [End set_video_color] @@ -169,176 +185,181 @@ struct Recorder { } async createRecorder(): Promise { - releaseCamera(); - // Create the CameraManager object. - let cameraManager = camera.getCameraManager(this.getUIContext().getHostContext()); - if (!cameraManager) { - Logger.error(TAG, 'camera.getCameraManager error'); - return; - } - - // Get supported camera devices. - let cameraDevices: Array = cameraManager.getSupportedCameras(); - if (cameraDevices !== undefined && cameraDevices.length <= 0) { - Logger.error(TAG, 'cameraManager.getSupportedCameras error!'); - return; - } - - // Get supported modes. - let sceneModes: Array = cameraManager.getSupportedSceneModes(cameraDevices[0]); - let isSupportVideoMode: boolean = sceneModes.indexOf(camera.SceneMode.NORMAL_VIDEO) >= 0; - if (!isSupportVideoMode) { - Logger.error('video mode not support'); - return; - } + try { + releaseCamera(); + // Create the CameraManager object. + let cameraManager = camera.getCameraManager(this.getUIContext().getHostContext()); + if (!cameraManager) { + Logger.error(TAG, 'camera.getCameraManager error'); + return; + } - // [Start create_video_output3] - let videoProfile: undefined | camera.VideoProfile = videoProfileCheck(cameraManager, params); - if (!videoProfile) { - Logger.error(TAG, 'videoProfile is not found!'); - return; - } + // Get supported camera devices. + let cameraDevices: Array = cameraManager.getSupportedCameras(); + if (cameraDevices !== undefined && cameraDevices.length <= 0) { + Logger.error(TAG, 'cameraManager.getSupportedCameras error!'); + return; + } - // [StartExclude create_video_output3] - //The preview stream of XComponent. - // [Start camera_conversation] - let XComponentPreviewProfile: camera.Profile | undefined = previewProfileCameraCheck(cameraManager, params); - if (XComponentPreviewProfile === undefined) { - Logger.error(TAG, 'XComponentPreviewProfile is not found'); - return; - } - // [StartExclude camera_conversation] - // [EndExclude create_video_output3] + // Get supported modes. + let sceneModes: Array = cameraManager.getSupportedSceneModes(cameraDevices[0]); + let isSupportVideoMode: boolean = sceneModes.indexOf(camera.SceneMode.NORMAL_VIDEO) >= 0; + if (!isSupportVideoMode) { + Logger.error('video mode not support'); + return; + } - // Create the encoder output object - encoderVideoOutput = cameraManager.createVideoOutput(videoProfile, params.surfaceId); - if (encoderVideoOutput === undefined) { - Logger.error(TAG, 'encoderVideoOutput is undefined'); - return; - } - Logger.info(TAG, 'encoderVideoOutput success'); - // [End create_video_output3] + // [Start create_video_output3] + let videoProfile: undefined | camera.VideoProfile = videoProfileCheck(cameraManager, params); + if (!videoProfile) { + Logger.error(TAG, 'videoProfile is not found!'); + return; + } - // Create a preview stream output object - XComponentPreviewOutput = cameraManager.createPreviewOutput(XComponentPreviewProfile, this.XComponentSurfaceId); - if (XComponentPreviewOutput === undefined) { - Logger.error(TAG, 'XComponentPreviewOutput is undefined'); - return; - } + // [StartExclude create_video_output3] + //The preview stream of XComponent. + // [Start camera_conversation] + let XComponentPreviewProfile: camera.Profile | undefined = previewProfileCameraCheck(cameraManager, params); + if (XComponentPreviewProfile === undefined) { + Logger.error(TAG, 'XComponentPreviewProfile is not found'); + return; + } + // [StartExclude camera_conversation] + // [EndExclude create_video_output3] - // Create the cameraInput object. - try { - cameraInput = cameraManager.createCameraInput(cameraDevices[0]); - } catch (error) { - let err = error as BusinessError; - Logger.error(TAG, `Failed to createCameraInput. error: ${JSON.stringify(err)}`); - } - if (cameraInput === undefined) { - Logger.error(TAG, 'cameraInput is undefined'); - return; - } + // Create the encoder output object + encoderVideoOutput = cameraManager.createVideoOutput(videoProfile, params.surfaceId); + if (encoderVideoOutput === undefined) { + Logger.error(TAG, 'encoderVideoOutput is undefined'); + return; + } + Logger.info(TAG, 'encoderVideoOutput success'); + // [End create_video_output3] - // Turn on the camera. - try { - await cameraInput.open(); - } catch (error) { - let err = error as BusinessError; - Logger.error(TAG, `Failed to open cameraInput. error: ${JSON.stringify(err)}`); - } - // [EndExclude camera_conversation] + // Create a preview stream output object + XComponentPreviewOutput = cameraManager.createPreviewOutput(XComponentPreviewProfile, this.XComponentSurfaceId); + if (XComponentPreviewOutput === undefined) { + Logger.error(TAG, 'XComponentPreviewOutput is undefined'); + return; + } - // Create a session flow - try { - videoSession = cameraManager.createSession(camera.SceneMode.NORMAL_VIDEO) as camera.VideoSession; - } catch (error) { - let err = error as BusinessError; - Logger.error(TAG, `Failed to create the session instance. error: ${JSON.stringify(err)}`); - } - // [StartExclude camera_conversation] - if (videoSession === undefined) { - Logger.error(TAG, 'videoSession is undefined'); - return; - } - // [EndExclude camera_conversation] + // Create the cameraInput object. + try { + cameraInput = cameraManager.createCameraInput(cameraDevices[0]); + } catch (error) { + let err = error as BusinessError; + Logger.error(TAG, `Failed to createCameraInput. error: ${JSON.stringify(err)}`); + } + if (cameraInput === undefined) { + Logger.error(TAG, 'cameraInput is undefined'); + return; + } - // Start Configuring the session. - try { - videoSession.beginConfig(); - } catch (error) { - // [StartExclude camera_conversation] - let err = error as BusinessError; - Logger.error(TAG, `Failed to beginConfig. error: ${JSON.stringify(err)}`); + // Turn on the camera. + try { + await cameraInput.open(); + } catch (error) { + let err = error as BusinessError; + Logger.error(TAG, `Failed to open cameraInput. error: ${JSON.stringify(err)}`); + } // [EndExclude camera_conversation] - } - // [StartExclude camera_conversation] - // Add CameraInput to the session. - try { - videoSession.addInput(cameraInput); - } catch (error) { - // DocsDot - let err = error as BusinessError; - Logger.error(TAG, `Failed to add cameraInput. error: ${JSON.stringify(err)}`); - // DocsDot - } - // [EndExclude camera_conversation] - // Add the XComponent preview stream to the session. - try { - videoSession.addOutput(XComponentPreviewOutput); - } catch (error) { + // Create a session flow + try { + videoSession = cameraManager.createSession(camera.SceneMode.NORMAL_VIDEO) as camera.VideoSession; + } catch (error) { + let err = error as BusinessError; + Logger.error(TAG, `Failed to create the session instance. error: ${JSON.stringify(err)}`); + } // [StartExclude camera_conversation] - let err = error as BusinessError; - Logger.error(TAG, `Failed to add XcomponentPreviewOutput. error: ${JSON.stringify(err)}`); + if (videoSession === undefined) { + Logger.error(TAG, 'videoSession is undefined'); + return; + } // [EndExclude camera_conversation] - } - // Add the encoder video stream to the session. - try { - videoSession.addOutput(encoderVideoOutput); - } catch (error) { + // Start Configuring the session. + try { + videoSession.beginConfig(); + } catch (error) { + // [StartExclude camera_conversation] + let err = error as BusinessError; + Logger.error(TAG, `Failed to beginConfig. error: ${JSON.stringify(err)}`); + // [EndExclude camera_conversation] + } // [StartExclude camera_conversation] - let err = error as BusinessError; - Logger.error(TAG, `Failed to add encoderVideoOutput. error: ${JSON.stringify(err)}`); - // [EndExclude camera_conversation] - } - // Submit configuration information. - try { - await videoSession.commitConfig(); - } catch (error) { - // [StartExclude camera_conversation] - let err = error as BusinessError; - Logger.error(TAG, `videoSession commitConfig error: ${JSON.stringify(err)}`); + // Add CameraInput to the session. + try { + videoSession.addInput(cameraInput); + } catch (error) { + // DocsDot + let err = error as BusinessError; + Logger.error(TAG, `Failed to add cameraInput. error: ${JSON.stringify(err)}`); + // DocsDot + } // [EndExclude camera_conversation] - } + // Add the XComponent preview stream to the session. + try { + videoSession.addOutput(XComponentPreviewOutput); + } catch (error) { + // [StartExclude camera_conversation] + let err = error as BusinessError; + Logger.error(TAG, `Failed to add XcomponentPreviewOutput. error: ${JSON.stringify(err)}`); + // [EndExclude camera_conversation] + } - // Set video stabilization. - if (setVideoStabilizationMode(videoSession)) { - // Set color space. - setColorSpaceBeforeCommitConfig(videoSession, params.isHDRVivid); - } + // Add the encoder video stream to the session. + try { + videoSession.addOutput(encoderVideoOutput); + } catch (error) { + // [StartExclude camera_conversation] + let err = error as BusinessError; + Logger.error(TAG, `Failed to add encoderVideoOutput. error: ${JSON.stringify(err)}`); + // [EndExclude camera_conversation] + } - // Session start. - try { - await videoSession.start(); - } catch (error) { - // [StartExclude camera_conversation] - let err = error as BusinessError; - Logger.error(TAG, `videoSession start error: ${JSON.stringify(err)}`); - // [EndExclude camera_conversation] - } + // Submit configuration information. + try { + await videoSession.commitConfig(); + } catch (error) { + // [StartExclude camera_conversation] + let err = error as BusinessError; + Logger.error(TAG, `videoSession commitConfig error: ${JSON.stringify(err)}`); + // [EndExclude camera_conversation] + } - // Start the video output stream - encoderVideoOutput.start((err: BusinessError) => { - // [StartExclude camera_conversation] - if (err) { - Logger.error(TAG, `Failed to start the encoder video output. error: ${JSON.stringify(err)}`); - return; + // Set video stabilization. + if (setVideoStabilizationMode(videoSession)) { + // Set color space. + setColorSpaceBeforeCommitConfig(videoSession, params.isHDRVivid); } - Logger.info(TAG, 'Callback invoked to indicate the encoder video output start success.'); - // [EndExclude camera_conversation] - }); - // [End camera_conversation] + + // Session start. + try { + await videoSession.start(); + } catch (error) { + // [StartExclude camera_conversation] + let err = error as BusinessError; + Logger.error(TAG, `videoSession start error: ${JSON.stringify(err)}`); + // [EndExclude camera_conversation] + } + + // Start the video output stream + encoderVideoOutput.start((err: BusinessError) => { + // [StartExclude camera_conversation] + if (err) { + Logger.error(TAG, `Failed to start the encoder video output. error: ${JSON.stringify(err)}`); + return; + } + Logger.info(TAG, 'Callback invoked to indicate the encoder video output start success.'); + // [EndExclude camera_conversation] + }); + // [End camera_conversation] + } catch (error) { + hilog.error(0x0000, TAG, `createRecorder catch error, code: ${error.code}, message: ${error.message}`); + return; + } } build() {