博客
关于我
【六】Android MediaPlayer整体架构源码分析 -【start请求播放处理流程】【Part 2】
阅读量:673 次
发布时间:2019-03-15

本文共 7558 字,大约阅读时间需要 25 分钟。

Android 10.0 系统中媒体播放器(NuPlayer)的音频解码与渲染实现分析

5. canOffloadStream 函数实现分析

5.1 mSource->isStreaming() 实现

mSource->isStreaming() 方法返回的是 mIsStreaming 是否是网络数据源流媒体数据源标识值。非网络数据源时返回 false。

// [frameworks/av/media/libmediaplayerservice/nuplayer/GenericSource.cpp]bool NuPlayer::GenericSource::isStreaming() const {    Mutex::Autolock _l(mLock);    return mIsStreaming;}

5.2 canOffloadStream 方法实现

canOffloadStream 方法用于检查是否可以通过硬解码器解码并播放音频流。其实现逻辑如下:

// [frameworks/av/media/libstagefright/Utils.cpp]bool canOffloadStream(const sp
& meta, bool hasVideo, bool isStreaming, audio_stream_type_t streamType) { audio_offload_info_t info = AUDIO_INFO_INITIALIZER; if (OK != getAudioOffloadInfo(meta, hasVideo, isStreaming, streamType, &info)) { return false; } return AudioSystem::isOffloadSupported(info);}

5.3 audio_offload_info_t 定义与默认值

audio_offload_info_t 结构体定义在 system/media/audio/include/system/audio.h 文件中,主要用于存储音频解码和播放所需的配置信息。

// [system/media/audio/include/system/audio.h]typedef struct {    uint16_t version;    uint16_t size;    uint32_t sample_rate;    audio_channel_mask_t channel_mask;    audio_format_t format;    audio_stream_type_t stream_type;    uint32_t bit_rate;    int64_t duration_us;    bool has_video;    bool is_streaming;    uint32_t bit_width;    uint32_t offload_buffer_size;    audio_usage_t usage;} __attribute__((aligned(8))) audio_offload_info_t;#define AUDIO_INFO_INITIALIZER {    /* .version = */ AUDIO_OFFLOAD_INFO_VERSION_0_1,    /* .size = */ sizeof(audio_offload_info_t),    /* .sample_rate = */ 0,    /* .channel_mask = */ 0,    /* .format = */ AUDIO_FORMAT_DEFAULT,    /* .stream_type = */ AUDIO_STREAM_VOICE_CALL,    /* .bit_rate = */ 0,    /* .duration_us = */ 0,    /* .has_video = */ false,    /* .is_streaming = */ false,    /* .bit_width = */ 16,    /* .offload_buffer_size = */ 0,    /* .usage = */ AUDIO_USAGE_UNKNOWN};

5.4 getAudioOffloadInfo 方法实现

getAudioOffloadInfo 方法用于获取音频解码和播放所需的详细信息,主要包括 MIME 类型到音频格式的映射、AAC 配置级别的处理以及音频通道的配置。

// [frameworks/av/media/libstagefright/Utils.cpp]status_t getAudioOffloadInfo(const sp
& meta, bool hasVideo, bool isStreaming, audio_stream_type_t streamType, audio_offload_info_t* info) { const char* mime; if (meta == NULL) { return BAD_VALUE; } CHECK(meta->findCString(kKeyMIMEType, &mime)); *info = AUDIO_INFO_INITIALIZER; info->format = AUDIO_FORMAT_INVALID; if (mapMimeToAudioFormat(info->format, mime) != OK) { ALOGE("Couldn't map mime type \"%s\" to a valid AudioSystem::audio_format !", mime); return BAD_VALUE; } else { ALOGV("Mime type \"%s\" mapped to audio_format %d", mime, info->format); } if (AVUtils::get()->canOffloadStream(meta) != true) { return false; } int32_t aacaot = -1; if (meta->findInt32(kKeyAACAOT, &aacaot)) { bool isADTSSupported = false; if (!__NO_AVEXTENSIONS__) { isADTSSupported = AVUtils::get()->mapAACProfileToAudioFormat(meta, info->format, (OMX_AUDIO_AACPROFILETYPE) aacaot); } if (!isADTSSupported) { mapAACProfileToAudioFormat(info->format, (OMX_AUDIO_AACPROFILETYPE) aacaot); } } int32_t srate = -1; if (!meta->findInt32(kKeySampleRate, &srate)) { ALOGV("track of type '%s' does not publish sample rate", mime); } info->sample_rate = srate; int32_t cmask = 0; if (!meta->findInt32(kKeyChannelMask, &cmask) || cmask == CHANNEL_MASK_USE_CHANNEL_ORDER) { ALOGV("track of type '%s' does not publish channel mask", mime); int32_t channelCount; if (!meta->findInt32(kKeyChannelCount, &channelCount)) { ALOGV("track of type '%s' does not publish channel count", mime); } else { cmask = audio_channel_out_mask_from_count(channelCount); } ALOGW("track of type '%s' does not publish channel mask, channel count %d", mime, channelCount); } info->channel_mask = cmask; int64_t duration = 0; if (!meta->findInt64(kKeyDuration, &duration)) { ALOGV("track of type '%s' does not publish duration", mime); } info->duration_us = duration; int32_t brate = -1; if (!meta->findInt32(kKeyBitRate, &brate)) { ALOGV("track of type '%s' does not publish bitrate", mime); } info->bit_rate = brate; info->stream_type = streamType; info->has_video = hasVideo; info->is_streaming = isStreaming; return OK;}

