0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

OpenHarmony 3.2 Beta多媒体系列——视频录制

2KHh_gh_15d2f06 来源:未知 2023-02-10 11:20 次阅读

ca3ce0d4-a8f1-11ed-bfe3-dac502259ad0.png

巴延兴

深圳开鸿数字产业发展有限公司

资深OS框架开发工程师

一、简介

媒体子系统为开发者提供了媒体相关的很多功能,本文针对其中的视频录制功能做个详细的介绍。首先,我将通过媒体子系统提供的视频录制Test代码作为切入点,给大家梳理一下整个录制的流程。

二、目录

foundation/multimedia/camera_framework

├──frameworks
│ ├── js
│ │ └── camera_napi                            #napi实现
│ │     └── src
│ │         ├── input                          #Camera输入
│ │         ├── output                         #Camera输出
│ │         └── session                        #会话管理
│ └── native                                     #native实现
│     └── camera
│         ├── BUILD.gn
│         ├── src
│         │ ├── input                          #Camera输入
│         │ ├── output                         #Camera输出
│         │ └── session                        #会话管理
├── interfaces                                     #接口定义
│ ├── inner_api                                  #内部native实现
│ │ └── native
│ │     ├── camera
│ │     │ └── include
│ │     │     ├── input
│ │     │     ├── output
│ │     │     └── session
│ └── kits                                       #napi接口
│     └── js
│         └── camera_napi
│             ├── BUILD.gn
│             ├── include
│             │ ├── input
│             │ ├── output
│             │ └── session
│             └── @ohos.multimedia.camera.d.ts
└── services                                       #服务端
    └── camera_service
        ├── binder
        │ ├── base
        │ ├── client                             #IPC的客户端
        │ │ └── src
      │ └── server                             #IPC的服务端
      │     └── src
└──src

三、录制的总体流程

ca66cd5e-a8f1-11ed-bfe3-dac502259ad0.png    

四、Native接口使用

在OpenAtom OpenHarmony(以下简称“OpenHarmony”)系统中,多媒体子系统通过N-API接口提供给上层JS调用,N-API相当于是JS和Native之间的桥梁,在OpenHarmony源码中,提供了C++直接调用视频录制功能的例子,foundation/multimedia/camera_framework/interfaces/inner_api/native/test目录中。本文章主要参考了camera_video.cpp文件中的视频录制流程。 首先根据camera_video.cpp的main方法,了解下视频录制的主要流程代码。
int main(int argc, char **argv)
{
    ......


    // 创建CameraManager实例
    sptr camManagerObj = CameraManager::GetInstance();


    // 设置回调
    camManagerObj->SetCallback(std::make_shared(testName));


    // 获取支持的相机设备列表
    std::vector> cameraObjList = camManagerObj->GetSupportedCameras();


    // 创建采集会话
    sptr captureSession = camManagerObj->CreateCaptureSession();


    // 开始配置采集会话
    captureSession->BeginConfig();


    // 创建CameraInput
    sptr captureInput = camManagerObj->CreateCameraInput(cameraObjList[0]);
    sptr cameraInput = (sptr &)captureInput;


    // 开启CameraInput
    cameraInput->Open();


    // 设置CameraInput的Error回调
    cameraInput->SetErrorCallback(std::make_shared(testName));


    // 添加CameraInput实例到采集会话中
    ret = captureSession->AddInput(cameraInput);


    sptr videoSurface = nullptr;
    std::shared_ptr recorder = nullptr;


    // 创建Video的Surface
    videoSurface = Surface::CreateSurfaceAsConsumer();


    sptr videoListener = new SurfaceListener("Video", SurfaceType::VIDEO, g_videoFd, videoSurface);


    // 注册Surface的事件监听
    videoSurface->RegisterConsumerListener((sptr &)videoListener);


    // 视频的配置
    VideoProfile videoprofile = VideoProfile(static_cast(videoFormat), videosize, videoframerates);


    // 创建VideoOutput实例
    sptr videoOutput = camManagerObj->CreateVideoOutput(videoprofile, videoSurface);


    // 设置VideoOutput的回调
    ((sptr &)videoOutput)->SetCallback(std::make_shared(testName));


    // 添加videoOutput到采集会话中
    ret = captureSession->AddOutput(videoOutput);


    // 提交会话配置
    ret = captureSession->CommitConfig();


    // 开始录制
    ret = ((sptr &)videoOutput)->Start();




    sleep(videoPauseDuration);
    MEDIA_DEBUG_LOG("Resume video recording");
    // 暂停录制
    ret = ((sptr &)videoOutput)->Resume();


    MEDIA_DEBUG_LOG("Wait for 5 seconds before stop");
    sleep(videoCaptureDuration);
    MEDIA_DEBUG_LOG("Stop video recording");
    // 停止录制
    ret = ((sptr &)videoOutput)->Stop();


    MEDIA_DEBUG_LOG("Closing the session");
    // 停止采集会话
    ret = captureSession->Stop();


    MEDIA_DEBUG_LOG("Releasing the session");
    // 释放会话采集
    captureSession->Release();


    // Close video file
    TestUtils::SaveVideoFile(nullptr, 0, VideoSaveMode::CLOSE, g_videoFd);
    cameraInput->Release();
    camManagerObj->SetCallback(nullptr);
    return 0;
}
以上是视频录制的整体流程,其过程主要通过Camera模块支持的能力来实现,其中涉及几个重要的类:CaptureSession、CameraInput、VideoOutput。CaptureSession是整个过程的控制者,CameraInput和VideoOutput相当于是设备的输入和输出。

