android nuplayer reset处理流程

2024-05-27 11:18

本文主要是介绍android nuplayer reset处理流程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

转载
1.NuPlayerDriver::reset() 
[cpp]  view plain copy
  1. mPlayer->resetAsync();// 执行异步reset  
  2.   
  3. while (mResetInProgress) { // 等待reset完成,如果5秒未完成,则会出现ANR  
  4.     mCondition.wait(mLock);  
  5. }  
2.NuPlayer::resetAsync()
发送kWhatReset消息

3.kWhatReset消息的处理
NuPlayer::onMessageReceived
case kWhatReset:
(1)如果mFlushingAudio或者mFlushingVideo是AWAITING_DISCONTINUITY状态,执行
[cpp]  view plain copy
  1. mRenderer->resume();  
  2.     if (mRenderer != NULL) {  
  3.         // There's an edge case where the renderer owns all output  
  4.         // buffers and is paused, therefore the decoder will not read  
  5.         // more input data and will never encounter the matching  
  6.         // discontinuity. To avoid this, we resume the renderer.  
  7.   
  8.         if (mFlushingAudio == AWAITING_DISCONTINUITY  
  9.                 || mFlushingVideo == AWAITING_DISCONTINUITY) {  
  10.             mRenderer->resume();  
  11.         }  
  12.     }  
(2)如果正在flushing,则推迟执行reset
[cpp]  view plain copy
  1. if (mFlushingAudio != NONE || mFlushingVideo != NONE) {  
  2.     // We're currently flushing, postpone the reset until that's  
  3.     // completed.  
  4.   
  5.     LOGV("postponing reset mFlushingAudio=%d, mFlushingVideo=%d",  
  6.             mFlushingAudio, mFlushingVideo);  
  7.   
  8.     mResetPostponed = true; // 设置推迟reset标志  
  9.     break;  
  10. }  
(3)如果mAudioDecoder == NULL && mVideoDecoder == NULL,则表示已经执行完reset,则调用
finishReset()

(4)执行audio的flushDecoder

(5)执行video的flushDecoder

(6)设置变量mResetInProgress为true

4.NuPlayer::finishReset()
(1)执行mSource->stop();
(2)执行driver->notifyResetComplete()
[cpp]  view plain copy
  1. if (mSource != NULL) {  
  2.     mSource->stop(); // 执行NuPlayer::RTSPSource::stop()函数  
  3.     mSource.clear();  
  4. }  
  5.   
  6. if (mDriver != NULL) {  
  7.     sp<NuPlayerDriver> driver = mDriver.promote();  
  8.     if (driver != NULL) {  
  9.         driver->notifyResetComplete();  
  10.     }  
  11. }  

4.1 NuPlayer::RTSPSource::stop()

stop函数发送消息后,断开与服务器的连接需要及时执行完成,否则会超时导致ANR。

[cpp]  view plain copy
  1. void NuPlayer::RTSPSource::stop() {  
  2.     sp<AMessage> msg = new AMessage(kWhatDisconnect, mReflector->id());  
  3.   
  4.     sp<AMessage> dummy;  
  5.     msg->postAndAwaitResponse(&dummy); // 最终调用全局变量gLooperRoster的postAndAwaitResponse函数  
  6. }  
