From a4f1ad741316728184e68ccab9c06a8ba809d124 Mon Sep 17 00:00:00 2001 From: ouyang Date: Fri, 17 Jan 2025 16:07:02 +0800 Subject: [PATCH 1/2] =?UTF-8?q?HDRVivid=E5=BD=95=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/cpp/capbilities/VideoEncoder.cpp | 7 ++ .../src/main/ets/common/utils/CameraCheck.ets | 48 +++++++++++- entry/src/main/ets/pages/Index.ets | 4 +- entry/src/main/ets/pages/Recorder.ets | 76 ++++++++++++++++++- 4 files changed, 128 insertions(+), 7 deletions(-) diff --git a/entry/src/main/cpp/capbilities/VideoEncoder.cpp b/entry/src/main/cpp/capbilities/VideoEncoder.cpp index ac2c556..2030718 100644 --- a/entry/src/main/cpp/capbilities/VideoEncoder.cpp +++ b/entry/src/main/cpp/capbilities/VideoEncoder.cpp @@ -180,5 +180,12 @@ int32_t VideoEncoder::GetSurface(SampleInfo &sampleInfo) (void)OH_NativeWindow_NativeWindowHandleOpt(sampleInfo.window, SET_USAGE, 16425); // 16425: Window usage (void)OH_NativeWindow_NativeWindowHandleOpt(sampleInfo.window, SET_FORMAT, ToGraphicPixelFormat(sampleInfo.pixelFormat, sampleInfo.isHDRVivid)); + if(sampleInfo.isHDRVivid) { + uint8_t metadataType = OH_VIDEO_HDR_HLG; + (void)OH_NativeWindow_SetMetadataValue(sampleInfo.window, OH_HDR_METADATA_TYPE, sizeof(uint8_t), &metadataType); + (void)OH_NativeWindow_NativeWindowHandleOpt(sampleInfo.window, SET_COLOR_GAMUT, NATIVEBUFFER_COLOR_GAMUT_BT2020); + OH_NativeBuffer_ColorSpace colorSpace = OH_COLORSPACE_BT2020_HLG_LIMIT; + (void)OH_NativeWindow_SetColorSpace(sampleInfo.window, colorSpace); + } return AVCODEC_SAMPLE_ERR_OK; } \ No newline at end of file diff --git a/entry/src/main/ets/common/utils/CameraCheck.ets b/entry/src/main/ets/common/utils/CameraCheck.ets index 0f10251..2884907 100644 --- a/entry/src/main/ets/common/utils/CameraCheck.ets +++ b/entry/src/main/ets/common/utils/CameraCheck.ets @@ -20,7 +20,53 @@ import { CommonConstants as Const } from '../CommonConstants'; const TAG = 'CAMERA_CHECK'; -export function cameraCheck(cameraManager: camera.CameraManager, +function getPreviewProfile(previewProfiles: Array, size: camera.Size, isHDRVivid: number): undefined | camera.Profile { + let previewProfile: undefined | camera.Profile = previewProfiles.find((profile: camera.Profile) => { + if(isHDRVivid) { + return profile.format === camera.CameraFormat.CAMERA_FORMAT_YCRCB_P010 && + profile.size.width === size.width && profile.size.height == size.height + } else { + return profile.format === camera.CameraFormat.CAMERA_FORMAT_YUV_420_SP && + profile.size.width === size.width && profile.size.height == size.height + } + }); + return previewProfile; +} + +export function previewProfileCameraCheck(cameraManager: camera.CameraManager, + cameraData: CameraDataModel): undefined | camera.Profile { + let cameraDevices = cameraManager.getSupportedCameras(); + if (cameraDevices !== undefined && cameraDevices.length <= 0) { + Logger.error(TAG, 'cameraManager.getSupportedCameras error!'); + return; + } + + let profiles: camera.CameraOutputCapability = + cameraManager.getSupportedOutputCapability(cameraDevices[0], camera.SceneMode.NORMAL_VIDEO); + if (!profiles) { + Logger.error(TAG, 'cameraManager.getSupportedOutputCapability error!'); + return; + } + + let previewProfilesArray: Array = profiles.previewProfiles; + if (!previewProfilesArray) { + Logger.error("createOutput previewProfilesArray == null || undefined"); + return; + } + + let videoSize: camera.Size = { + width: 1920, + height: 1080 + } + let previewProfile: undefined | camera.Profile = getPreviewProfile(previewProfilesArray, videoSize, cameraData.isHDRVivid); + if (!previewProfile) { + Logger.error('previewProfile is not found'); + return; + } + return previewProfile; +} + +export function videoProfileCheck(cameraManager: camera.CameraManager, cameraData: CameraDataModel): undefined | camera.VideoProfile { let cameraDevices = cameraManager.getSupportedCameras(); if (cameraDevices !== undefined && cameraDevices.length <= 0) { diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index 56f63f5..9adab6b 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -23,7 +23,7 @@ import Logger from '../common/utils/Logger'; import DateTimeUtil from '../common/utils/DateTimeUtils'; import { CommonConstants as Const } from '../common/CommonConstants'; import { CameraDataModel } from '../model/CameraDateModel'; -import { cameraCheck } from '../common/utils/CameraCheck'; +import { videoProfileCheck } from '../common/utils/CameraCheck'; const TAG: string = Const.INDEX_TAG; const DATETIME: DateTimeUtil = new DateTimeUtil(); @@ -82,7 +82,7 @@ struct Player { Logger.error(TAG, 'camera.getCameraManager error!'); } - let videoProfile: undefined | camera.VideoProfile = cameraCheck(cameraManager, this.cameraData); + let videoProfile: undefined | camera.VideoProfile = videoProfileCheck(cameraManager, this.cameraData); if (!videoProfile) { Logger.error(TAG, 'videoProfile is not found'); promptAction.showToast({ diff --git a/entry/src/main/ets/pages/Recorder.ets b/entry/src/main/ets/pages/Recorder.ets index 1d48c9a..0c049c0 100644 --- a/entry/src/main/ets/pages/Recorder.ets +++ b/entry/src/main/ets/pages/Recorder.ets @@ -22,7 +22,8 @@ import Logger from '../common/utils/Logger'; import { dateTime } from '../common/utils/DateTimeUtils'; import { CommonConstants as Const } from '../common/CommonConstants'; import { CameraDataModel } from '../model/CameraDateModel'; -import { cameraCheck } from '../common/utils/CameraCheck'; +import { previewProfileCameraCheck, videoProfileCheck } from '../common/utils/CameraCheck'; +import { colorSpaceManager } from '@kit.ArkGraphics2D'; const TAG: string = Const.RECORDER_TAG; @@ -59,6 +60,59 @@ async function releaseCamera(): Promise { videoSession.release(); } +function isVideoStabilizationModeSupported(session: camera.VideoSession, mode: camera.VideoStabilizationMode): boolean { + let isSupported: boolean = false; + try { + isSupported = session.isVideoStabilizationModeSupported(mode); + } catch (error) { + // 失败返回错误码error.code并处理 + let err = error as BusinessError; + console.error(`The isVideoStabilizationModeSupported call failed. error code: ${err.code}`); + } + return isSupported; +} + +function setVideoStabilizationMode(session: camera.VideoSession): boolean { + let mode: camera.VideoStabilizationMode = camera.VideoStabilizationMode.AUTO; + // 查询是否支持视频防抖 + let isSupported: boolean = isVideoStabilizationModeSupported(session, mode); + if (isSupported) { + console.info(`setVideoStabilizationMode: ${mode}`); + // 设置视频防抖 + session.setVideoStabilizationMode(mode); + let activeVideoStabilizationMode = session.getActiveVideoStabilizationMode(); + console.info(`activeVideoStabilizationMode: ${activeVideoStabilizationMode}`); + } else { + console.info(`videoStabilizationMode: ${mode} is not support`); + } + return isSupported; +} + +function getSupportedColorSpaces(session: camera.VideoSession): Array { + let colorSpaces: Array = []; + try { + colorSpaces = session.getSupportedColorSpaces(); + } catch (error) { + let err = error as BusinessError; + console.error(`The getSupportedColorSpaces call failed. error code: ${err.code}`); + } + return colorSpaces; +} + +function setColorSpaceBeforeCommitConfig(session: camera.VideoSession, isHdr: boolean): void { + 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) { + console.info(`setColorSpace: ${colorSpace}`); + session.setColorSpace(colorSpace); + let activeColorSpace:colorSpaceManager.ColorSpace = session.getActiveColorSpace(); + console.info(`activeColorSpace: ${activeColorSpace}`); + } else { + console.info(`colorSpace: ${colorSpace} is not support`); + } +} + @Entry @Component struct Recorder { @@ -130,14 +184,22 @@ struct Recorder { return; } - let videoProfile: undefined | camera.VideoProfile = cameraCheck(cameraManager, params); + // 获取支持的模式类型 + 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; + } + + let videoProfile: undefined | camera.VideoProfile = videoProfileCheck(cameraManager, params); if (!videoProfile) { Logger.error(TAG, 'videoProfile is not found!'); return; } - //The preview stream of XComponent. - let XComponentPreviewProfile: camera.Profile = params.previewProfile; + // The preview stream of XComponent. + let XComponentPreviewProfile: camera.Profile | undefined = previewProfileCameraCheck(cameraManager, params) if (XComponentPreviewProfile === undefined) { Logger.error(TAG, 'XComponentPreviewProfile is not found'); return; @@ -230,6 +292,12 @@ struct Recorder { Logger.error(TAG, `videoSession commitConfig error: ${JSON.stringify(err)}`); } + // 设置视频防抖 + if (setVideoStabilizationMode(videoSession)) { + // 设置色彩空间 + setColorSpaceBeforeCommitConfig(videoSession, true); + } + // Session start. try { await videoSession.start(); -- Gitee From 3be4bb3d356e9d1d6a4c0bcafe6c63e3827d430a Mon Sep 17 00:00:00 2001 From: ouyang Date: Thu, 27 Mar 2025 11:15:24 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E2=91=A0=E5=88=A0=E9=99=A4=E5=86=97?= =?UTF-8?q?=E4=BD=99=E4=BB=A3=E7=A0=81=E3=80=82buffer=E7=9A=84width?= =?UTF-8?q?=E3=80=81height=E3=80=81pixelformat=E3=80=81colorspace=E7=94=B1?= =?UTF-8?q?=E7=94=9F=E4=BA=A7=E8=80=85=E5=86=B3=E5=AE=9A=EF=BC=8C=E4=B8=8D?= =?UTF-8?q?=E9=9C=80=E4=B8=BB=E5=8A=A8=E5=AF=B9nativeWindow=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E8=BF=99=E4=BA=9B=E5=8F=82=E6=95=B0=E3=80=82=20?= =?UTF-8?q?=E2=91=A1=E6=9B=B4=E6=94=B9=E6=97=8B=E8=BD=AC=E8=A7=92=E5=BA=A6?= =?UTF-8?q?=E7=9A=84=E9=80=BB=E8=BE=91=EF=BC=8C=E8=A7=A3=E5=B0=81=E8=A3=85?= =?UTF-8?q?->=E8=A7=A3=E7=A0=81=E9=87=87=E7=94=A8=E8=A7=86=E9=A2=91?= =?UTF-8?q?=E5=B0=81=E8=A3=85=E5=8E=9F=E8=A7=92=E5=BA=A6=E9=80=81=E6=98=BE?= =?UTF-8?q?=EF=BC=8C=E9=85=8D=E7=BD=AENativeWindowSetScalingModeV2?= =?UTF-8?q?=EF=BC=8C=E4=BD=BF=E5=9B=BE=E5=83=8F=E8=83=BD=E8=87=AA=E9=80=82?= =?UTF-8?q?=E5=BA=94window=E5=B0=BA=E5=AF=B8=E7=BC=A9=E6=94=BE=EF=BC=9B?= =?UTF-8?q?=E7=BC=96=E7=A0=81->=E5=B0=81=E8=A3=85=EF=BC=9A=E7=94=B1?= =?UTF-8?q?=E4=BA=8E=E7=9B=B8=E6=9C=BA=E5=8F=AA=E6=9C=89=E7=B1=BB=E4=BC=BC?= =?UTF-8?q?1920=C3=971080=E8=BF=99=E6=A0=B7=E7=9A=84=E6=A8=AA=E5=B1=8F?= =?UTF-8?q?=E7=9A=84=E7=9A=84profile=EF=BC=8C=E6=B2=A1=E6=9C=891080=C3=971?= =?UTF-8?q?920=E7=9A=84profile=EF=BC=8C=E6=89=80=E4=BB=A5=E5=BE=97?= =?UTF-8?q?=E5=BE=80=E6=96=87=E4=BB=B6=E9=87=8C=E5=B0=81=E8=A3=85=E4=B8=80?= =?UTF-8?q?=E4=B8=AA90=E5=BA=A6=E7=9A=84=E8=A7=92=E5=BA=A6=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=EF=BC=8C=E5=90=8E=E7=BB=AD=E6=92=AD=E6=94=BE=E6=89=8D?= =?UTF-8?q?=E4=BC=9A=E6=98=AF=E7=AB=96=E5=B1=8F=E6=98=BE=E7=A4=BA=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- entry/src/main/cpp/capbilities/Muxer.cpp | 5 ++- .../src/main/cpp/capbilities/VideoDecoder.cpp | 5 +-- .../src/main/cpp/capbilities/VideoEncoder.cpp | 33 ------------------- entry/src/main/cpp/render/PluginRender.cpp | 1 + 4 files changed, 4 insertions(+), 40 deletions(-) diff --git a/entry/src/main/cpp/capbilities/Muxer.cpp b/entry/src/main/cpp/capbilities/Muxer.cpp index fec20da..1bcd8b3 100644 --- a/entry/src/main/cpp/capbilities/Muxer.cpp +++ b/entry/src/main/cpp/capbilities/Muxer.cpp @@ -20,8 +20,7 @@ #define LOG_TAG "Muxer" namespace { -constexpr int32_t VERTICAL_ANGLE = 90; -constexpr int32_t HORIZONTAL_ANGLE = 0; +constexpr int32_t CAMERA_ANGLE = 90; } Muxer::~Muxer() @@ -59,7 +58,7 @@ int32_t Muxer::Config(SampleInfo &sampleInfo) int32_t ret = OH_AVMuxer_AddTrack(muxer_, &videoTrackId_, formatVideo); OH_AVFormat_Destroy(formatVideo); formatVideo = nullptr; - OH_AVMuxer_SetRotation(muxer_, sampleInfo.videoHeight > sampleInfo.videoWidth ? VERTICAL_ANGLE : HORIZONTAL_ANGLE); + OH_AVMuxer_SetRotation(muxer_, CAMERA_ANGLE); CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK, AVCODEC_SAMPLE_ERR_ERROR, "AddTrack failed"); return AVCODEC_SAMPLE_ERR_OK; } diff --git a/entry/src/main/cpp/capbilities/VideoDecoder.cpp b/entry/src/main/cpp/capbilities/VideoDecoder.cpp index 5ae314b..7cfd167 100644 --- a/entry/src/main/cpp/capbilities/VideoDecoder.cpp +++ b/entry/src/main/cpp/capbilities/VideoDecoder.cpp @@ -20,7 +20,6 @@ namespace { constexpr int LIMIT_LOGD_FREQUENCY = 50; -constexpr int ROTATION_ANGLE = 90; } // namespace VideoDecoder::~VideoDecoder() @@ -55,9 +54,7 @@ int32_t VideoDecoder::Configure(const SampleInfo &sampleInfo) OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, sampleInfo.videoHeight); OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, sampleInfo.frameRate); OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, sampleInfo.pixelFormat); - if (sampleInfo.videoHeight > sampleInfo.videoWidth) { - OH_AVFormat_SetIntValue(format, OH_MD_KEY_ROTATION, sampleInfo.rotation + ROTATION_ANGLE); - } + OH_AVFormat_SetIntValue(format, OH_MD_KEY_ROTATION, sampleInfo.rotation); AVCODEC_SAMPLE_LOGI("====== VideoDecoder config ======"); AVCODEC_SAMPLE_LOGI("%{public}d*%{public}d, %{public}.1ffps", sampleInfo.videoWidth, sampleInfo.videoHeight, diff --git a/entry/src/main/cpp/capbilities/VideoEncoder.cpp b/entry/src/main/cpp/capbilities/VideoEncoder.cpp index 7342702..cd1c5f2 100644 --- a/entry/src/main/cpp/capbilities/VideoEncoder.cpp +++ b/entry/src/main/cpp/capbilities/VideoEncoder.cpp @@ -18,26 +18,6 @@ #undef LOG_TAG #define LOG_TAG "VideoEncoder" -namespace { - -int32_t ToGraphicPixelFormat(int32_t avPixelFormat, bool isHDRVivid) -{ - if (isHDRVivid) { - return NATIVEBUFFER_PIXEL_FMT_YCBCR_P010; - } - switch (avPixelFormat) { - case AV_PIXEL_FORMAT_RGBA: - return NATIVEBUFFER_PIXEL_FMT_RGBA_8888; - case AV_PIXEL_FORMAT_YUVI420: - return NATIVEBUFFER_PIXEL_FMT_YCBCR_420_P; - case AV_PIXEL_FORMAT_NV21: - return NATIVEBUFFER_PIXEL_FMT_YCRCB_420_SP; - default: // NV12 and others - return NATIVEBUFFER_PIXEL_FMT_YCRCB_420_SP; - } -} -} // namespace - VideoEncoder::~VideoEncoder() { Release(); @@ -175,18 +155,5 @@ int32_t VideoEncoder::GetSurface(SampleInfo &sampleInfo) int32_t ret = OH_VideoEncoder_GetSurface(encoder_, &sampleInfo.window); CHECK_AND_RETURN_RET_LOG(ret == AV_ERR_OK && sampleInfo.window, AVCODEC_SAMPLE_ERR_ERROR, "Get surface failed, ret: %{public}d", ret); - (void)OH_NativeWindow_NativeWindowHandleOpt(sampleInfo.window, SET_BUFFER_GEOMETRY, sampleInfo.videoWidth, - sampleInfo.videoHeight); - (void)OH_NativeWindow_NativeWindowHandleOpt(sampleInfo.window, SET_USAGE, 16425); // 16425: Window usage - (void)OH_NativeWindow_NativeWindowHandleOpt(sampleInfo.window, SET_FORMAT, - ToGraphicPixelFormat(sampleInfo.pixelFormat, sampleInfo.isHDRVivid)); - if(sampleInfo.isHDRVivid) { - uint8_t metadataType = OH_VIDEO_HDR_HLG; - (void)OH_NativeWindow_SetMetadataValue(sampleInfo.window, OH_HDR_METADATA_TYPE, sizeof(uint8_t), &metadataType); - (void)OH_NativeWindow_NativeWindowHandleOpt(sampleInfo.window, SET_COLOR_GAMUT, - NATIVEBUFFER_COLOR_GAMUT_BT2020); - OH_NativeBuffer_ColorSpace colorSpace = OH_COLORSPACE_BT2020_HLG_LIMIT; - (void)OH_NativeWindow_SetColorSpace(sampleInfo.window, colorSpace); - } return AVCODEC_SAMPLE_ERR_OK; } \ No newline at end of file diff --git a/entry/src/main/cpp/render/PluginRender.cpp b/entry/src/main/cpp/render/PluginRender.cpp index 6d8a479..415003d 100644 --- a/entry/src/main/cpp/render/PluginRender.cpp +++ b/entry/src/main/cpp/render/PluginRender.cpp @@ -54,6 +54,7 @@ void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) { if (render->eglCore_->EglContextInit(window, width, height)) { auto context = PluginManager::GetInstance(); context->pluginWindow_ = (OHNativeWindow *)window; + OH_NativeWindow_NativeWindowSetScalingModeV2(context->pluginWindow_, OH_SCALING_MODE_SCALE_FIT_V2); } } } -- Gitee