五、调用流程

ca7758e0-a8f1-11ed-bfe3-dac502259ad0.jpgca87d83c-a8f1-11ed-bfe3-dac502259ad0.jpgca9c452e-a8f1-11ed-bfe3-dac502259ad0.jpg       左右滑动查看更多  后续主要针对上面的调用流程,梳理具体的调用流程,方便我们对了解视频录制的整理架构有一个更加深入的了解。 1. 创建CameraManager实例通过CameraManager::GetInstance()获取CameraManager的实例,后续的一些接口都是通过该实例进行调用的。GetInstance使用了单例模式,在OpenHarmony代码中这种方式很常见。
sptr &CameraManager::GetInstance()
{
    if (CameraManager::cameraManager_ == nullptr) {
        MEDIA_INFO_LOG("Initializing camera manager for first time!");
        CameraManager::cameraManager_ = new(std::nothrow) CameraManager();
        if (CameraManager::cameraManager_ == nullptr) {
            MEDIA_ERR_LOG("CameraManager::GetInstance failed to new CameraManager");
        }
    }
    return CameraManager::cameraManager_;
}
2. 获取支持的相机设备列表通过调用CameraManager的GetSupportedCameras()接口,获取设备支持的CameraDevice列表。跟踪代码可以发现serviceProxy_->GetCameras最终会调用到Camera服务端的对应接口。
std::vector> CameraManager::GetSupportedCameras()
{
    CAMERA_SYNC_TRACE;


    std::lock_guard lock(mutex_);
    std::vector cameraIds;
    std::vector> cameraAbilityList;
    int32_t retCode = -1;
    sptr cameraObj = nullptr;
    int32_t index = 0;


    if (cameraObjList.size() > 0) {
        cameraObjList.clear();
    }
    if (serviceProxy_ == nullptr) {
        MEDIA_ERR_LOG("CameraManager::GetCameras serviceProxy_ is null, returning empty list!");
        return cameraObjList;
    }
    std::vector> supportedCameras;
    retCode = serviceProxy_->GetCameras(cameraIds, cameraAbilityList);
    if (retCode == CAMERA_OK) {
        for (auto& it : cameraIds) {
            cameraObj = new(std::nothrow) CameraDevice(it, cameraAbilityList[index++]);
            if (cameraObj == nullptr) {
                MEDIA_ERR_LOG("CameraManager::GetCameras new CameraDevice failed for id={public}%s", it.c_str());
                continue;
            }
            supportedCameras.emplace_back(cameraObj);
        }
    } else {
        MEDIA_ERR_LOG("CameraManager::GetCameras failed!, retCode: %{public}d", retCode);
    }


    ChooseDeFaultCameras(supportedCameras);
    return cameraObjList;
}
3. 创建采集会话下面是比较重要的环节,通过调用CameraManager的CreateCaptureSession接口创建采集会话。CameraManager创建采集会话,是通过serviceProxy_->CreateCaptureSession方式进行调用,这里涉及到了OpenHarmony中的IPC的调用,serviceProxy_是远端服务在本地的代理,通过这个代理可以调用到具体的服务端,这里是HCameraService。
sptr CameraManager::CreateCaptureSession()
{
    CAMERA_SYNC_TRACE;
    sptr captureSession = nullptr;
    sptr result = nullptr;
    int32_t retCode = CAMERA_OK;


    if (serviceProxy_ == nullptr) {
        MEDIA_ERR_LOG("CameraManager::CreateCaptureSession serviceProxy_ is null");
        return nullptr;
    }
    retCode = serviceProxy_->CreateCaptureSession(captureSession);
    if (retCode == CAMERA_OK && captureSession != nullptr) {
        result = new(std::nothrow) CaptureSession(captureSession);
        if (result == nullptr) {
            MEDIA_ERR_LOG("Failed to new CaptureSession");
        }
    } else {
        MEDIA_ERR_LOG("Failed to get capture session object from hcamera service!, %{public}d", retCode);
    }
    return result;
}
代码最终来到HCameraService::CreateCaptureSession中,该方法中new了一个HCaptureSession对象,并且将该对象传递给了参数session,所以前面的captureSession对象就是这里new出来的HCaptureSession,前面的CameraManager的CreateCaptureSession()方法中将captureSession封装成CaptureSession对象返回给应用层使用。
int32_t HCameraService::CreateCaptureSession(sptr &session)
{
    CAMERA_SYNC_TRACE;
    sptr captureSession;
    if (streamOperatorCallback_ == nullptr) {
        streamOperatorCallback_ = new(std::nothrow) StreamOperatorCallback();
        if (streamOperatorCallback_ == nullptr) {
            MEDIA_ERR_LOG("HCameraService::CreateCaptureSession streamOperatorCallback_ allocation failed");
            return CAMERA_ALLOC_ERROR;
        }
    }


    std::lock_guard lock(mutex_);
    OHOS::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
    captureSession = new(std::nothrow) HCaptureSession(cameraHostManager_, streamOperatorCallback_, callerToken);
    if (captureSession == nullptr) {
        MEDIA_ERR_LOG("HCameraService::CreateCaptureSession HCaptureSession allocation failed");
        return CAMERA_ALLOC_ERROR;
    }
    session = captureSession;
    return CAMERA_OK;
}
4. 开始配置采集会话调用CaptureSession的BeginConfig进行采集会话的配置工作。这个工作最终调用到被封装的HCaptureSession中。
int32_t HCaptureSession::BeginConfig()
{
    CAMERA_SYNC_TRACE;
    if (curState_ == CaptureSessionState::SESSION_CONFIG_INPROGRESS) {
        MEDIA_ERR_LOG("HCaptureSession::BeginConfig Already in config inprogress state!");
        return CAMERA_INVALID_STATE;
    }
    std::lock_guard lock(sessionLock_);
    prevState_ = curState_;
    curState_ = CaptureSessionState::SESSION_CONFIG_INPROGRESS;
    tempCameraDevices_.clear();
    tempStreams_.clear();
    deletedStreamIds_.clear();
    return CAMERA_OK;
}
5. 创建CameraInput应用层通过camManagerObj->CreateCameraInput(cameraObjList[0])的方式进行CameraInput的创建,cameraObjList[0]就是前面获取支持设备的第一个。根据CameraDevice创建对应的CameraInput对象。
sptr CameraManager::CreateCameraInput(sptr &camera)
{
    CAMERA_SYNC_TRACE;
    sptr cameraInput = nullptr;
    sptr deviceObj = nullptr;


    if (camera != nullptr) {
        deviceObj = CreateCameraDevice(camera->GetID());
        if (deviceObj != nullptr) {
            cameraInput = new(std::nothrow) CameraInput(deviceObj, camera);
            if (cameraInput == nullptr) {
                MEDIA_ERR_LOG("failed to new CameraInput Returning null in CreateCameraInput");
                return cameraInput;
            }
        } else {
            MEDIA_ERR_LOG("Returning null in CreateCameraInput");
        }
    } else {
        MEDIA_ERR_LOG("CameraManager: Camera object is null");
    }
    return cameraInput;
}
6. 开启CameraInput调用了CameraInput的Open方法,进行输入设备的启动打开。
void CameraInput::Open()
{
    int32_t retCode = deviceObj_->Open();
    if (retCode != CAMERA_OK) {
        MEDIA_ERR_LOG("Failed to open Camera Input, retCode: %{public}d", retCode);
    }
}
7. 添加CameraInput实例到采集会话中通过调用captureSession的AddInput方法,将创建的CameraInput对象添加到采集会话的输入中,这样采集会话就知道采集输入的设备。
int32_t CaptureSession::AddInput(sptr &input)
{
    CAMERA_SYNC_TRACE;
    if (input == nullptr) {
        MEDIA_ERR_LOG("CaptureSession::AddInput input is null");
        return CAMERA_INVALID_ARG;
    }
    input->SetSession(this);
    inputDevice_ = input;
    return captureSession_->AddInput(((sptr &)input)->GetCameraDevice());
}
最终调用到HCaptureSession的AddInput方法,该方法中核心的代码是tempCameraDevices_.emplace_back(localCameraDevice),将需要添加的CameraDevice插入到tempCameraDevices_容器中。
int32_t HCaptureSession::AddInput(sptr cameraDevice)
{
    CAMERA_SYNC_TRACE;
    sptr localCameraDevice = nullptr;


    if (cameraDevice == nullptr) {
        MEDIA_ERR_LOG("HCaptureSession::AddInput cameraDevice is null");
        return CAMERA_INVALID_ARG;
    }
    if (curState_ != CaptureSessionState::SESSION_CONFIG_INPROGRESS) {
        MEDIA_ERR_LOG("HCaptureSession::AddInput Need to call BeginConfig before adding input");
        return CAMERA_INVALID_STATE;
    }
    if (!tempCameraDevices_.empty() || (cameraDevice_ != nullptr && !cameraDevice_->IsReleaseCameraDevice())) {
        MEDIA_ERR_LOG("HCaptureSession::AddInput Only one input is supported");
        return CAMERA_INVALID_SESSION_CFG;
    }
    localCameraDevice = static_cast(cameraDevice.GetRefPtr());*>
    if (cameraDevice_ == localCameraDevice) {
        cameraDevice_->SetReleaseCameraDevice(false);
    } else {
        tempCameraDevices_.emplace_back(localCameraDevice);
        CAMERA_SYSEVENT_STATISTIC(CreateMsg("CaptureSession::AddInput"));
    }


    sptr streamOperator;
    int32_t rc = localCameraDevice->GetStreamOperator(streamOperatorCallback_, streamOperator);
    if (rc != CAMERA_OK) {
        MEDIA_ERR_LOG("HCaptureSession::GetCameraDevice GetStreamOperator returned %{public}d", rc);
        localCameraDevice->Close();
        return rc;
    }
    return CAMERA_OK;
}
8. 创建Video的Surface通过Surface::CreateSurfaceAsConsumer创建Surface。
sptr Surface::string name, bool isShared)
{
    sptr surf = new ConsumerSurface(name, isShared);
    GSError ret = surf->Init();
    if (ret != GSERROR_OK) {
        BLOGE("Failure, Reason: consumer surf init failed");
        return nullptr;
    }
    return surf;
}
9. 创建VideoOutput实例通过调用CameraManager的CreateVideoOutput来创建VideoOutput实例。
sptr CameraManager::CreateVideoOutput(VideoProfile &profile, sptr &surface)
{
    CAMERA_SYNC_TRACE;
    sptr streamRepeat = nullptr;
    sptr result = nullptr;
    int32_t retCode = CAMERA_OK;
    camera_format_t metaFormat;


    metaFormat = GetCameraMetadataFormat(profile.GetCameraFormat());
    retCode = serviceProxy_->CreateVideoOutput(surface->GetProducer(), metaFormat,
                                               profile.GetSize().width, profile.GetSize().height, streamRepeat);
    if (retCode == CAMERA_OK) {
        result = new(std::nothrow) VideoOutput(streamRepeat);
        if (result == nullptr) {
            MEDIA_ERR_LOG("Failed to new VideoOutput");
        } else {
            std::vector videoFrameRates = profile.GetFrameRates();
            if (videoFrameRates.size() >= 2) { // vaild frame rate range length is 2
                result->SetFrameRateRange(videoFrameRates[0], videoFrameRates[1]);
            }
            POWERMGR_SYSEVENT_CAMERA_CONFIG(VIDEO,
                                            profile.GetSize().width,
                                            profile.GetSize().height);
        }
    } else {
        MEDIA_ERR_LOG("VideoOutpout: Failed to get stream repeat object from hcamera service! %{public}d", retCode);
    }
    return result;
}
该方法中通过IPC的调用最终调用到了HCameraService的CreateVideoOutput(surface->GetProducer(), format, streamRepeat)。
int32_t HCameraService::CreateVideoOutput(const sptr &producer, int32_t format,
                                          int32_t width, int32_t height,
                                          sptr &videoOutput)
{
    CAMERA_SYNC_TRACE;
    sptr streamRepeatVideo;


    if ((producer == nullptr) || (width == 0) || (height == 0)) {
        MEDIA_ERR_LOG("HCameraService::CreateVideoOutput producer is null");
        return CAMERA_INVALID_ARG;
    }
    streamRepeatVideo = new(std::nothrow) HStreamRepeat(producer, format, width, height, true);
    if (streamRepeatVideo == nullptr) {
        MEDIA_ERR_LOG("HCameraService::CreateVideoOutput HStreamRepeat allocation failed");
        return CAMERA_ALLOC_ERROR;
    }
    POWERMGR_SYSEVENT_CAMERA_CONFIG(VIDEO, producer->GetDefaultWidth(),
                                    producer->GetDefaultHeight());
    videoOutput = streamRepeatVideo;
    return CAMERA_OK;
}
HCameraService的CreateVideoOutput方法中主要创建了HStreamRepeat,并且通过参数传递给前面的CameraManager使用,CameraManager通过传递的HStreamRepeat对象,进行封装,创建出VideoOutput对象。 10. 添加videoOutput到采集会话中,并且提交采集会话该步骤类似添加CameraInput到采集会话的过程,可以参考前面的流程。 11. 开始录制通过调用VideoOutput的Start进行录制的操作。
int32_t VideoOutput::Start()
{
    return static_cast(GetStream().GetRefPtr())->Start();
}
该方法中会调用到HStreamRepeat的Start方法。
int32_t HStreamRepeat::Start()
{
    CAMERA_SYNC_TRACE;


    if (streamOperator_ == nullptr) {
        return CAMERA_INVALID_STATE;
    }
    if (curCaptureID_ != 0) {
        MEDIA_ERR_LOG("HStreamRepeat::Start, Already started with captureID: %{public}d", curCaptureID_);
        return CAMERA_INVALID_STATE;
    }
    int32_t ret = AllocateCaptureId(curCaptureID_);
    if (ret != CAMERA_OK) {
        MEDIA_ERR_LOG("HStreamRepeat::Start Failed to allocate a captureId");
        return ret;
    }
    std::vector ability;
    OHOS::ConvertMetadataToVec(cameraAbility_, ability);
    CaptureInfo captureInfo;
    captureInfo.streamIds_ = {streamId_};
    captureInfo.captureSetting_ = ability;
    captureInfo.enableShutterCallback_ = false;
    MEDIA_INFO_LOG("HStreamRepeat::Start Starting with capture ID: %{public}d", curCaptureID_);
    CamRetCode rc = (CamRetCode)(streamOperator_->Capture(curCaptureID_, captureInfo, true));
    if (rc != HDI::NO_ERROR) {
        ReleaseCaptureId(curCaptureID_);
        curCaptureID_ = 0;
        MEDIA_ERR_LOG("HStreamRepeat::Start Failed with error Code:%{public}d", rc);
        ret = HdiToServiceError(rc);
    }
    return ret;
}
核心的代码是streamOperator_->Capture,其中最后一个参数true,表示采集连续数据。 12. 录制结束,保存录制文件