4.2 处理kWhatDisconnect消息
[cpp]  view plain copy
  1. void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {  
  2.     if (msg->what() == kWhatDisconnect) {  
  3.         uint32_t replyID;  
  4.         CHECK(msg->senderAwaitsResponse(&replyID)); // 取得replyID  
  5.   
  6.         mDisconnectReplyID = replyID;  
  7.         finishDisconnectIfPossible(); // 断开与服务器的数据链接  
  8.         return;  
  9.     }  
4.3 NuPlayer::RTSPSource::finishDisconnectIfPossible
[cpp]  view plain copy
  1. if (mState != DISCONNECTED) {  
  2.     mHandler->disconnect(); // 执行MyHandler.h的disconnect函数,发送'abor'消息,断开与服务器的链接  
  3.     return;  
  4. }  
5.NuPlayerDriver::notifyResetComplete()
设置mResetInProgress为false,则1.中的等待完成,即reset执行结束

6.NuPlayer::flushDecoder
[cpp]  view plain copy
  1. (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();  
  2.  mRenderer->flush(audio);  
7.NuPlayer::Decoder::signalFlush()
调用mCodec->signalFlush(); 调用的是ACodec的signalFlush函数

8.ACodec::signalFlush()
发送kWhatFlush消息

9.ACodec::UninitializedState::onMessageReceived
case ACodec::kWhatFlush:
发送ACodec::kWhatFlushCompleted消息

10.对ACodec::kWhatFlushCompleted消息的处理位于NuPlayer类中
[cpp]  view plain copy
  1. NuPlayer::onMessageReceived  
  2. case kWhatVideoNotify:  
  3. case kWhatAudioNotify:  
  4. ...  
  5.     } else if (what == ACodec::kWhatFlushCompleted) {  
  6.         bool needShutdown;  
  7.   
  8.         if (audio) {  
  9.             CHECK(IsFlushingState(mFlushingAudio, &needShutdown));  
  10.             mFlushingAudio = FLUSHED;  
  11.         } else {  
  12.             CHECK(IsFlushingState(mFlushingVideo, &needShutdown));  
  13.             mFlushingVideo = FLUSHED;  
  14.   
  15.             mVideoLateByUs = 0;  
  16.         }  
  17.   
  18.         LOGV("decoder %s flush completed", audio ? "audio" : "video");  
  19.   
  20.         if (needShutdown) {  
  21.             LOGV("initiating %s decoder shutdown",  
  22.                  audio ? "audio" : "video");  
  23.   
  24. // 调用Decoder类的initiateShutdown --> ACodec::initiateShutdown() --> 发送kWhatShutdown消息 -->  
  25. // 再发送ACodec::kWhatShutdownCompleted消息 --> 回到本函数处理ACodec::kWhatShutdownCompleted消息  
  26.             (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();  
  27.   
  28.             if (audio) {  
  29.                 mFlushingAudio = SHUTTING_DOWN_DECODER;  
  30.             } else {  
  31.                 mFlushingVideo = SHUTTING_DOWN_DECODER;  
  32.             }  
  33.         }  
  34.   
  35.         finishFlushIfPossible(); //  
  36.     }  
  37.   
  38. ...  
  39.     } else if (what == ACodec::kWhatShutdownCompleted) {  
  40.         LOGV("%s shutdown completed", audio ? "audio" : "video");  
  41.         if (audio) {  
  42.             mAudioDecoder.clear();  
  43.   
  44.             CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);  
  45.             mFlushingAudio = SHUT_DOWN;  
  46.         } else {  
  47.             mVideoDecoder.clear();  
  48.   
  49.             CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);  
  50.             mFlushingVideo = SHUT_DOWN;  
  51.         }  
  52.   
  53.         finishFlushIfPossible(); //  
  54.     }  
11.finishFlushIfPossible的处理
[cpp]  view plain copy
  1. void NuPlayer::finishFlushIfPossible() {  
  2.     if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {  
  3.         return;  
  4.     }  
  5.   
  6.     if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {  
  7.         return;  
  8.     }  
  9.   
  10.     LOGV("both audio and video are flushed now.");  
  11.   
  12.     if (mTimeDiscontinuityPending) {  
  13.         mRenderer->signalTimeDiscontinuity(); // 发送消息  
  14.         mTimeDiscontinuityPending = false;  
  15.     }  
  16.   
  17. // NuPlayer::Decoder::signalResume --> ACodec::signalResume --> 发送kWhatResume消息 -->  
  18. // ACodec::ExecutingState::resume --> ACodec::ExecutingState::submitOutputBuffers -->  
  19. // ACodec::BaseState::postFillThisBuffer --> kWhatInputBufferFilled -->  
  20. // ACodec::BaseState::onInputBufferFilled  
  21.     if (mAudioDecoder != NULL) {  
  22.         mAudioDecoder->signalResume();  
  23.     }  
  24.   
  25.     if (mVideoDecoder != NULL) {  
  26.         mVideoDecoder->signalResume();  
  27.     }  
  28.   
  29.     mFlushingAudio = NONE;  
  30.     mFlushingVideo = NONE;  
  31.   
  32.     if (mResetInProgress) { // 3.(6)中设置为true了  
  33.         LOGV("reset completed");  
  34.   
  35.         mResetInProgress = false;  
  36.         finishReset(); // reset执行完成,见4,5的处理  
  37.     } else if (mResetPostponed) { // 如果3.(2)中设置了推迟执行reset,则重新发送kWhatReset消息  
  38.         (new AMessage(kWhatReset, id()))->post();  
  39.         mResetPostponed = false;  
  40.     } else if (mAudioDecoder == NULL || mVideoDecoder == NULL) {  
  41.         postScanSources();  
  42.     }  
  43. }  

