NuPlayer渲染和同步模块

简介: NuPlayer渲染和同步模块

NuPlayer的解码模块相对比较简单,统一使用了一个基类NuPlayerDecoderBase管理,该类中包含了一个MediaCodec的对象,实际解码工作全靠MediaCodec。


如果你不会知道MediaCodec是什么,推荐去官网看看:MediaCodec

那他的主要功能有哪些呢?


将音视频的原始数据缓存到队列

音频数据消耗播放

视频数据消耗显示

音视频同步

播放器控制

void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
    int32_t audio;
    CHECK(msg->findInt32("audio", &audio));
    if (dropBufferIfStale(audio, msg)) {
        return;
    }
    if (audio) {
        mHasAudio = true; //音频
    } else {
        mHasVideo = true; //视频
    }
    if (mHasVideo) {
        if (mVideoScheduler == NULL) {
            mVideoScheduler = new VideoFrameScheduler();  //视频渲染调整
           mVideoScheduler->init();
        }
    }
    sp<ABuffer> buffer;
    CHECK(msg->findBuffer("buffer", &buffer));
    sp<AMessage> notifyConsumed;
    CHECK(msg->findMessage("notifyConsumed", &notifyConsumed));
    QueueEntry entry;
    entry.mBuffer = buffer;
    entry.mNotifyConsumed = notifyConsumed;
    entry.mOffset = 0;
   entry.mFinalResult = OK;
   entry.mBufferOrdinal = ++mTotalBuffersQueued;
   if (audio) {
       Mutex::Autolock autoLock(mLock);
        mAudioQueue.push_back(entry);
        postDrainAudioQueue_l(); //刷新音频
    } else {
        mVideoQueue.push_back(entry);
       postDrainVideoQueue(); //刷新视频
   }
    Mutex::Autolock autoLock(mLock);
    if (!mSyncQueues || mAudioQueue.empty() || mVideoQueue.empty()) {
        return;
    }
    sp<ABuffer> firstAudioBuffer = (*mAudioQueue.begin()).mBuffer;
    sp<ABuffer> firstVideoBuffer = (*mVideoQueue.begin()).mBuffer;
    if (firstAudioBuffer == NULL || firstVideoBuffer == NULL) {
        // EOS signalled on either queue.
        syncQueuesDone_l();
        return;
    }
   int64_t firstAudioTimeUs;
    int64_t firstVideoTimeUs;
    CHECK(firstAudioBuffer->meta()
            ->findInt64("timeUs", &firstAudioTimeUs));
    CHECK(firstVideoBuffer->meta()
            ->findInt64("timeUs", &firstVideoTimeUs));
    int64_t diff = firstVideoTimeUs - firstAudioTimeUs;
    ALOGV("queueDiff = %.2f secs", diff / 1E6);
    if (diff > 100000ll) {
        // Audio data starts More than 0.1 secs before video.
       // Drop some audio.
       (*mAudioQueue.begin()).mNotifyConsumed->post();
       mAudioQueue.erase(mAudioQueue.begin());
        return;
    }
    syncQueuesDone_l();
}
目录
相关文章
|
机器学习/深度学习 人工智能 算法
机器学习笔试面试之图像数据不足时的处理方法、检验方法、不均衡样本集的重采样
机器学习笔试面试之图像数据不足时的处理方法、检验方法、不均衡样本集的重采样
411 0
|
监控 NoSQL MongoDB
MongoDB数据库的索引管理技巧
【8月更文挑战第20天】MongoDB数据库的索引管理技巧
259 1
|
11月前
|
人工智能 前端开发 Linux
github是怎么用的,如何下载仓库
github是怎么用的,如何下载仓库
|
12月前
|
编解码 前端开发 UED
网页设计中图标的重要性及其两种主要形式:传统网页图标与字体图标。传统图标视觉效果丰富但文件较大
本文探讨了网页设计中图标的重要性及其两种主要形式:传统网页图标与字体图标。传统图标视觉效果丰富但文件较大,字体图标体积小且易于维护,但视觉表现较简单。文章还介绍了它们的实际应用案例及使用时的注意事项,旨在帮助设计师根据项目需求选择合适的图标形式,提升网页的美观性和用户体验。
313 7
|
11月前
|
网络协议 程序员
为什么TCP需要三次握手?一文讲透!
TCP三次握手是TCP协议建立连接的关键步骤,确保客户端和服务端同步状态并确认彼此的存在。过程分为三步:1) 客户端发送SYN包请求连接;2) 服务端回应SYN/ACK包确认收到并提供初始序列号;3) 客户端发送ACK包确认服务端的序列号,双方进入连接状态。此机制确保了双向通信的可靠性和资源的有效利用,避免了失效请求导致的问题。
|
SQL Java Unix
Android经典面试题之Java中获取时间戳的方式有哪些?有什么区别?
在Java中获取时间戳有多种方式,包括`System.currentTimeMillis()`(毫秒级,适用于日志和计时)、`System.nanoTime()`(纳秒级,高精度计时)、`Instant.now().toEpochMilli()`(毫秒级,ISO-8601标准)和`Instant.now().getEpochSecond()`(秒级)。`Timestamp.valueOf(LocalDateTime.now()).getTime()`适用于数据库操作。选择方法取决于精度、用途和时间起点的需求。
301 3
|
运维 数据挖掘 OLAP
阿里云Hologres:一站式轻量级OLAP分析平台的全面评测
在数据驱动决策的今天,企业对高效、灵活的数据分析平台的需求日益增长。阿里云的Hologres,作为一站式实时数仓引擎,提供了强大的OLAP(在线分析处理)分析能力。本文将对Hologres进行深入评测,探讨其在多源集成、性能、易用性以及成本效益方面的表现。
537 8
|
SQL XML Java
Xml 映射文件中,除了常见的 select|insert|updae|delete 标签之外,还有哪些标签?
Xml 映射文件中,除了常见的 select|insert|updae|delete 标签之外,还有哪些标签?
307 0
|
定位技术
ArcMap:第一届全国大学生GIS技能大赛(滁州学院)详解-下午题2
ArcMap:第一届全国大学生GIS技能大赛(滁州学院)详解-下午题
444 0
|
数据采集 数据可视化 关系型数据库
【优秀python web设计】基于Python flask的猫眼电影可视化系统,可视化用echart,前端Layui,数据库用MySQL,包括爬虫
本文介绍了一个基于Python Flask框架、MySQL数据库和Layui前端框架的猫眼电影数据采集分析与可视化系统,该系统通过爬虫技术采集电影数据,利用数据分析库进行处理,并使用Echart进行数据的可视化展示,以提供全面、准确的电影市场分析结果。
529 4