一、问题现象:
我在使用微视听app播放视频的时候,经常在播放前面一段广告的时候会莫名地卡住,每次都是播放8s就卡住了,利用logcat查看调试信息如下
12-07 11:16:55.616: I/TENCENT_AD_AdView(1773): ## 2017-12-07 11:16:55.618 [1773,1773,:0] INFO ## [TENCENT_AD_AdView]handle adview message:1001
12-07 11:16:55.646: I/HLSP2P(1773): ## 2017-12-07 11:16:55.651 [1773,2800,:0] INFO ## [HLSP2P][Scheduler.cpp:1480][INFO][OnPeerConnected]keyid: v0025u7iuf8.321003.hls, punch peer 3372405511(180.122.10.163:1863) ok, bPunchAllow = 0
12-07 11:16:55.721: I/HLSP2P(1773): ## 2017-12-07 11:16:55.726 [1773,2796,:0] INFO ## [HLSP2P][vod_hls_handler.cpp:39]task_id: 300018, _n: 1, uri: /vodhls/300018/2.ts
12-07 11:16:55.721: I/HLSP2P(1773): ## 2017-12-07 11:16:55.727 [1773,2796,:0] INFO ## [HLSP2P][vod_hls_handler.cpp:399]ts_handler_request conn: 0x7552d520 uri: /vodhls/300018/2.ts
12-07 11:16:55.726: I/HLSP2P(1773): ## 2017-12-07 11:16:55.730 [1773,2796,:0] INFO ## [HLSP2P][vod_hls_handler.cpp:434]ts_handler_request task_id: 300018, uri: /vodhls/300018/2.ts, filename: 2.ts, range[0, -1]
12-07 11:16:55.736: I/HLSP2P(1773): ## 2017-12-07 11:16:55.742 [1773,2796,:0] INFO ## [HLSP2P][vod_hls_handler.cpp:514]ts_hanlder_poll TXP2P_GetTsSize task_id: 300018, filename: 2.ts, filesize: 2055404
12-07 11:16:55.766: I/PlaylistFetcher(4190): queueing discontinuity (seek=0, explicit=1)
12-07 11:16:55.776: I/PlaylistFetcher(4190): queueing discontinuity (seek=0, explicit=1)
12-07 11:16:55.781: I/LiveSession(4190): [video] read discontinuity of type 7, extra = NULL
12-07 11:16:55.781: I/NuPlayer(4190): video discontinuity (formatChange=1, time=1)
12-07 11:16:55.781: I/PlaylistFetcher(4190): queueing discontinuity (seek=0, explicit=1)
12-07 11:16:55.786: I/PlaylistFetcher(4190): queueing discontinuity (seek=0, explicit=1)
12-07 11:16:55.786: I/PlaylistFetcher(4190): queueing discontinuity (seek=0, explicit=1)
12-07 11:16:55.791: I/PlaylistFetcher(4190): queueing discontinuity (seek=0, explicit=1)
12-07 11:16:55.791: I/PlaylistFetcher(4190): queueing discontinuity (seek=0, explicit=1)
12-07 11:16:55.796: I/PlaylistFetcher(4190): queueing discontinuity (seek=0, explicit=1)
12-07 11:16:55.796: I/PlaylistFetcher(4190): queueing discontinuity (seek=0, explicit=1)
12-07 11:16:55.801: I/PlaylistFetcher(4190): queueing discontinuity (seek=0, explicit=1)
12-07 11:16:55.806: I/PlaylistFetcher(4190): queueing discontinuity (seek=0, explicit=1)
二、问题分析:
出现这个问题的原因是在线视频的广告是利用缓存存储,一般是一边下载一边播放,然后又一个进度值来记录当前的播放位置,但是由于某种原因导致数据丢失,然后视频播放就陷入了死循环,不会放弃原来的数据包,导致一直卡住。把mediaserver进程杀掉也可以暂时解决这个问题,但是下次播放视频还会再次发生。
三、问题解决
andoird4.4源码应该有一些不完善的地方,利用google查询,发现别人发布了补丁,只要把这个补丁打到4.4的安卓源码里就能解决问题。
说明: HLS: do not discard packets when queuing explicit discontinuity in case of explicit discontinuity (#EXT-X-DISCONTINUITY tag in the playlist), do not discard packets that's already queued. (when seeking, the old fetcher will be discarded so this won't affect seeking case.) Bug: 15020526 Change-Id: I5d3fc489df35e3bc44acb1ee7851571cb99cb56b
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp index 5cf9238..388f77a 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp +++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -272,7 +272,9 @@ if (seeking) { track->mPackets->queueDiscontinuity( - ATSParser::DISCONTINUITY_SEEK, NULL); + ATSParser::DISCONTINUITY_SEEK, + NULL, + true /* discard */); } track->mPackets->queueAccessUnit(buffer); @@ -280,7 +282,9 @@ } else if (err == INFO_FORMAT_CHANGED) { #if 0 track->mPackets->queueDiscontinuity( - ATSParser::DISCONTINUITY_FORMATCHANGE, NULL); + ATSParser::DISCONTINUITY_FORMATCHANGE, + NULL, + false /* discard */); #endif } else { track->mPackets->signalEOS(err);
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp index 94800ba..2338b23 100644 --- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp +++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -505,7 +505,10 @@ TrackInfo *info = &mTracks.editItemAt(trackIndex); spsource = info->mSource; if (source != NULL) { - source->queueDiscontinuity(ATSParser::DISCONTINUITY_SEEK, NULL); + source->queueDiscontinuity( + ATSParser::DISCONTINUITY_SEEK, + NULL, + true /* discard */); } break;
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp index 2af0998..10437c9 100644 --- a/media/libstagefright/httplive/PlaylistFetcher.cpp +++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -588,7 +588,10 @@ void PlaylistFetcher::queueDiscontinuity( ATSParser::DiscontinuityType type, const sp&extra) { for (size_t i = 0; i < mPacketSources.size(); ++i) { - mPacketSources.valueAt(i)->queueDiscontinuity(type, extra); + // do not discard buffer upon #EXT-X-DISCONTINUITY tag + // (seek will discard buffer by abandoning old fetchers) + mPacketSources.valueAt(i)->queueDiscontinuity( + type, extra, false /* discard */); } } @@ -723,8 +726,7 @@ firstSeqNumberInPlaylist = 0; } - bool seekDiscontinuity = false; - bool explicitDiscontinuity = false; + bool discontinuity = false; const int32_t lastSeqNumberInPlaylist = firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1; @@ -792,7 +794,7 @@ if (mSeqNumber < firstSeqNumberInPlaylist) { mSeqNumber = firstSeqNumberInPlaylist; } - explicitDiscontinuity = true; + discontinuity = true; // fall through } else { @@ -817,7 +819,7 @@ int32_t val; if (itemMeta->findInt32("discontinuity", &val) && val != 0) { - explicitDiscontinuity = true; + discontinuity = true; } int64_t range_offset, range_length; @@ -877,7 +879,7 @@ return; } - if (mStartup || seekDiscontinuity || explicitDiscontinuity) { + if (mStartup || discontinuity) { // Signal discontinuity. if (mPlaylist->isComplete() || mPlaylist->isEvent()) { @@ -887,18 +889,14 @@ mNextPTSTimeUs = getSegmentStartTimeUs(mSeqNumber); } - if (seekDiscontinuity || explicitDiscontinuity) { - ALOGI("queueing discontinuity (seek=%d, explicit=%d)", - seekDiscontinuity, explicitDiscontinuity); + if (discontinuity) { + ALOGI("queueing discontinuity (explicit=%d)", discontinuity); queueDiscontinuity( - explicitDiscontinuity - ? ATSParser::DISCONTINUITY_FORMATCHANGE - : ATSParser::DISCONTINUITY_SEEK, + ATSParser::DISCONTINUITY_FORMATCHANGE, NULL /* extra */); - seekDiscontinuity = false; - explicitDiscontinuity = false; + discontinuity = false; } }
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp index 338e899..3d241e0 100644 --- a/media/libstagefright/mpeg2ts/ATSParser.cpp +++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -669,7 +669,7 @@ } if (mSource != NULL) { - mSource->queueDiscontinuity(type, extra); + mSource->queueDiscontinuity(type, extra, true); } }
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp index 021b640..871824a 100644 --- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp +++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -217,22 +217,25 @@ void AnotherPacketSource::queueDiscontinuity( ATSParser::DiscontinuityType type, - const sp&extra) { + const sp&extra, + bool discard) { Mutex::Autolock autoLock(mLock); - // Leave only discontinuities in the queue. - List>::iterator it = mBuffers.begin(); - while (it != mBuffers.end()) { - spoldBuffer = *it; + if (discard) { + // Leave only discontinuities in the queue. + List>::iterator it = mBuffers.begin(); + while (it != mBuffers.end()) { + spoldBuffer = *it; - int32_t oldDiscontinuityType; - if (!oldBuffer->meta()->findInt32( - "discontinuity", &oldDiscontinuityType)) { - it = mBuffers.erase(it); - continue; + int32_t oldDiscontinuityType; + if (!oldBuffer->meta()->findInt32( + "discontinuity", &oldDiscontinuityType)) { + it = mBuffers.erase(it); + continue; + } + + ++it; } - - ++it; } mEOSResult = OK;
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h index 9b193a2..06c49bd 100644 --- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h +++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -54,7 +54,9 @@ void queueAccessUnit(const sp&buffer); void queueDiscontinuity( - ATSParser::DiscontinuityType type, const sp&extra); + ATSParser::DiscontinuityType type, + const sp&extra, + bool discard); void signalEOS(status_t result);
参考资料:https://android.googlesource.com/platform/frameworks/av/+/632740c%5E%21/