这篇关于android nuplayer reset处理流程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1007322

相关文章

Go语言使用Buffer实现高性能处理字节和字符

《Go语言使用Buffer实现高性能处理字节和字符》在Go中,bytes.Buffer是一个非常高效的类型,用于处理字节数据的读写操作,本文将详细介绍一下如何使用Buffer实现高性能处理字节和... 目录1. bytes.Buffer 的基本用法1.1. 创建和初始化 Buffer1.2. 使用 Writ

Python视频处理库VidGear使用小结

《Python视频处理库VidGear使用小结》VidGear是一个高性能的Python视频处理库,本文主要介绍了Python视频处理库VidGear使用小结,文中通过示例代码介绍的非常详细,对大家的... 目录一、VidGear的安装二、VidGear的主要功能三、VidGear的使用示例四、VidGea

Python结合requests和Cheerio处理网页内容的操作步骤

《Python结合requests和Cheerio处理网页内容的操作步骤》Python因其简洁明了的语法和强大的库支持,成为了编写爬虫程序的首选语言之一,requests库是Python中用于发送HT... 目录一、前言二、环境搭建三、requests库的基本使用四、Cheerio库的基本使用五、结合req

使用Python处理CSV和Excel文件的操作方法

《使用Python处理CSV和Excel文件的操作方法》在数据分析、自动化和日常开发中,CSV和Excel文件是非常常见的数据存储格式,ython提供了强大的工具来读取、编辑和保存这两种文件,满足从基... 目录1. CSV 文件概述和处理方法1.1 CSV 文件格式的基本介绍1.2 使用 python 内

Python实现NLP的完整流程介绍

《Python实现NLP的完整流程介绍》这篇文章主要为大家详细介绍了Python实现NLP的完整流程,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 编程安装和导入必要的库2. 文本数据准备3. 文本预处理3.1 小写化3.2 分词(Tokenizatio

如何使用celery进行异步处理和定时任务(django)

《如何使用celery进行异步处理和定时任务(django)》文章介绍了Celery的基本概念、安装方法、如何使用Celery进行异步任务处理以及如何设置定时任务,通过Celery,可以在Web应用中... 目录一、celery的作用二、安装celery三、使用celery 异步执行任务四、使用celery

SpringBoot操作spark处理hdfs文件的操作方法

《SpringBoot操作spark处理hdfs文件的操作方法》本文介绍了如何使用SpringBoot操作Spark处理HDFS文件,包括导入依赖、配置Spark信息、编写Controller和Ser... 目录SpringBoot操作spark处理hdfs文件1、导入依赖2、配置spark信息3、cont

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

SpringBoot使用minio进行文件管理的流程步骤

《SpringBoot使用minio进行文件管理的流程步骤》MinIO是一个高性能的对象存储系统,兼容AmazonS3API,该软件设计用于处理非结构化数据,如图片、视频、日志文件以及备份数据等,本文... 目录一、拉取minio镜像二、创建配置文件和上传文件的目录三、启动容器四、浏览器登录 minio五、

MyBatis延迟加载的处理方案

《MyBatis延迟加载的处理方案》MyBatis支持延迟加载(LazyLoading),允许在需要数据时才从数据库加载,而不是在查询结果第一次返回时就立即加载所有数据,延迟加载的核心思想是,将关联对... 目录MyBATis如何处理延迟加载?延迟加载的原理1. 开启延迟加载2. 延迟加载的配置2.1 使用