六、总结

本文主要对OpenHarmony 3.2 Beta多媒体子系统的视频录制进行介绍,首先梳理了整体的录制流程,然后对录制过程中的主要步骤进行了详细地分析。视频录制主要分为以下几个步骤:(1) 获取CameraManager实例。(2) 创建采集会话CaptureSession。(3) 创建CameraInput实例,并且将输入设备添加到CaptureSession中。(4) 创建Video录制需要的Surface。(5) 创建VideoOutput实例,并且将输出添加到CaptureSession中。(6) 提交采集会话的配置。(7) 调用VideoOutput的Start方法,进行视频的录制。(8) 录制结束,保存录制的文件。 关于OpenHarmony 3.2 Beta多媒体系列开发,我之前还分享过《OpenHarmony 3.2 Beta源码分析之MediaLibrary》《OpenHarmony 3.2 Beta多媒体系列——音视频播放框架》《OpenHarmony 3.2 Beta多媒体系列——音视频播放gstreamer》这几篇文章,欢迎感兴趣的开发者进行阅读。

THE END

推荐阅读

点击图片即可阅读

caaae64c-a8f1-11ed-bfe3-dac502259ad0.png

关注深开鸿

了解更多资讯

cae54468-a8f1-11ed-bfe3-dac502259ad0.jpg