5.5 mapMimeToAudioFormat 方法实现

mapMimeToAudioFormat 方法将 MIME 类型映射到对应的音频格式。

// [frameworks/av/media/libstagefright/Utils.cpp]status_t mapMimeToAudioFormat(audio_format_t* format, const char* mime) {    const struct mime_conv_t* p = &mimeLookup[0];    while (p->mime != NULL) {        if (0 == strcasecmp(mime, p->mime)) {            format = p->format;            return OK;        }        ++p;    }    if (!__NO_AVEXTENSIONS__) {        return AVUtils::get()->mapMimeToAudioFormat(format, mime);    }    return BAD_VALUE;}

5.6 AudioSystem::isOffloadSupported 方法实现

isOffloadSupported 方法检查系统是否支持音频解码的 offload 模式。

// [frameworks/av/media/libaudioclient/AudioSystem.cpp]bool AudioSystem::isOffloadSupported(const audio_offload_info_t* info) {    ALOGV("isOffloadSupported()");    const sp
&aps = AudioSystem::get_audio_policy_service(); if (aps == 0) return false; return aps->isOffloadSupported(info);}

6. NuPlayer::Renderer 类声明与构造函数实现

NuPlayer::Renderer 类声明了与消息处理相关的接口。

// [frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h]struct NuPlayer::Renderer : public AHandler {};

7. NuPlayer::Renderer 构造函数实现

NuPlayer::Renderer 的构造函数初始化各个成员变量,包括音频源、媒体时钟、通知对象等。

// [frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp]NuPlayer::Renderer::Renderer(const sp
& sink, const sp
& mediaClock, const sp
& notify, uint32_t flags) : mAudioSink(sink), mUseVirtualAudioSink(false), mNotify(notify), mFlags(flags), mNumFramesWritten(0), mDrainAudioQueuePending(false), mDrainVideoQueuePending(false), mAudioQueueGeneration(0), mVideoQueueGeneration(0), mAudioDrainGeneration(0), mVideoDrainGeneration(0), mAudioEOSGeneration(0), mMediaClock(mediaClock), mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT), mAudioFirstAnchorTimeMediaUs(-1), mAnchorTimeMediaUs(-1), mAnchorNumFramesWritten(-1), mVideoLateByUs(0LL), mNextVideoTimeMediaUs(-1), mHasAudio(false), mHasVideo(false), mNotifyCompleteAudio(false), mNotifyCompleteVideo(false), mSyncQueues(false), mPaused(false), mPauseDrainAudioAllowedUs(0), mVideoSampleReceived(false), mVideoRenderingStarted(false), mVideoRenderingStartGeneration(0), mAudioRenderingStartGeneration(0), mRenderingDataDelivered(false), mNextAudioClockUpdateTimeUs(-1), mLastAudioMediaTimeUs(-1), mAudioOffloadPauseTimeoutGeneration(0), mAudioTornDown(false), mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER), mCurrentPcmInfo(AUDIO_PCMINFO_INITIALIZER), mTotalBuffersQueued(0), mLastAudioBufferDrained(0), mUseAudioCallback(false), mWakeLock(new AWakeLock()), mNeedVideoClearAnchor(false) { CHECK(mediaClock != NULL); mPlaybackRate = mPlaybackSettings.mSpeed; mMediaClock->setPlaybackRate(mPlaybackRate);}

8. mCurrentPcmInfo (AUDIO_PCMINFO_INITIALIZER) 实现

AUDIO_PCMINFO_INITIALIZER 初始化 PCM 信息,用于音频解码。

// [frameworks/av/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h]static const NuPlayer::Renderer::PcmInfo NuPlayer::Renderer::AUDIO_PCMINFO_INITIALIZER = {    AUDIO_CHANNEL_NONE,    AUDIO_OUTPUT_FLAG_NONE,    AUDIO_FORMAT_INVALID,    0,    0};

通过以上分析,可以清晰地了解 Android 10.0 系统中媒体播放器的音频解码与渲染实现的关键逻辑和技术细节。

转载地址:http://qopmz.baihongyu.com/

你可能感兴趣的文章
Multisim中555定时器使用技巧
查看>>
MySQL CRUD 数据表基础操作实战
查看>>
multisim变压器反馈式_穿过隔离栅供电:认识隔离式直流/ 直流偏置电源
查看>>
mysql csv import meets charset
查看>>
multivariate_normal TypeError: ufunc ‘add‘ output (typecode ‘O‘) could not be coerced to provided……
查看>>
MySQL DBA 数据库优化策略
查看>>
multi_index_container
查看>>
mutiplemap 总结
查看>>
MySQL Error Handling in Stored Procedures---转载
查看>>
MVC 区域功能
查看>>
MySQL FEDERATED 提示
查看>>
mysql generic安装_MySQL 5.6 Generic Binary安装与配置_MySQL
查看>>
Mysql group by
查看>>
MySQL I 有福啦,窗口函数大大提高了取数的效率!
查看>>
mysql id自动增长 初始值 Mysql重置auto_increment初始值
查看>>
MySQL in 太多过慢的 3 种解决方案
查看>>
Mysql Innodb 锁机制
查看>>
MySQL InnoDB中意向锁的作用及原理探
查看>>
MySQL InnoDB事务隔离级别与锁机制深入解析
查看>>
Mysql InnoDB存储引擎 —— 数据页
查看>>