目录
1. 处理解码之后的数据
(1) handleAnOutputBuffer
NuPlayerDecoder调用handleAnOutputBuffer处理解码之后的音视频数据. 函数最终会调用NuPlayerDecoderRenderer::queueBuffer处理这个Buffer
bool NuPlayer::Decoder::handleAnOutputBuffer(size_t index, size_t offset, size_t size,
int64_t timeUs, int32_t flags) {
sp<MediaCodecBuffer> buffer;
//根据Index从MediaCodec获取Buffer
mCodec->getOutputBuffer(index, &buffer);
mOutputBuffers.editItemAt(index) = buffer;
// 把offset size timeUs信息添加到buffer中
// 其中timeUs是buffer的媒体时间(Buffer在媒体文件的位置)
buffer->setRange(offset, size);
buffer->meta()->clear();
buffer->meta()->setInt64("timeUs", timeUs);
// 创建一个消息kWhatRenderBuffer, 消息会被传入到NuplayerRenderer,
// 当Buffer被Renderer处理完成后,就会发送这个消息消息
sp<AMessage> reply = new AMessage(kWhatRenderBuffer, this);
reply->setSize("buffer-ix", index);
reply->setInt32("generation", mBufferGeneration);
// 调用NuplayerRenderer 的 queueBuffer
mRenderer->queueBuffer(mIsAudio, buffer, reply);
(2). queueBuffer
把音视频的buffer添加到Render的队列 mAudioQueue(audio) mVideoQueue(!audio)
<1> queueBuffer发送消息kWhatQueueBuffer调用Renderer::onQueueBuffer
void NuPlayer::Renderer::queueBuffer(bool audio, const sp<MediaCodecBuffer> &buffer, const sp<AMessage> ¬ifyConsumed) {
int64_t mediaTimeUs = -1;
buffer->meta()->findInt64("timeUs", &mediaTimeUs);
// 发送消息kWhatQueueBuffer, 调用onQueueBuffer
// 把Decoder传入的消息notifyConsumed放入到新创建的msg
sp<AMessage> msg = new AMessage(kWhatQueueBuffer, this);
msg->setInt32("queueGeneration", getQueueGeneration(audio));
msg->setInt32("audio", static_cast<int32_t>(audio));
msg->setObject("buffer", buffer);
msg->setMessage("notifyConsumed", notifyConsumed);
msg->post();
<2> 把音视频Buffer添加到队列mAudioQueue, mVideoQueue。调用postDrainAudioQueue_l, postDrainVideoQueue处理各自队列中的Buffer
void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg)
// 判断是Audio数据还是Video的数据
if (audio) mHasAudio = true;
else mHasVideo = true;
//创建并初始化一个mVideoScheduler
if (mHasVideo)
if (mVideoScheduler == NULL)
mVideoScheduler = new VideoFrameScheduler();
mVideoScheduler->init();
//创建一个队列的节点用来保存buffer的信息。
CHECK(msg->findMessage("notifyConsumed", ¬ifyConsumed));
QueueEntry entry;
entry.mBuffer = buffer;
// Decoder传入的消息kWhatRenderBuffer被放入到节点
entry.mNotifyConsumed = notifyConsumed;
entry.mOffset = 0;
entry.mFinalResult = OK;
entry.mBufferOrdinal = ++mTotalBuffersQueued;
// 把创建的节点push到音频数据的队列和视频数据的队列 mAudioQueue mVideoQueue
// 调用postDrainAudioQueue_l 或 postDrainVideoQueue,清空音视频数据的队列
if (audio) {
mAudioQueue.push_back(entry);
postDrainAudioQueue_l();
} else {
mVideoQueue.push_back(entry);
postDrainVideoQueue();
}
2. AudioBuffer的处理
(1) postDrainAudioQueue_l
调用onDrainAudioQueue来处理Auido队列的Buffer
void NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs)
//发送消息 kWhatDrainAudioQueue, 调用
sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
msg->setInt32("drainGeneration", mAudioDrainGeneration);
msg->post(delayUs);
case kWhatDrainAudioQueue
// 接下来主要的工作在onDrainAudioQueue中完成
if (onDrainAudioQueue()) {
// 函数onDrainAud