深开鸿公众号

cb10541e-a8f1-11ed-bfe3-dac502259ad0.jpg

深开鸿视频号

深圳开鸿数字产业发展有限公司(简称“深开鸿”)于2021年成立于中国深圳,以数字化、智慧化改变人类的生产和生活方式为愿景,专注于自主软件根技术的研发与持续创新,致力于打造万物智联核心技术、定义万物智联标准、引领万物智联时代发展。

深开鸿基于OpenHarmony,创新打造互通互联互享的KaihongOS数字底座,上承可视可管可控的超级设备管理平台,灵活扩展,柔性组合,聚合成全场景超级设备解决方案,实现更大范围的以软件定义硬件,引领智慧基建、智慧康养、智慧能源、智慧交通、智慧制造、智慧政务、智慧金融、智慧教育等多个行业变革,赋能、赋智、赋值千行百业的数智化转型。

从开源中来,到行业中去,深开鸿以构筑行业数字化生态、培养生态人才为己任,持续突破行业边界,立志成为万物智联时代的“国之重器”。

以数字化、智慧化改变人类的生产和生活方式

点击在看和点赞,与更多的美好相遇 ↓


原文标题:OpenHarmony 3.2 Beta多媒体系列——视频录制

文章出处:【微信公众号:深开鸿】欢迎添加关注!文章转载请注明出处。


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 深开鸿
    +关注

    关注

    1

    文章

    325

    浏览量

    2165

