diff --git a/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/camera_manager.cpp b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/camera_manager.cpp index 852241e054e36ac20627869110346c7c85c952bd..0394b18d69c8352119d65c30570221cdb8bd3a50 100644 --- a/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/camera_manager.cpp +++ b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/camera_manager.cpp @@ -41,6 +41,7 @@ NDKCamera::NDKCamera(char* str) GetSupportedCameras(); GetSupportedOutputCapability(); CreatePreviewOutput(); + CreatePhotoOutput(); CreateCameraInput(); CameraInputOpen(); SessionFlowFn(); @@ -142,6 +143,50 @@ Camera_ErrorCode NDKCamera::setZoomRatioFn(uint32_t zoomRatio) return ret; } +Camera_ErrorCode NDKCamera::SessionBegin() +{ + Camera_ErrorCode ret = OH_CaptureSession_BeginConfig(captureSession_); + if (ret == CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_BeginConfig success."); + } else { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_BeginConfig failed. %d ", ret); + } + return ret; +} + +Camera_ErrorCode NDKCamera::SessionCommitConfig() +{ + Camera_ErrorCode ret = OH_CaptureSession_CommitConfig(captureSession_); + if (ret == CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_CommitConfig success."); + } else { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_CommitConfig failed. %d ", ret); + } + return ret; +} + +Camera_ErrorCode NDKCamera::SessionStart() +{ + Camera_ErrorCode ret = OH_CaptureSession_Start(captureSession_); + if (ret == CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Start success."); + } else { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Start failed. %d ", ret); + } + return ret; +} + +Camera_ErrorCode NDKCamera::SessionStop() +{ + Camera_ErrorCode ret = OH_CaptureSession_Stop(captureSession_); + if (ret == CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Stop success."); + } else { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Stop failed. %d ", ret); + } + return ret; +} + Camera_ErrorCode NDKCamera::SessionFlowFn() { OH_LOG_ERROR(LOG_APP, "Start SessionFlowFn IN."); @@ -261,6 +306,33 @@ Camera_ErrorCode NDKCamera::CreatePhotoOutput(void) return ret_; } +Camera_ErrorCode NDKCamera::CreateVideoOutput(char* videoId) +{ + videoProfile_ = cameraOutputCapability_->videoProfiles[0]; + if (videoProfile_ == nullptr) { + OH_LOG_ERROR(LOG_APP, "Get videoProfiles failed."); + return CAMERA_INVALID_ARGUMENT; + } + ret_ = OH_CameraManager_CreateVideoOutput(cameraManager_, videoProfile_, videoId, &videoOutput_); + if (videoId == nullptr || videoOutput_ == nullptr || ret_ != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "CreateVideoOutput failed."); + return CAMERA_INVALID_ARGUMENT; + } + + return ret_; +} + +Camera_ErrorCode NDKCamera::AddVideoOutput() +{ + Camera_ErrorCode ret = OH_CaptureSession_AddVideoOutput(captureSession_, videoOutput_); + if (ret == CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_AddVideoOutput success."); + } else { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_AddVideoOutput failed. %d ", ret); + } + return ret; +} + Camera_ErrorCode NDKCamera::CreateMetadataOutput(void) { metaDataObjectType_ = cameraOutputCapability_->supportedMetadataObjectTypes[2]; // 2:camera metedata types @@ -314,4 +386,38 @@ Camera_ErrorCode NDKCamera::PhotoOutputRelease(void) return CAMERA_INVALID_ARGUMENT; } return ret_; +} + +Camera_ErrorCode NDKCamera::startVideo(char* videoId) +{ + OH_LOG_ERROR(LOG_APP, "startVideo begin."); + Camera_ErrorCode ret = SessionStop(); + if (ret == CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "SessionStop success."); + } else { + OH_LOG_ERROR(LOG_APP, "SessionStop failed. %d ", ret); + } + ret = SessionBegin(); + if (ret == CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "SessionBegin success."); + } else { + OH_LOG_ERROR(LOG_APP, "SessionBegin failed. %d ", ret); + } + CreateVideoOutput(videoId); + AddVideoOutput(); + SessionCommitConfig(); + SessionStart(); + return ret; +} + +Camera_ErrorCode NDKCamera::VideoOutputStart() +{ + OH_LOG_ERROR(LOG_APP, "VideoOutputStart begin."); + Camera_ErrorCode ret = OH_VideoOutput_Start(videoOutput_); + if (ret == CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_VideoOutput_Start success."); + } else { + OH_LOG_ERROR(LOG_APP, "OH_VideoOutput_Start failed. %d ", ret); + } + return ret; } \ No newline at end of file diff --git a/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/camera_manager.h b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/camera_manager.h index 46a757c7ed1ddf4b38ea4dbdb00a92a1b054423f..eeb53d8fa536585453eab8fc3d8347349f4d6af5 100644 --- a/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/camera_manager.h +++ b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/camera_manager.h @@ -34,6 +34,7 @@ #include "multimedia/camera_framework/capture_session.h" #include "multimedia/camera_framework/photo_output.h" #include "multimedia/camera_framework/preview_output.h" +#include "multimedia/camera_framework/video_output.h" #include "napi/native_api.h" #include "multimedia/camera_framework/camera_manager.h" @@ -68,6 +69,7 @@ public: Camera_ErrorCode GetSupportedOutputCapability(void); Camera_ErrorCode CreatePreviewOutput(void); Camera_ErrorCode CreatePhotoOutput(void); + Camera_ErrorCode CreateVideoOutput(char *videoId); Camera_ErrorCode CreateMetadataOutput(void); Camera_ErrorCode IsCameraMuted(void); Camera_ErrorCode PreviewOutputStop(void); @@ -76,6 +78,13 @@ public: Camera_ErrorCode HasFlashFn(uint32_t mode); Camera_ErrorCode setZoomRatioFn(uint32_t zoomRatio); Camera_ErrorCode SessionFlowFn(); + Camera_ErrorCode SessionBegin(); + Camera_ErrorCode SessionCommitConfig(); + Camera_ErrorCode SessionStart(); + Camera_ErrorCode SessionStop(); + Camera_ErrorCode startVideo(char *videoId); + Camera_ErrorCode AddVideoOutput(); + Camera_ErrorCode VideoOutputStart(); private: explicit NDKCamera(char *str); @@ -88,8 +97,10 @@ private: uint32_t size_; Camera_OutputCapability* cameraOutputCapability_; const Camera_Profile* profile_; + const Camera_VideoProfile* videoProfile_; Camera_PreviewOutput* previewOutput_; Camera_PhotoOutput* photoOutput_; + Camera_VideoOutput* videoOutput_; const Camera_MetadataObjectType* metaDataObjectType_; Camera_MetadataOutput* metadataOutput_; Camera_Input* cameraInput_; diff --git a/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/main.cpp b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/main.cpp index ff3a5da1d5fd0f9b955971bfa4b0130895110152..fc3825bf28037a0f9b74e037ad5c1e5439d9f2f4 100644 --- a/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/main.cpp +++ b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/main.cpp @@ -19,12 +19,14 @@ #include "camera_manager.h" #include "hilog/log.h" +static NDKCamera* ndkCamera_ = nullptr; + static napi_value SetZoomRatio(napi_env env, napi_callback_info info) { size_t requireArgc = 2; size_t argc = 2; napi_value args[2] = {nullptr}; - napi_value resutl; + napi_value result; napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); @@ -36,10 +38,7 @@ static napi_value SetZoomRatio(napi_env env, napi_callback_info info) OH_LOG_ERROR(LOG_APP, "zoomRatio : %d", zoomRatio); - NDKCamera *camera_ = NDKCamera::GetInstance(); - camera_ ->setZoomRatioFn(zoomRatio); - - return resutl; + return result; } static napi_value InitCamera(napi_env env, napi_callback_info info) @@ -48,7 +47,7 @@ static napi_value InitCamera(napi_env env, napi_callback_info info) size_t requireArgc = 2; size_t argc = 2; napi_value args[2] = {nullptr}; - napi_value resutl; + napi_value result; size_t typeLen = 0; char* surfaceId = nullptr; @@ -61,17 +60,61 @@ static napi_value InitCamera(napi_env env, napi_callback_info info) int32_t cameraDeviceIndex; napi_get_value_int32(env, args[1], &cameraDeviceIndex); - NDKCamera* ndkCamera = NDKCamera::GetInstance(surfaceId); + ndkCamera_ = NDKCamera::GetInstance(surfaceId); OH_LOG_ERROR(LOG_APP, "InitCamera End"); - return resutl; + return result; } +static napi_value StartPhotoOrVideo(napi_env env, napi_callback_info info) +{ + OH_LOG_INFO(LOG_APP, "StartPhotoOrVideo Start"); + size_t requireArgc = 2; + size_t argc = 2; + napi_value args[2] = {nullptr}; + napi_value result; + size_t typeLen = 0; + size_t videoIdLen = 0; + char *modeFlag = nullptr; + char *videoId = nullptr; + + napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); + + napi_get_value_string_utf8(env, args[0], nullptr, 0, &typeLen); + modeFlag = new char[typeLen + 1]; + napi_get_value_string_utf8(env, args[0], modeFlag, typeLen + 1, &typeLen); + + napi_get_value_string_utf8(env, args[1], nullptr, 0, &videoIdLen); + videoId = new char[videoIdLen + 1]; + napi_get_value_string_utf8(env, args[1], videoId, videoIdLen + 1, &videoIdLen); + + if (!strcmp(modeFlag, "photo")) { + // take photo func + } else if (!strcmp(modeFlag, "video")) { + ndkCamera_->startVideo(videoId); + OH_LOG_ERROR(LOG_APP, "StartPhotoOrVideo000 %{public}s", videoId); + } + + return result; +} + +static napi_value VideoOutputStart(napi_env env, napi_callback_info info) +{ + OH_LOG_INFO(LOG_APP, "VideoOutputStart Start"); + size_t requireArgc = 0; + size_t argc = 0; + napi_value result; + ndkCamera_->VideoOutputStart(); + + return result; +} EXTERN_C_START static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor desc[] = { { "initCamera", nullptr, InitCamera, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "startPhotoOrVideo", nullptr, StartPhotoOrVideo, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "videoOutputStart", nullptr, VideoOutputStart, nullptr, nullptr, nullptr, napi_default, nullptr }, { "setZoomRatio", nullptr, SetZoomRatio, nullptr, nullptr, nullptr, napi_default, nullptr } }; napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); diff --git a/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/types/libentry/index.d.ts b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/types/libentry/index.d.ts index 312c91f911a764eb3b4a0ede5d7deb5d00ee7a3d..1e804bf3ea50e05487fc8bc5ecf0a6765e9fb1c3 100644 --- a/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/types/libentry/index.d.ts +++ b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/cpp/types/libentry/index.d.ts @@ -1,3 +1,5 @@ export const add: (a: number, b: number) => number; export const initCamera:(surfaceId: string) => number; +export const startPhotoOrVideo:(modeFlag: string, videoId: string) => number; +export const videoOutputStart: () => number; export const setZoomRatio: (a: number) => number; \ No newline at end of file diff --git a/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/ets/model/DateTimeUtil.ts b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/ets/model/DateTimeUtil.ts new file mode 100644 index 0000000000000000000000000000000000000000..b43e2737baea11d2d8e026be1978113cb8f48b63 --- /dev/null +++ b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/ets/model/DateTimeUtil.ts @@ -0,0 +1,57 @@ +/** + * @file 日期工具 + */ +export default class DateTimeUtil { + + /** + * 时分秒 + */ + getTime() { + const DATETIME = new Date() + return this.concatTime(DATETIME.getHours(), DATETIME.getMinutes(), DATETIME.getSeconds()) + } + + /** + * 年月日 + */ + getDate() { + const DATETIME = new Date() + return this.concatDate(DATETIME.getFullYear(), DATETIME.getMonth() + 1, DATETIME.getDate()) + } + + /** + * 日期不足两位补充0 + * @param value-数据值 + */ + fill(value: number) { + return (value > 9 ? '' : '0') + value + } + /** + * 录制时间定时器 + * @param millisecond-数据值 + */ + getVideoTime(millisecond: number): string { + let minute = Math.floor(millisecond / 60000) + let second = Math.floor((millisecond - minute * 60000) / 1000) + return `${this.fill(minute)} : ${this.fill(second)}` + } + /** + * 年月日格式修饰 + * @param year + * @param month + * @param date + */ + concatDate(year: number, month: number, date: number) { + return `${year}${this.fill(month)}${this.fill(date)}` + } + + /** + * 时分秒格式修饰 + * @param hours + * @param minutes + * @param seconds + */ + concatTime(hours: number, minutes: number, seconds: number) { + return `${this.fill(hours)}${this.fill(minutes)}${this.fill(seconds)}` + } +} \ No newline at end of file diff --git a/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/ets/model/MediaUtils.ts b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/ets/model/MediaUtils.ts new file mode 100644 index 0000000000000000000000000000000000000000..9a5fba3b26a80e10fcf7999f36a23df29a2db51e --- /dev/null +++ b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/ets/model/MediaUtils.ts @@ -0,0 +1,193 @@ +// @ts-nocheck + +import mediaLibrary from '@ohos.multimedia.mediaLibrary' +import DateTimeUtil from '../model/DateTimeUtil' +import Logger from '../model/Logger' + +export default class MediaUtils { + private tag: string = 'zyk MediaUtils' + private mediaTest: mediaLibrary.MediaLibrary = mediaLibrary.getMediaLibrary(globalThis.abilityContext) + private static instance: MediaUtils = new MediaUtils() + private num: number = 0 + + public static getInstance() { + if (this.instance === undefined) { + this.instance = new MediaUtils() + } + return this.instance + } + + async createAndGetUri(mediaType: number) { + let info = this.getInfoFromType(mediaType) + let dateTimeUtil = new DateTimeUtil() + let name = `${dateTimeUtil.getDate()}_${dateTimeUtil.getTime()}` + let displayName = `${info.prefix}${name}${info.suffix}` + Logger.info(this.tag, `createAndGetUri displayName = ${displayName},mediaType = ${mediaType}`) + let publicPath = await this.mediaTest.getPublicDirectory(info.directory) + Logger.info(this.tag, `createAndGetUri publicPath = ${publicPath}`) + try { + return await this.mediaTest.createAsset(mediaType, displayName, publicPath) + } catch { + this.num++ + displayName = `${info.prefix}${name}_${this.num}${info.suffix}` + return await this.mediaTest.createAsset(mediaType, displayName, publicPath) + } + } + + async queryFile(dataUri: any) { + let fileKeyObj = mediaLibrary.FileKey + if (dataUri !== undefined) { + let args = dataUri.id.toString() + let fetchOp = { + selections: `${fileKeyObj.ID}=?`, + selectionArgs: [args], + } + const fetchFileResult = await this.mediaTest.getFileAssets(fetchOp) + Logger.info(this.tag, `fetchFileResult.getCount() = ${fetchFileResult.getCount()}`) + const fileAsset = await fetchFileResult.getAllObject() + return fileAsset[0] + } + } + + async getFdPath(fileAsset: any) { + let fd = await fileAsset.open('Rw') + Logger.info(this.tag, `fd = ${fd}`) + return fd + } + + async createFile(mediaType: number) { + let dataUri = await this.createAndGetUri(mediaType) + if (dataUri) { + let fileAsset = await this.queryFile(dataUri) + if (fileAsset) { + let fd = await this.getFdPath(fileAsset) + return fd + } + } + } + + async getFileAssetsFromType(mediaType: number) { + Logger.info(this.tag, `getFileAssetsFromType,mediaType = ${mediaType}`) + let fileKeyObj = mediaLibrary.FileKey + let fetchOp = { + selections: `${fileKeyObj.MEDIA_TYPE}=?`, + selectionArgs: [`${mediaType}`], + } + const fetchFileResult = await this.mediaTest.getFileAssets(fetchOp) + Logger.info(this.tag, `getFileAssetsFromType,fetchFileResult.count = ${fetchFileResult.getCount()}`) + let fileAssets = [] + if (fetchFileResult.getCount() > 0) { + fileAssets = await fetchFileResult.getAllObject() + } + return fileAssets + } + + async getAlbums() { + Logger.info(this.tag, 'getAlbums begin') + let albums = [] + const [ files, images, videos, audios ] = await Promise.all([ + this.getFileAssetsFromType(mediaLibrary.MediaType.FILE), + this.getFileAssetsFromType(mediaLibrary.MediaType.IMAGE), + this.getFileAssetsFromType(mediaLibrary.MediaType.VIDEO), + this.getFileAssetsFromType(mediaLibrary.MediaType.AUDIO) + ]) + albums.push({ + albumName: 'Documents', count: files.length, mediaType: mediaLibrary.MediaType.FILE + }) + albums.push({ + albumName: 'Pictures', count: images.length, mediaType: mediaLibrary.MediaType.IMAGE + }) + albums.push({ + albumName: 'Camera', count: videos.length, mediaType: mediaLibrary.MediaType.VIDEO + }) + albums.push({ + albumName: 'Audios', count: audios.length, mediaType: mediaLibrary.MediaType.AUDIO + }) + return albums + } + + deleteFile(media: any) { + let uri = media.uri + Logger.info(this.tag, `deleteFile,uri = ${uri}`) + return this.mediaTest.deleteAsset(uri) + } + + onDateChange(callback: () => void) { + this.mediaTest.on('albumChange', () => { + Logger.info(this.tag, 'albumChange called') + callback() + }) + this.mediaTest.on('imageChange', () => { + Logger.info(this.tag, 'imageChange called') + callback() + }) + this.mediaTest.on('audioChange', () => { + Logger.info(this.tag, 'audioChange called') + callback() + }) + this.mediaTest.on('videoChange', () => { + Logger.info(this.tag, 'videoChange called') + callback() + }) + this.mediaTest.on('fileChange', () => { + Logger.info(this.tag, 'fileChange called') + callback() + }) + } + + offDateChange() { + this.mediaTest.off('albumChange') + this.mediaTest.off('imageChange') + this.mediaTest.off('audioChange') + this.mediaTest.off('videoChange') + this.mediaTest.off('fileChange') + } + // 照片格式 + onChangePhotoFormat() { + if (globalThis.settingDataObj.photoFormat == 0) { + return 'png' + } + if (globalThis.settingDataObj.photoFormat == 1) { + return 'jpg' + } + if (globalThis.settingDataObj.photoFormat == 2) { + return 'bmp' + } + if (globalThis.settingDataObj.photoFormat == 3) { + return 'webp' + } + if (globalThis.settingDataObj.photoFormat == 4) { + return 'jpeg' + } + } + + getInfoFromType(mediaType: number) { + let result = { + prefix: '', suffix: '', directory: 0 + } + switch (mediaType) { + case mediaLibrary.MediaType.FILE: + result.prefix = 'FILE_' + result.suffix = '.txt' + result.directory = mediaLibrary.DirectoryType.DIR_DOCUMENTS + break + case mediaLibrary.MediaType.IMAGE: + result.prefix = 'IMG_' + // result.suffix = '.jpg' + result.suffix = `.${this.onChangePhotoFormat()}` + result.directory = mediaLibrary.DirectoryType.DIR_CAMERA + break + case mediaLibrary.MediaType.VIDEO: + result.prefix = 'VID_' + result.suffix = '.mp4' + result.directory = mediaLibrary.DirectoryType.DIR_CAMERA + break + case mediaLibrary.MediaType.AUDIO: + result.prefix = 'AUD_' + result.suffix = '.wav' + result.directory = mediaLibrary.DirectoryType.DIR_AUDIO + break + } + return result + } +} \ No newline at end of file diff --git a/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/ets/pages/tableIndex.ets b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/ets/pages/tableIndex.ets index 3cf1e77464b2d3ae493939b237008fd577982c25..6b49e1713fe39e5dc1889d48572d9839fd95b61e 100644 --- a/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/ets/pages/tableIndex.ets +++ b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/ets/pages/tableIndex.ets @@ -23,7 +23,11 @@ import { CountdownPage } from '../views/CountdownPage' import { FlashingLightPage } from '../views/FlashingLightPage' import { SlidePage } from '../views/SlidePage' import { modeSwitchPage } from '../views/modeSwitchPage' +import mediaLibrary from '@ohos.multimedia.mediaLibrary' +import fileio from '@ohos.fileio' +import media from '@ohos.multimedia.media' +import MediaUtils from '../model/MediaUtils' // import CameraService from '../model/CameraService' // import { CountdownPage } from '../views/CountdownPage' @@ -32,7 +36,7 @@ import { modeSwitchPage } from '../views/modeSwitchPage' // import { setting } from '../model/Setting' -const TAG: string = 'xmj indexPage' +const TAG: string = 'UI indexPage' globalThis.settingDataObj = { mirrorBol: false, // 镜像使能 -> 关闭 @@ -87,6 +91,7 @@ struct Index { autoCancel: false, customStyle: true }) + // 参考线 @State referenceLineBol: boolean = false @State onShow: boolean = false diff --git a/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/ets/views/modeSwitchPage.ets b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/ets/views/modeSwitchPage.ets index de845a236cad0276ea244256662d6470791ebefd..d602cabe2c0c27680f8fbb22cfb02092c635ced9 100644 --- a/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/ets/views/modeSwitchPage.ets +++ b/frameworks/native/camera/test/ndktest/camera_ndk_demo/entry/src/main/ets/views/modeSwitchPage.ets @@ -19,17 +19,51 @@ // // import { MultiCameraDialog } from '../Dialog/MultiCameraDialog' // import { PortraitCameraDialog } from '../Dialog/PortraitCameraDialog' -// import DateTimeUtil from '../model/DateTimeUtil' +import DateTimeUtil from '../model/DateTimeUtil' import Logger from '../model/Logger' +import cameraDemo from 'libentry.so' // import CameraService from '../model/CameraService' import mediaLibrary from '@ohos.multimedia.mediaLibrary'; import image from '@ohos.multimedia.image'; +import media from '@ohos.multimedia.media' +import MediaUtils from '../model/MediaUtils' +import AVRecorder from '@ohos.multimedia.media' @Component export struct modeSwitchPage { - private tag: string = 'zyk modeSwitchPage:' + private tag: string = 'UI modeSwitchPage:' + private mediaUtil = MediaUtils.getInstance() + private fileAsset: mediaLibrary.FileAsset = undefined + private fd: number = -1 + @State videoId: string = '' + private videoRecorder: media.AVRecorder = undefined + private videoConfig: AVRecorder.AVRecorderConfig = { + audioSourceType: 1, + videoSourceType: 1, + profile: { + audioBitrate: 48000, + audioChannels: 2, + // @ts-ignore + audioCodec: 'audio/mp4a-latm', + audioSampleRate: 48000, + durationTime: 1000, + // @ts-ignore + fileFormat: 'mp4', + videoBitrate: 3000000, + // @ts-ignore + videoCodec: 'video/avc', + videoFrameWidth: 640, + videoFrameHeight: 480, + videoFrameRate: 30 + }, + url: 'file:///data/media/01.mp4', + orientationHint: 0, + maxSize: 100, + maxDuration: 500, + rotation: 0 + } // 相机摄像头 @Link cameraDeviceIndex: number // surfaceID值 @@ -48,11 +82,11 @@ export struct modeSwitchPage { // 录制时间定时器 @State timer: number = undefined // 时间管理器 - // @State dateTimeUtil: DateTimeUtil = new DateTimeUtil() + @State dateTimeUtil: DateTimeUtil = new DateTimeUtil() // 选择模式 @State modelBagCol: string = 'photo' // 选择相机或者拍照 - // @State @Watch('onChangeIsModeBol') isModeBol: boolean = true + @State @Watch('onChangeIsModeBol') isModeBol: boolean = true // 录像开始暂停 // @State @Watch('onChangeRecord') isRecording: boolean = true // 视频缩略图 @@ -81,9 +115,9 @@ export struct modeSwitchPage { // customStyle: true // }) // // 暂停后点击停止 需要将暂停回复默认 - // onChangeIsModeBol() { + onChangeIsModeBol() { // this.isRecording = true - // } + } // // 恢复视频录制 // resumeVideo() { // CameraService.resumeVideo().then(() => { @@ -107,52 +141,80 @@ export struct modeSwitchPage { // CameraService.pauseVideo() // } // } - // // 倒计时拍照和录像 - // countTakeVideoFn() { - // if (this.countdownNum) { - // // 清除定时器 - // if (this.countTimerOut) { - // clearTimeout(this.countTimerOut) - // } - // if (this.countTimerInt) { - // clearInterval(this.countTimerInt) - // } - // // 开启定时器 - // this.countTimerOut = setTimeout(() => { - // // 判断是录像还是拍照模式 - // this.isVideoPhotoFn() - // }, this.countdownNum * 1000) - // // 开启计时器 - // this.countTimerInt = setInterval(() => { - // this.countdownNum-- - // if (this.countdownNum === 0) { - // clearInterval(this.countTimerInt) - // } - // }, 1000) - // } else { - // this.isVideoPhotoFn() - // } - // } - // // 判断录像或者照片模式 - // isVideoPhotoFn() { - // if (this.modelBagCol == 'photo') { - // CameraService.takePicture() - // } else if (this.modelBagCol == 'portrait') { - // CameraService.takePicture() - // } else if (this.modelBagCol == 'video') { - // this.isModeBol = false - // if (this.timer) { - // clearInterval(this.timer) - // } - // // 开始录制 - // CameraService.startVideo().then(() => { - // // 计时器 - // this.timer = setInterval(() => { - // this.videoRecodeTime += 1000 - // }, 1000) - // }) - // } - // } + // 倒计时拍照和录像 + countTakeVideoFn() { + if (this.countdownNum) { + // 清除定时器 + if (this.countTimerOut) { + clearTimeout(this.countTimerOut) + } + if (this.countTimerInt) { + clearInterval(this.countTimerInt) + } + // 开启定时器 + this.countTimerOut = setTimeout(() => { + // 判断是录像还是拍照模式 + this.isVideoPhotoFn() + }, this.countdownNum * 1000) + // 开启计时器 + this.countTimerInt = setInterval(() => { + this.countdownNum-- + if (this.countdownNum === 0) { + clearInterval(this.countTimerInt) + } + }, 1000) + } else { + this.isVideoPhotoFn() + } + } + async getVideoSurfaceID(){ + Logger.info(this.tag, `getVideoSurfaceID`) + this.videoRecorder = await media.createAVRecorder() + Logger.info(this.tag, `getVideoSurfaceID videoRecorder: ${this.videoRecorder}`) + + this.fileAsset = await this.mediaUtil.createAndGetUri(mediaLibrary.MediaType.VIDEO) + Logger.info(this.tag, `getVideoSurfaceID fileAsset: ${this.fileAsset}`) + + this.fd = await this.mediaUtil.getFdPath(this.fileAsset) + Logger.info(this.tag, `getVideoSurfaceID fd: ${this.fd}`) + + this.videoConfig.url = `fd://${this.fd}` + Logger.info(this.tag, `getVideoSurfaceID videoConfig.url : ${this.videoConfig.url }`) + this.videoConfig.profile.videoFrameRate = 15 + Logger.info(this.tag, `getVideoSurfaceID 111`) + await this.videoRecorder.prepare(this.videoConfig) + Logger.info(this.tag, `getVideoSurfaceID 222`) + this.videoId = await this.videoRecorder.getInputSurface() + Logger.info(this.tag, `getVideoSurfaceID videoId: ${this.videoId}`) + } + + // 判断录像或者照片模式 + async isVideoPhotoFn() { + await this.getVideoSurfaceID() + + //this.mReceiver = image.createImageReceiver(640, 480, 2000, 8) + // @ts-ignore + //this.videoId = this.mReceiver.getReceivingSurfaceId(); + + if (this.modelBagCol == 'photo') { + cameraDemo.startPhotoOrVideo(this.modelBagCol, this.videoId) + } else if (this.modelBagCol == 'video') { + this.isModeBol = false + if (this.timer) { + clearInterval(this.timer) + } + // 开始录制 + cameraDemo.startPhotoOrVideo(this.modelBagCol, this.videoId) + cameraDemo.videoOutputStart() + this.videoRecorder.start() +// cameraDemo.startPhotoOrVideo(this.modelBagCol).then(() => { +// // 计时器 +// this.timer = setInterval(() => { +// this.videoRecodeTime += 1000 +// }, 1000) +// }) + } + } aboutToAppear() { // CameraService.setTakePictureCallback(this.handleTakePicture.bind(this)) @@ -164,7 +226,7 @@ export struct modeSwitchPage { } build() { - if (true) { + if (this.isModeBol) { Column() { Text('拍照') @@ -265,7 +327,7 @@ export struct modeSwitchPage { .backgroundColor('rgba(255,255,255,0.20)') .onClick(() => { // 倒计时拍照录像—默认拍照录像 - // this.countTakeVideoFn() + this.countTakeVideoFn() }) } //.margin({ top: 32 }) @@ -293,104 +355,126 @@ export struct modeSwitchPage { } }.position({ x: '70%', y: '82%' }) } else { - // Column() { - // Row() { - // Text().size({ width: 12, height: 12 }).backgroundColor($r('app.color.theme_color')).borderRadius(6) - // Text(this.dateTimeUtil.getVideoTime(this.videoRecodeTime)) - // .fontSize(30) - // .fontColor(Color.White) - // .margin({ left: 8 }) - // }.offset({ x: -580, y: -180 }) - // }.position({ x: 120, y: 450 }) - // - // Column() { - // // 录像抓拍键 - // Button() { - // Text().width('120px').height('120px').borderRadius('35px').backgroundColor(Color.White) - // } - // .border({ width: 2, color: 0xFFFFFF, radius: 45 }) - // .width('200px') - // .height('200px') - // .backgroundColor('rgba(255,255,255,0.20)') - // .onClick(() => { - // CameraService.takePicture() - // }) - // }.position({ x: '10%', y: '82%' }) - // - // Column() { - // Row() { - // Column() { - // // 录像停止键 - // Button() { - // Image($r('app.media.ic_camera_video_close')).size({ width: 25, height: 25 }) - // } - // .width('120px') - // .height('120px') - // .backgroundColor($r('app.color.theme_color')) - // .onClick(() => { - // if (this.timer) { - // clearInterval(this.timer) - // } - // // 弹框无法响应 - // // CameraService.pauseVideo() - // // 停止录制 - // CameraService.stopVideo().then(async (fileAsset) => { - // this.videoRecodeTime = 0 - // this.isModeBol = true - // try { - // // 获取录制缩略图 - // this.videoThumbnail = await fileAsset.getThumbnail() - // } catch (err) { - // Logger.info(this.tag, 'videoThumbnail err----------:' + JSON.stringify(err.message)) - // } - // }) - // // 打开停止弹框 - // // this.isRecodeStopDialogController.open() - // }) - // } - // .width('180px') - // .height('180px') - // .borderRadius('60px') - // .backgroundColor($r('app.color.theme_color')) - // .justifyContent(FlexAlign.SpaceAround) - // } - // .justifyContent(FlexAlign.Center) - // .border({ width: 3, color: 0xFFFFFF, radius: 70 }) - // .width('200px') - // .height('200px') - // .backgroundColor('rgba(255,255,255,0.20)') - // }.position({ x: '40%', y: '82%' }) - // - // Column() { - // Row() { - // Column() { - // // 录像暂停-播放键 - // Button() { - // Image(this.isRecording ? $r('app.media.ic_camera_video_on') : $r('app.media.ic_camera_video_off')) - // .size({ - // width: 25, - // height: 25 - // }) - // } - // .width('120px') - // .height('120px') - // .backgroundColor($r('app.color.theme_color')) - // .onClick(() => { - // this.isRecording = !this.isRecording - // }) - // } - // .width('180px') - // .height('180px') - // .borderRadius('60px') - // .backgroundColor($r('app.color.theme_color')) - // .justifyContent(FlexAlign.SpaceAround) - // } - // .justifyContent(FlexAlign.Center) - // .border({ width: 3, color: 0xFFFFFF, radius: 70 }) - // .width('200px') - // .height('200px') - // .backgroundColor('rgba(255,255,255,0.20)') - // }.position({ x: '70%', y: '82%' }) + Column() { + Row() { + Text().size({ width: 12, height: 12 }).backgroundColor($r('app.color.theme_color')).borderRadius(6) + Text(this.dateTimeUtil.getVideoTime(this.videoRecodeTime)) + .fontSize(30) + .fontColor(Color.White) + .margin({ left: 8 }) + }.offset({ x: -580, y: -180 }) + }.position({ x: 120, y: 450 }) + + Column() { + // 录像抓拍键 + Button() { + Text().width('120px').height('120px').borderRadius('35px').backgroundColor(Color.White) + } + .border({ width: 2, color: 0xFFFFFF, radius: 45 }) + .width('200px') + .height('200px') + .backgroundColor('rgba(255,255,255,0.20)') + .onClick(() => { + //CameraService.takePicture() + }) + }.position({ x: '10%', y: '82%' }) + + Column() { + Row() { + Column() { + // 录像停止键 + Button() { + Image($r('app.media.ic_camera_video_close')).size({ width: 25, height: 25 }) + } + .width('120px') + .height('120px') + .backgroundColor($r('app.color.theme_color')) + .onClick(() => { + if (this.timer) { + clearInterval(this.timer) + } + // 弹框无法响应 + // CameraService.pauseVideo() + // 停止录制 + this.stopVideo().then(async (fileAsset) => { + this.videoRecodeTime = 0 + this.isModeBol = true + try { + // 获取录制缩略图 + this.videoThumbnail = await fileAsset.getThumbnail() + } catch (err) { + Logger.info(this.tag, 'videoThumbnail err----------:' + JSON.stringify(err.message)) + } + }) + // 打开停止弹框 + // this.isRecodeStopDialogController.open() + }) + } + .width('180px') + .height('180px') + .borderRadius('60px') + .backgroundColor($r('app.color.theme_color')) + .justifyContent(FlexAlign.SpaceAround) + } + .justifyContent(FlexAlign.Center) + .border({ width: 3, color: 0xFFFFFF, radius: 70 }) + .width('200px') + .height('200px') + .backgroundColor('rgba(255,255,255,0.20)') + }.position({ x: '40%', y: '82%' }) + +// Column() { +// Row() { +// Column() { +// // 录像暂停-播放键 +// Button() { +// Image(this.isRecording ? $r('app.media.ic_camera_video_on') : $r('app.media.ic_camera_video_off')) +// .size({ +// width: 25, +// height: 25 +// }) +// } +// .width('120px') +// .height('120px') +// .backgroundColor($r('app.color.theme_color')) +// .onClick(() => { +// this.isRecording = !this.isRecording +// }) +// } +// .width('180px') +// .height('180px') +// .borderRadius('60px') +// .backgroundColor($r('app.color.theme_color')) +// .justifyContent(FlexAlign.SpaceAround) +// } +// .justifyContent(FlexAlign.Center) +// .border({ width: 3, color: 0xFFFFFF, radius: 70 }) +// .width('200px') +// .height('200px') +// .backgroundColor('rgba(255,255,255,0.20)') +// }.position({ x: '70%', y: '82%' }) + } + } + + async stopVideo() { + try { + if (this.videoRecorder) { + await this.videoRecorder.stop() + await this.videoRecorder.release() + } +// if (this.videoOutput) { +// await this.videoOutput.stop() +// await this.videoOutput.release() +// } + if (this.fileAsset) { + await this.fileAsset.close(this.fd) + return this.fileAsset + } + Logger.info(this.tag, 'stopVideo end') +// 弹框开始需要注释 +// await this.videoOutput.stop() + } catch (err) { + Logger.info(this.tag, 'stopVideo err: ' + JSON.stringify(err)) } } } diff --git a/frameworks/native/ndk/impl/camera_manager_impl.cpp b/frameworks/native/ndk/impl/camera_manager_impl.cpp index aaf923df184dfd67585742fc14e55351cff32b51..609685e7bbb53d61081ec315f58721e0fd99929f 100644 --- a/frameworks/native/ndk/impl/camera_manager_impl.cpp +++ b/frameworks/native/ndk/impl/camera_manager_impl.cpp @@ -153,9 +153,15 @@ Camera_ErrorCode Camera_Manager::GetSupportedCameraOutputCapability(const Camera MEDIA_ERR_LOG("alloc size <= 0"); return CAMERA_INVALID_ARGUMENT; } + Camera_Profile **previewProfilesWarp = new Camera_Profile *; + Camera_Profile **photoProfilesWarp = new Camera_Profile *; + Camera_VideoProfile **videoProfilesWarp = new Camera_VideoProfile *; Camera_Profile *outPreviewProfiles = new Camera_Profile[previewOutputNum]; Camera_Profile *outPhotoProfiles = new Camera_Profile[photoOutputNum]; Camera_VideoProfile *outVideoProfiles = new Camera_VideoProfile[videoOutputNum]; + *previewProfilesWarp = outPreviewProfiles; + *photoProfilesWarp = outPhotoProfiles; + *videoProfilesWarp = outVideoProfiles; for (int i = 0; i < previewOutputNum; i++) { outPreviewProfiles[i].format = static_cast(previewProfiles[i].GetCameraFormat()); outPreviewProfiles[i].size.width = previewProfiles[i].GetSize().width; @@ -164,14 +170,14 @@ Camera_ErrorCode Camera_Manager::GetSupportedCameraOutputCapability(const Camera } MEDIA_ERR_LOG("GetSupportedCameraOutputCapability previewOutputNum exit"); - outCapability->previewProfiles = &outPreviewProfiles; + outCapability->previewProfiles = previewProfilesWarp; for (int i = 0; i < photoOutputNum; i++) { outPhotoProfiles[i].format = static_cast(photoProfiles[i].GetCameraFormat()); outPhotoProfiles[i].size.width = photoProfiles[i].GetSize().width; outPhotoProfiles[i].size.height = photoProfiles[i].GetSize().height; } - outCapability->photoProfiles = &outPhotoProfiles; + outCapability->photoProfiles = photoProfilesWarp; for (int i = 0; i < videoOutputNum; i++) { outVideoProfiles[i].format = static_cast(videoProfiles[i].GetCameraFormat()); @@ -180,7 +186,7 @@ Camera_ErrorCode Camera_Manager::GetSupportedCameraOutputCapability(const Camera outVideoProfiles[i].range.min = videoProfiles[i].framerates_[0]; outVideoProfiles[i].range.max = videoProfiles[i].framerates_[1]; } - outCapability->videoProfiles = &outVideoProfiles; + outCapability->videoProfiles = videoProfilesWarp; *cameraOutputCapability = outCapability; MEDIA_ERR_LOG("GetSupportedCameraOutputCapability previewOutputNum return");