Android NuPlayer播放框架

电脑杂谈  发布时间:2020-07-04 23:03:13  来源:网络整理

android 缓存框架_android 音频播放框架_android 音频框架

[时间: 2016-09] [状态: 打开]

[关键字: android,nuplayer,开源播放器,播放框架,nuplayerdriver]

0 NuPlayer简介

流媒体框架是Android 2.3中引入的,流媒体框架的核心是NuPlayer. 在以前的版本中,通常认为本地播放使用Stagefrightplayer + Awesomeplayer和NuPlayer进行流式传输. 在Android4.0之后,HttpLive和RTSP协议开始使用NuPlayer播放器,而在Android5.0(L版本)之后,本地播放器也开始使用NuPlayer播放器. Android 7.0(N版)完全删除了Awesomeplayer.

用外行的话来说,NuPlayer是AOSP中提供的多媒体播放框架,它可以支持本地文件,HTTP(HLS),RTSP和其他协议的播放,通常支持H.264android 音频播放框架,H.265 / HEVC,AAC编码格式,支持MP4,MPEG-TS包.

在实现方面,NuPlayer与Awesomeplayer不同. NuPlayer基于StagefrightPlayer的基本类. 它使用较低级别的ALooper / AHandler机制来异步处理请求. ALooper将消息请求排队. AHandler处理它们,因此NuPlayer中的Mutex / Lock更少. Awesomeplayer使用omxcodec,NuPlayer使用Acodec.

1个NuPlayer框架

下图是NuPlayer的总体框架

nuplayer arch

或以下图片

nuplayer class diagram

Android层的多媒体框架具有多层实现,甚至跨进程调用. 在这里,我们重点介绍NuPlayerDriver之后的实现和相关逻辑. 至于上层的调用逻辑,建议参考其他材料.

android 音频播放框架_android 音频框架_android 缓存框架

每个部分的功能如下:

2如何通过NuPlayer播放多媒体文件

在AOSP中,多媒体文件或URL通常称为数据源. 通常,多媒体文件包含至少一个音频流,视频流或字幕流. NuPlayer将这三个称为Track,并且在细分下有AudioTrack,VideoTrack和SubtitleTrack. 解析多媒体文件后,可以将其还原为原始数据,然后进行渲染. 具体过程参考下图:

multimedia-file-play-proc

DataSource有两个概念:

VideoTrack和AudioTrack是指提取器(多路分配器)的两个通道,此处的输出只是简单地多路分解的视频和音频流. 之后的输出是音频和视频的输出:

关于Android应用程序层如何调用MediaPlayerandroid 音频播放框架,建议参考我以前的文章MediaPlayer Interface&State.

3我个人的AOSP源代码分析方法

鉴于AOSP是一个操作系统,整个过程更加复杂. 从实际的角度来看,您可以专注于某个点. 例如,我在这里主要关注NuPlayer框架及其内部实现逻辑. 最后,如何从类中提取所需的框架和知识点. 然后,类的外部接口部分通常包括:

在多媒体播放中,关注点是:

4 NuPlayer接口实现分析(NuPlayerDriver)

NuPlayer框架中最顶层的类是NuPlayerDriver,它继承自MediaPlayerInterface,并且主要提供状态转换机制作为NuPlayer类的包装器. NuPlayerDriver类的最重要的成员如下:

android 音频播放框架_android 音频框架_android 缓存框架

首先解释一下,我参考的是Android 7的源代码,即NuPlayerDriver.cpp(目录: ./frameworks/av/media/libmediaplayerservice/nuplayer /)

4.1构造函数和析构函数

从代码中可以看到,构造函数的主要功能是创建ALooper和NuPlayer实例并将它们关联.

mLooper = (new ALooper);
mLooper->start(
        false, /* runOnCallingThread */
        true,  /* canCallJava */
        PRIORITY_AUDIO);
mPlayer = new NuPlayer(pid);
mLooper->registerHandler(mPlayer);
mPlayer->setDriver(this);

析构函数主要是销毁创建的ALooper和NuPlayer. 由于它是一个智能指针,因此只需停止即可.

mLooper->stop();

4.2 SetDataSource

此接口的实现非常简单,检查当前的播放状态,然后直接调用NuPlayer :: setDataSourceAsync函数.

status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
    ALOGV("setDataSource(%p) file(%d)", this, fd);
    Mutex::Autolock autoLock(mLock);
    if (mState != STATE_IDLE) {
        return INVALID_OPERATION;
    }
    mState = STATE_SET_DATASOURCE_PENDING;
    mPlayer->setDataSourceAsync(fd, offset, length);
    while (mState == STATE_SET_DATASOURCE_PENDING) {
        mCondition.wait(mLock);
    }
    return mAsyncResult;
}

最后等待函数返回并调用NuPlayerDriver :: notifySetDataSourceCompleted接口以更改播放器状态.

4.3 setVideoSurfaceTexture