原文标题:OpenHarmony 3.2 Beta多媒体系列——视频录制

文章出处:【微信号:gh_15d2f062a168,微信公众号:深开鸿】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    安谋科技自研“玲珑”多媒体家族再添新军,加速超高清显示和端边云视频应用落地

    9月19日,安谋科技在北京召开新品发布媒体沟通会,正式亮出本土自研多媒体产品矩阵的最新力作——首款“玲珑”D8/D6/D2显示处理器和新一代的“玲珑”V510/V710视频处理器,为当前终端市场超高画质显示、超高清
    的头像 发表于 09-25 15:00 2858次阅读
    安谋科技自研“玲珑”<b class='flag-5'>多媒体</b>家族再添新军,加速超高清显示和端边云<b class='flag-5'>视频</b>应用落地

    基于ArkTS语言的OpenHarmony APP应用开发:多媒体管理2

    视频开始播放。再次点击视频进入视频全屏页。首页下滑500vp后,视频小窗口化。4.点击直播按钮进入直播页,上下滑动视频。本案例已在
    的头像 发表于 09-21 08:06 243次阅读
    基于ArkTS语言的<b class='flag-5'>OpenHarmony</b> APP应用开发:<b class='flag-5'>多媒体</b>管理2

    基于ArkTS语言的OpenHarmony APP应用开发:多媒体管理2

    播放按钮,视频开始播放。再次点击视频进入视频全屏页。 首页下滑500vp后,视频小窗口化。 4.点击直播按钮进入直播页,上下滑动视频。 本案
    发表于 09-20 13:47

    基于ArkTS语言的OpenHarmony APP应用开发:多媒体管理

    1、程序介绍 本示例展示了视频组件的基本功能,以及如何控制播放状态的相关能力,包括视频切换、封面切换、播放、暂停等。 本案例已在OpenHarmony凌蒙派-RK3568开发板验证通过,具体代码可
    发表于 09-19 15:50

    AM62A上的多媒体应用

    电子发烧友网站提供《AM62A上的多媒体应用.pdf》资料免费下载
    发表于 08-29 11:52 0次下载
    AM62A上的<b class='flag-5'>多媒体</b>应用

    请问STM32F7系列可以录制视频吗?分辨率多少的?

    网上几乎没人用STM32的芯片来做录制视频的,请教一下各位高手STM32F7系列可以用做录制视频吗?
    发表于 05-09 06:06

    鸿蒙媒体开发【简述】

    录制)、图片等。 如下图所示,媒体系统面向应用开发提供音视频应用、图库应用的编程框架接口;面向设备开发提供对接不同硬件芯片适配加速功能;中间以服务形态提供媒体核心功能和管理机制。 音
    发表于 02-28 17:53

    OpenHarmony4.0源码解析之媒体框架

    媒体框架简介 媒体框架 multimedia_player_framework 主要提供音视频录制与播放功能。 框架简介 从框架图中可以看出,媒体
    的头像 发表于 02-26 22:05 755次阅读
    <b class='flag-5'>OpenHarmony</b>4.0源码解析之<b class='flag-5'>媒体</b>框架

    视频解码生成在多媒体制作中的应用

    视频解码生成是多媒体制作中不可或缺的一部分,它扮演着将编码的音视频数据转化为可播放、可编辑的内容的关键角色。在多媒体制作的全过程中,音视频
    的头像 发表于 02-21 14:39 349次阅读

    万兴科技发布国内首个音视频多媒体大模型“天幕”

    万兴科技近日正式发布了国内首个音视频多媒体大模型——万兴“天幕”,并宣布大模型研发中心将正式落户马栏山。
    的头像 发表于 02-04 11:42 1244次阅读

    LED大屏幕处理器与多媒体内容的兼容性和互动性

    LED大屏幕处理器与多媒体内容的兼容性和互动性是其重要特性之一。以下是对这一特性的详细解释:   兼容性:LED大屏幕处理器需要能够接收和处理各种多媒体内容,如视频、图片、动画等。为了实现这一
    的头像 发表于 01-25 14:39 713次阅读

    揭秘讯维多媒体中央控制系统的核心优势

    随着科技的发展,多媒体设备在各个领域中的应用越来越广泛。而多媒体中央控制系统作为其核心组成部分,在实现设备的集中控制和管理方面具有显著的优势。本文将深入揭秘多媒体中央控制系统的核心优势,帮助您更好
    的头像 发表于 01-23 14:58 698次阅读

    多媒体触摸查询系统-终端说明书

    电子发烧友网站提供《多媒体触摸查询系统-终端说明书.docx》资料免费下载
    发表于 01-17 16:36 0次下载

    多媒体一体机为什么推荐用工业级连接器

    多媒体一体机在办公、培训、教学等场景中覆盖面非常广,它告别了手写的低效与繁琐,带来了智能交互新体验。如何保障多媒体一体机在长期以及任何场合上的可靠电源传输连接是一项非常重要的工作。LP系列连接器为
    的头像 发表于 01-17 08:13 351次阅读
    <b class='flag-5'>多媒体</b>一体机为什么推荐用工业级连接器

    搭载KaihongOS的高动态人形机器人“夸父”通过OpenHarmony3.2 Release版本兼容性测评

      近日,搭载KaihongOS的国内首款可跳跃、可适应多地形行走的开源鸿蒙人形机器人通过OpenAtom OpenHarmony(以下简称“OpenHarmony”)3.2 Release版本
    的头像 发表于 12-07 18:15 523次阅读