96SEO 2026-02-20 07:54 0
部分简单#xff0c;越读越发现自己的无知#xff0c;Android

onRequestInputBuffers();virtual
等等方法这时候可能就会有人有疑问了我上层调用的这些接口为什么底层却没有了呢其实在之前的文章中我们已经对部分接口做了解释这里就不再赘述。
type、surface、secure、width、height、crypto、csd
设定上层传下的参数pause这个方法其实并没有用后面详细了解它为什么没有用setRenderer设定
的解码流程initiateShutdown停止解码流程并释放相关资源getStats获取当前
信息当前解出的帧数丢弃的帧数等等信息。
其他onConfigure
NuPlayer::instantiateDecoder(bool
mSource-getFormat(audio);*decoder
mCCDecoder);(*decoder)-init();(*decoder)-configure(format);
{mDecoderLooper-registerHandler(this);
NuPlayer::DecoderBase::onRequestInputBuffers()
AMessage(kWhatRequestInputBuffers,
NuPlayer::Decoder::onConfigure(const
mime;CHECK(format-findString(mime,
MediaCodec::CreateByType(mCodecLooper,
{mCodec-getName(mComponentName);mComponentName.append(.secure);mCodec-release();mCodec
MediaCodec::CreateByComponentName(mCodecLooper,
*/);rememberCodecSpecificData(format);spAMessage
this);mCodec-setCallback(reply);err
mBufferGeneration这个东西是干什么的呢其实我们之前已经说过
NuPlayer::Decoder::isStaleReply(const
generation;CHECK(msg-findInt32(generation,
NuPlayer::Decoder::onMessageReceived(const
ACodec、NuPlayer::Source、Renderer
发送消息NuPlayer、Renderer、MediaCodec
index);reply-setInt32(generation,
mBufferGeneration);reply-setSize(size,
起着状态记录的作用当状态发生改变后依赖该状态的消息将会不再处理。
它和一些具体的状态例如
NuPlayer::Decoder::onMessageReceived(const
cbID;CHECK(msg-findInt32(callbackID,
MediaCodec::CB_INPUT_AVAILABLE:{int32_t
index;CHECK(msg-findInt32(index,
index));handleAnInputBuffer(index);break;}case
MediaCodec::CB_OUTPUT_AVAILABLE:{int32_t
flags;CHECK(msg-findInt32(index,
index));CHECK(msg-findSize(offset,
offset));CHECK(msg-findSize(size,
size));CHECK(msg-findInt64(timeUs,
timeUs));CHECK(msg-findInt32(flags,
flags));handleAnOutputBuffer(index,
CB_INPUT_AVAILABLE、CB_OUTPUT_AVAILABLE、CB_ERROR、CB_OUTPUT_FORMAT_CHANGED
NuPlayer::Decoder::handleAnInputBuffer(size_t
buffer;mCodec-getInputBuffer(index,
{mInputBuffers.add();mInputBufferIsDequeued.add();mMediaBuffers.editItemAt(i)
NULL;mInputBufferIsDequeued.editItemAt(i)
false;}}mInputBuffers.editItemAt(index)
buffer;mInputBufferIsDequeued.editItemAt(index)
AMessage();msg-setSize(buffer-ix,
mCSDsToSubmit.itemAt(0);msg-setBuffer(buffer,
buffer);mCSDsToSubmit.removeAt(0);if
{handleError(UNKNOWN_ERROR);return
(!mPendingInputMessages.empty())
*mPendingInputMessages.begin();if
{break;}mPendingInputMessages.erase(mPendingInputMessages.begin());}//
(!mInputBufferIsDequeued.editItemAt(index))
中mDequeuedInputBuffers.push_back(index);//
decoderonRequestInputBuffers();return
datadoRequestBuffersonRequestInputBuffers
内部实现onInputBufferFetched成功从Source
MediaCodecfetchInputDataonInputBufferFetched
NuPlayer::DecoderBase::onRequestInputBuffers()
获取数据的调用mRequestInputBuffersPending
AMessage(kWhatRequestInputBuffers,
doRequestBuffers所以它们的作用是相同的但是一个是基类的方法一个是子类的方法。
这么设计有什么用呢我的理解是这样每个
方法使用父类定义的数据读取流程流程中调用子类的数据读取实现这样就一举两得既统一了读取流程又区分了读取方式。
获取数据失败了那么需要做延时等待并且重新尝试获取等待的过程中我们并不希望外部能够再调用到
NuPlayer::Decoder::doRequestBuffers()
!mDequeuedInputBuffers.empty())
*mDequeuedInputBuffers.begin();spAMessage
AMessage();msg-setSize(buffer-ix,
bufferbreak;}mDequeuedInputBuffers.erase(mDequeuedInputBuffers.begin());if
(!mPendingInputMessages.empty()||
{mPendingInputMessages.push_back(msg);}}return
NuPlayer::Decoder::fetchInputData(spAMessage
mSource-dequeueAccessUnit(mIsAudio,
获取码流不连续的原因CHECK(accessUnit-meta()-findInt32(discontinuity,
ATSParser::DISCONTINUITY_AUDIO_FORMAT))||
ATSParser::DISCONTINUITY_VIDEO_FORMAT));bool
判断当前播放的码流格式是否支持无缝切换seamlessFormatChange
supportsSeamlessFormatChange(newFormat);//
bufferrememberCodecSpecificData(newFormat);mTimeChangePending
bufferrememberCodecSpecificData(newFormat);continue;}
100ms视频为avc并且不是参考帧那么就drop掉当前读取的内容if
!IsAVCReferenceFrame(accessUnit))
(dropAccessUnit);reply-setBuffer(buffer,
不仅仅是获取了数据还对码流的异常情况做了处理。
dequeueAccessUnit
OK获取到有效数据-EWOULDBLOCK未能读取到数据INFO_DISCONTINUITY码流不连续ERROR_END_OF_STREAM读到文件末尾
DISCONTINUITY_VIDEO_FORMAT格式变化分别宽高变化和mime
DISCONTINUITY_TIME这种情况出现在直播的回播中比较多。
无缝切换adaptive-playback如果支持则不对该事件做处理如果不支持把返回值设置为
ERROR_END_OF_STREAM那么重新开始播放之后需要先填充
MediaCodec这里比较简单就是做了数据拷贝而已要看的只有
事件处理完成后才会写入下一个序列的数据这部分我们放到下一小节来看。
NuPlayer::Decoder::isDiscontinuityPending()
NuPlayer::Decoder::handleAnOutputBuffer(size_t
buffermCodec-getOutputBuffer(index,
buffer-meta()-findInt64(frameIndex,
frameIndex);buffer-setRange(offset,
ptsbuffer-meta()-clear();buffer-meta()-setInt64(timeUs,
{buffer-meta()-setInt64(frameIndex,
index);reply-setInt32(generation,
mBufferGeneration);reply-setSize(size,
video);buffer-meta()-setInt32(eos,
(mSkipRenderingUntilMediaTimeUs
mSkipRenderingUntilMediaTimeUs)
requested.,mComponentName.c_str(),
{notifyResumeCompleteIfNecessary();if
true;}mSkipRenderingUntilMediaTimeUs
播放停止后重新恢复播放等待第一帧到达后上抛消息在seek时用到notifyResumeCompleteIfNecessary();if
avsyncmRenderer-queueBuffer(mIsAudio,
NuPlayer::Decoder::handleOutputFormatChange(const
autolock(mStatsLock);mStats-setInt32(width,
mNotify-dup();notify-setInt32(what,
kWhatVideoSizeChanged);notify-setMessage(format,
(mSource-getDuration(durationUs)
AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US))
AUDIO_OUTPUT_FLAG_DEEP_BUFFER;}
AUDIO_OUTPUT_FLAG_NONE;}spAMessage
AMessage(kWhatAudioOutputFormatChanged,
this);reply-setInt32(generation,
mBufferGeneration);mRenderer-changeAudioFormat(format,
{onRenderBuffer(msg);}break;}isStaleReply
NuPlayer::Decoder::onRenderBuffer(const
indexCHECK(msg-findSize(buffer-ix,
timestampNs;CHECK(msg-findInt64(timestampNs,
mCodec-renderOutputBufferAndRelease(bufferIx,
mCodec-releaseOutputBuffer(bufferIx);}//
{finishHandleDiscontinuity(true
renderOutputBufferAndRelease否则调用
NuPlayer::Decoder::finishHandleDiscontinuity(bool
{ALOGV(finishHandleDiscontinuity:
mNotify-dup();msg-setInt32(what,
kWhatInputDiscontinuity);msg-setInt32(formatChange,
mFormatChangePending);msg-post();mFormatChangePending
DecoderBase::kWhatInputDiscontinuity)
formatChange;CHECK(msg-findInt32(formatChange,
{mDeferredActions.push_back(new
FLUSH_CMD_SHUTDOWN));}mDeferredActions.push_back(new
SimpleAction(NuPlayer::performScanSources));processDeferredActions();}
NuPlayer::Decoder::doFlush(bool
notifyComplete);mRenderer-signalTimeDiscontinuity();}status_t
fails.}releaseAndResetMediaBuffers();mPaused
handled.finishHandleDiscontinuity(false
mNotify-dup();notify-setInt32(what,
kWhatFlushCompleted);notify-post();
NuPlayer::Decoder::onShutdown(bool
nownotifyResumeCompleteIfNecessary();if
nativeWindowConnect(mSurface.get(),
error%d,mComponentName.c_str(),
listreleaseAndResetMediaBuffers();if
mNotify-dup();notify-setInt32(what,
kWhatShutdownCompleted);notify-post();//
NuPlayer::Decoder::onResume(bool
mComponentName.c_str());handleError(NO_INIT);return;}mCodec-start();
机制领悟的还不够深刻设计模式也不会接下来会继续加强这部分的学习
如果觉得对您有帮助还请不要吝啬点赞、收藏与关注哦您的支持是我更新的最大动力。
https://blog.csdn.net/qq_41828351?spm1000.2115.3001.5343
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback