鸿蒙系统中VideoDecoder解码到Surface的实践与探索

引言

在鸿蒙系统的开发过程中,我遇到了一个关于视频解码的挑战:如何将VideoDecoder解码后的数据正确地渲染到绑定了纹理的OHNativeWindow上。这个问题不仅涉及到视频解码的基础知识,还牵涉到鸿蒙系统特有的API使用。通过一系列的实践和调试,我逐步解决了这个问题,并在此分享我的经验和解决方案。

问题描述

最初,我尝试使用鸿蒙系统的VideoDecoder进行视频解码,并希望将解码后的数据直接渲染到通过纹理ID创建的OHNativeWindow上。然而,在实际操作中,我发现尽管设置了OHNativeWindow到解码器,并注册了OH_NativeImage_SetOnFrameAvailableListener,但并没有收到预期的OH_OnFrameAvailableListener回调。

解决方案探索

面对这个问题,我首先查阅了鸿蒙系统的官方文档和相关API说明,确保我的使用方法没有错误。随后,我开始逐步排查可能的问题点:

  1. 解码器配置检查:确认VideoDecoder的配置是否正确,包括输入格式、输出格式等。
  2. 纹理绑定验证:检查OHNativeWindow与纹理的绑定是否正确无误。
  3. 回调机制测试:验证OH_NativeImage_SetOnFrameAvailableListener的注册和回调逻辑。

在多次尝试和调试后,我发现问题出在解码器的输出设置上。原来,我需要在创建解码器之前,先设置好输出Surface的像素格式。通过调用OH_AVFormat_SetIntValue(mCodecFormat, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_SURFACE_FORMAT);确保了像素格式的正确设置。

实施步骤
  1. 设置像素格式:在创建解码器之前,通过上述API设置正确的像素格式。
  2. 设置输出Surface:在解码器的配置阶段,使用OH_VideoDecoder_SetSurface(mDecoder, window.get());将OHNativeWindow设置为解码器的输出Surface。
  3. 注册回调:在解码器启动后,注册OH_NativeImage_SetOnFrameAvailableListener,以便接收解码后的帧数据。
结果验证

经过上述步骤的调整,我重新运行了程序,并成功接收到了OH_OnFrameAvailableListener的回调,视频数据也正确地渲染到了OHNativeWindow上。这表明,通过正确配置解码器的输出设置,可以有效地解决视频解码到纹理绑定窗口的问题。

结论

通过这次经历,我深刻理解了在鸿蒙系统中进行视频解码时,正确配置解码器输出设置的重要性。这不仅涉及到基础的API调用,还需要对视频解码的整个流程有深入的理解。希望我的经验能帮助到同样在使用鸿蒙系统进行开发的同行们,共同推动鸿蒙生态的发展。

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在多线程解码网络视频数据,可以使用Qt的QThread类来实现。具体步骤如下: 1. 创建一个QThread对象,并将其moveToThread()到一个新线程。 2. 在新线程创建一个QMediaPlayer对象,用于解码网络视频数据。 3. 将QMediaPlayer对象的setMedia()方法设置为网络视频数据的URL。 4. 在QMediaPlayer对象的stateChanged()信号,判断状态是否为QMediaPlayer::LoadedMedia,如果是则调用QMediaPlayer对象的play()方法开始播放视频数据。 5. 在QMediaPlayer对象的videoOutputChanged()信号,获取QVideoWidget对象,设置其作为QMediaPlayer的视频输出,并将其添加到QWidget。 6. 在新线程启动QCoreApplication::exec()方法,等待事件循环。 具体代码实现如下: ```cpp class VideoDecoder : public QObject { Q_OBJECT public: explicit VideoDecoder(QObject *parent = nullptr) : QObject(parent) {} public slots: void decodeVideo(const QString &url) { QMediaPlayer *player = new QMediaPlayer; QVideoWidget *videoWidget = new QVideoWidget; player->setMedia(QUrl(url)); player->setVideoOutput(videoWidget); connect(player, &QMediaPlayer::stateChanged, this, [player]() { if (player->state() == QMediaPlayer::LoadedMedia) { player->play(); } }); connect(player, &QMediaPlayer::videoOutputChanged, this, [videoWidget](QVideoWidget *vw) { videoWidget = vw; videoWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); videoWidget->setStyleSheet("background-color:black;"); videoWidget->show(); }); QThread *thread = new QThread; connect(thread, &QThread::started, player, &QMediaPlayer::play); connect(thread, &QThread::finished, player, &QMediaPlayer::stop); connect(thread, &QThread::finished, thread, &QThread::deleteLater); connect(thread, &QThread::destroyed, player, &QMediaPlayer::deleteLater); player->moveToThread(thread); thread->start(); QCoreApplication::exec(); } }; ``` 在主线程,创建VideoDecoder对象,调用其decodeVideo()方法,传入网络视频数据的URL即可在新线程解码网络视频数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鸿蒙开发助手

赏钱一扔,代码超神,事业飞腾

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值