无法播放adts格式文件流媒体的问题分析 流媒体播放器

问题背景:dlna测试,有一项测试用例是用不同的服务器共享adts文件,我们的手机作为终端用dlna应用去播放这些文件,都是采用的http形式的流媒体协议播放,在测试中发现一个avox服务器共享的adts文件无法播放
分析过程:将Awesomeplayer中的log开关打开,发现刚准备好播放的时候,下面的log就打出来了ALOGV("MEDIA_PLAYBACK_COMPLETE");那下面就以这个为线索进行跟踪问题原因了voidAwesomePlayer::onStreamDone() { // Posted whenever anystream finishes playing. if ((mFlags& LOOPING) { ...... } else { ALOGV("MEDIA_PLAYBACK_COMPLETE"); notifyListener_l(MEDIA_PLAYBACK_COMPLETE); pause_l(true ); modifyFlags(AT_EOS, SET); }}voidAwesomePlayer::postStreamDoneEvent_l(status_t status){ mStreamDoneStatus =status; mQueue.postEvent(mStreamDoneEvent);}postStreamDoneEvent_l有两个地方发出:第一次在onVideEvent里面,因为是音频,应当都不会进入这里面第二次是在下面这个函数中,这个函数作为一个事件,用来不断检查音频文件是否播放完成void AwesomePlayer::onCheckAudioStatus() {{ Mutex::AutolockautoLock(mAudioLock); status_tfinalStatus; //mWatchForAudioEOS这个变量肯定为true //mAudioPlayer->reachedEOS(&finalStatus)这个条件满足了导致 if (mWatchForAudioEOS&& mAudioPlayer->reachedEOS(&finalStatus)){ mWatchForAudioEOS = false; modifyFlags(AUDIO_AT_EOS, SET); modifyFlags(FIRST_FRAME, SET); postStreamDoneEvent_l(finalStatus); }}下面跟踪mAudioPlayer->reachedEOSbool AudioPlayer::reachedEOS(status_t *finalStatus) { *finalStatus = OK; Mutex::AutolockautoLock(mLock); *finalStatus =mFinalStatus; returnmReachedEOS;}从结果来看,这里返回的mReachedEOS肯定为true,而且finalStatus为ERROR_END_OF_STREAM在AudioPlayer中搜索设置mReachedEOS为true的地方,找到如下的地方:size_t AudioPlayer::fillBuffer(void *data, size_t size){ if (mNumFramesPlayed ==0) { ALOGV("AudioCallback"); }
if (mReachedEOS) { return 0; }
无法播放adts格式文件流媒体的问题分析 流媒体播放器
bool postSeekComplete =false; bool postEOS =false; int64_t postEOSDelayUs =0;
size_t size_done =0; size_t size_remaining =size; while (size_remaining> 0) { if (mInputBuffer == NULL) { status_terr; //下面的ifelse需要确定是走哪个分支 if(mIsFirstBuffer) { mInputBuffer =mFirstBuffer; mFirstBuffer = NULL; err =mFirstBufferResult; mIsFirstBuffer = false; } else{ err =mSource->read(&mInputBuffer,&options); } CHECK((err== OK && mInputBuffer !=NULL) || (err != OK &&mInputBuffer == NULL)); Mutex::Autolock autoLock(mLock); mReachedEOS = true; mFinalStatus = err; break; }也就是在调用mSource->read(&mInputBuffer,&options)时出错下面是视频播放中一系列read的调用关系:audioplayer回调函数---fillBuffer---AudioPlayer::read()----OMXCodec::read()----各个分离器Source::read()(这里是AACSource::read())省略中间的过程,直接定位到AACExtractor.cpp这个文件中的read()函数:发现有这么一段代码:size_t frameSize, frameSizeWithoutHeader, headerSize;if ((seekFrame >= mOffsetVector.size()) ||(frameSize = getAdtsFrameLength(mDataSource, mOffset,&headerSize)) == 0) { return ERROR_END_OF_STREAM;}打log发现,程序进入了这个if分支,也就是出现问题的原因了,下面就要分析为什么会进入这个if分支,由于||是断路操作符,第一个条件满足了就没有执行后面的也就是seekFrame >=mOffsetVector.size()条件满足了,这里两者都为0mOffsetVector赋值的地方也就是在AACExtractor的构造函数中,构造函数中有非常关键的下面的代码: if(mDataSource->getSize(&streamSize)== OK) { while (offset <streamSize) { if((frameSize = getAdtsFrameLength(source, offset, NULL)) == 0){ return; } mOffsetVector.push(offset); offset +=frameSize; numFrames++; } // Round up and get the duration mFrameDurationUs = (1024 * 1000000ll + (sr - 1))/ sr; duration = numFrames * mFrameDurationUs; mMeta->setInt64(kKeyDuration,duration); }这个if分支里面有个while循环用来计算帧数,并且最后计算这个文件的时长,打log发现,出问题的服务器上并没有进入这个if条件,而正常的服务器进入了。分析if中的条件:mDataSource->getSize(&streamSize) ==OK跟踪一下这个代码:mDataSource是NuCacheSource2.cppstatus_t NuCachedSource2::getSize(off64_t *size) { returnmSource->getSize(size); //mSource是ChromiumHTTPDataSource.cpp}status_t ChromiumHTTPDataSource::getSize(off64_t *size){ Mutex::AutolockautoLock(mLock); if(mContentSize < 0) { return ERROR_UNSUPPORTED; } *size =mContentSize; return OK;}由于这个方法没有返回ok,也就是mContentSize 小于0了赋值的地方就一处:void ChromiumHTTPDataSource::onConnectionEstablished( int64_t contentSize, const char *contentType){ mState =CONNECTED; mContentSize = (contentSize < 0) ? -1 :contentSize + mCurrentOffset; mContentType =String8(contentType); mCondition.broadcast();}这个函数是在服务器连接上的回调中调用的,在support.cpp中调用,具体看一下代码void SfDelegate::OnResponseStarted(net::URLRequest *request){ MY_LOGV("OnResponseStarted");
std::stringheaders; request->GetAllResponseHeaders(&headers);
MY_LOGV(StringPrintf("response headers: %s",headers.c_str()).c_str());
std::stringcontentType; request->GetResponseHeaderByName("Content-Type",&contentType);
mOwner->onConnectionEstablished( request->GetExpectedContentSize(),contentType.c_str());}request->GetExpectedContentSize()用来从服务器发送的报文中获取文件的大小,也就是这里没有获取到,导致后面没有设置成功。分析到这里,就自然而然的想到去抓包分析服务器返回的报文,抓取ip log发现:正常情况的如下,发送的报文中有如下信息:content-length: 2102023而不正常的情况,采用的是另一套标准,发送如下信息:transfer-encoding:chunked这种方式没有具体返回文件的长度,综上也就是最终导致问题出现的原因。
其实谷歌原始代码中是没有seekFrame >=mOffsetVector.size()这个判断条件的。

  

爱华网本文地址 » http://www.413yy.cn/a/25101017/353063.html

更多阅读

快速解决QQ登录超时,错误码0x00000001的问题 格式工厂 0x00000001

快速解决QQ登录超时,错误码0x00000001的问题——简介 有些时候,我们的QQ上着好好地突然掉线了,然后再次登陆怎么也不能登陆成功,且提示“QQ登录超时,错误码0x00000001”(如图),或者前一天晚上关机前还一切正常,第二天就无法登陆了。出现这个

收益法评估无形资产的问题分析 资产评估收益法案例

摘要:随着我国经济的发展,科学技术的进步,企业的成长,无形资产也展现出越来越重要的地位,无形资产的评估也越来越重要,本文重点对无形资产评估中收益法运用以及运用过程中易于出现的问题进行总结,并提出相应的解决办法。关键词:资产评估 无

发展油茶树苗种植栽培存在的问题分析 油茶高产栽培技术

  (1)发展潜力未被充分认识,缺乏统筹发展方案,基层重视不够,油茶树苗种植未加以重视。目前,存在“上面热,下面冷”的突出问题。大部分乡镇、村组未将“油茶产业化”的发展纳入重要议事日程,还停留在一般口号上,投入很少。同时,对“油茶产

解决黑莓桌面管理器连接不上设备的问题 黑莓桌面管理器6.0

网上的有一个说的和我的症状一样,数据线坏了,我重新买了根V3盒装的数据线,经过我的测量,排线是一样的usb口 1-5 2-4 3-3 4-1 手机口测量的时候附带的那根数据线usb口有一个不通剥开外层没发现断点,直到拨到手机口那里,我靠,焊接点已经断

声明:《无法播放adts格式文件流媒体的问题分析 流媒体播放器》为网友花样少女分享!如侵犯到您的合法权益请联系我们删除