此接口的实现思路与SetDataSource相同,但调用了NuPlayer :: setVideoSurfaceTextureAsync,并在处理请求后调用了NuPlayerDriver :: notifySetSurfaceComplete接口.

android 缓存框架_android 音频框架_android 音频播放框架

4.4 prepare / prepareAsync

这两个接口的基本功能是相同的,但是第二个是异步调用过程. 第一个是通过prepare_l接口实现的,两个接口最终都调​​用NuPlayer :: prepareAsync,并在请求处理完成后调用NuPlayerDriver :: notifyPrepareCompleted接口. 但是,有很多代码可用来判断播放状态. 例如,prepareAsync

中的代码

ALOGV("prepareAsync(%p)", this);
Mutex::Autolock autoLock(mLock);
switch (mState) {
    case STATE_UNPREPARED:
        mState = STATE_PREPARING;
        mIsAsyncPrepare = true;
        mPlayer->prepareAsync();
        return OK;
    case STATE_STOPPED:
        // this is really just paused. handle as seek to start
        mAtEOS = false;
        mState = STATE_STOPPED_AND_PREPARING;
        mIsAsyncPrepare = true;
        mPlayer->seekToAsync(0, true /* needNotify */);
        return OK;
    default:
        return INVALID_OPERATION;
};

4.5开始/停止

这两个功能用作开始和停止播放的界面,主要涉及播放器内部状态的切换和判断. 最终功能是通过调用NuPlayer :: start和NuPlayer :: pause接口来实现的.

以下是启动函数实现代码(start_l),主要需要判断处于不同状态的调用逻辑:

switch (mState) {
    case STATE_UNPREPARED:
    {
        status_t err = prepare_l();
        if (err != OK) {
            return err;
        }
        CHECK_EQ(mState, STATE_PREPARED);
        // fall through
    }
    case STATE_PAUSED:
    case STATE_STOPPED_AND_PREPARED:
    case STATE_PREPARED:
    {
        mPlayer->start();
        // fall through
    }
    case STATE_RUNNING:
    {
        if (mAtEOS) {
            mPlayer->seekToAsync(0);
            mAtEOS = false;
            mPositionUs = -1;
        }
        break;
    }

    default:
        return INVALID_OPERATION;
}
mState = STATE_RUNNING;

stop接口的实现相对简单,主要是确定可以调用stop接口的状态并报告MEDIA_STOPPED状态. 代码如下:

switch (mState) {
    case STATE_RUNNING:
        mPlayer->pause();
        // fall through
    case STATE_PAUSED:
        mState = STATE_STOPPED;
        notifyListener_l(MEDIA_STOPPED);
        break;
    case STATE_PREPARED:
    case STATE_STOPPED:
    case STATE_STOPPED_AND_PREPARING:
    case STATE_STOPPED_AND_PREPARED:
        mState = STATE_STOPPED;
        break;

    default:
        return INVALID_OPERATION;
}

4.6暂停/重置

pause用于实现暂停,其实现比较简单,直接调用NuPlayer :: puase即可实现,代码如下:

android 音频框架_android 音频播放框架_android 缓存框架

switch (mState) {
    case STATE_PAUSED:
    case STATE_PREPARED:
        return OK;
    case STATE_RUNNING:
        mState = STATE_PAUSED;
        notifyListener_l(MEDIA_PAUSED);
        mPlayer->pause();
        break;

    default:
        return INVALID_OPERATION;
}

reset重置播放器,这是一个同步调用界面. 通过调用NuPlayer :: resetAsync接口,然后调用NuPlayerDriver :: notifyResetComplete来通知最终的实现.

4.7 isPlaying / getDuration / getCurrentPosition

这些界面主要用于获取播放器的状态.

isPlaying由玩家状态直接判断,其实现如下:

bool NuPlayerDriver::isPlaying() {
    return mState == STATE_RUNNING && !mAtEOS;
}

getDuration的实现相对简单,代码如下. 但是,具体获得的mDurationUs需要通过NuPlayer报告或定期更新.

status_t NuPlayerDriver::getDuration(int *msec) {
    Mutex::Autolock autoLock(mLock);
    if (mDurationUs < 0) {
        return UNKNOWN_ERROR;
    }
    *msec = (mDurationUs + 500ll) / 1000;
    return OK;
}

getCurrentPosition是通过调用NuPlayer :: getCurrentPosition获得的.

4.8 getMetadata

此界面主要用于判断播放器的属性,例如是否支持暂停,搜索,向前搜索,向后搜索等.

5后续详细分析

本文主要分析NuPlayerDriver的接口实现. 以下分析部分包括:

总而言之,NuPlayerDriver主要是接口层的连接,并在播放器内部记录状态数据以确保其符合Android MediaPlayer状态调用逻辑. 代码相对简单.

参考NuPlayer引入了用于HTTP实时流传输的NuPlayerStagefright视频播放过程


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/bofangqi/article-268667-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      • 帕里
        帕里

        男女比例失调正常因为重男轻女

      热点图片
      拼命载入中...