MediaScaner Issue之Extractor获取关键帧耗时问题
背景:这个出现一个问题播放本地视频,拔出硬盘,视频异常退出
初步log分析:
1、退出播放的原因是出现了media server died
2、media server died 的原因是 media retriver was killed by vold service,
3、其实之前有记录过这个问题,可以看
MediaProvider 多媒体扫描流程
所以第一步还是得找出来看是那个文件扫描比较久,其实出问题得时候log 已经看出来了
17:35:13.195 2834 2876 W vold : Found symlink /proc/7492/fd/84 referencing /storage/1E0E51B90E518AA3/4K/xxxx.mkv
17:35:13.195 2834 2876 W vold : Found symlink /proc/7492/fd/85 referencing /storage/1E0E51B90E518AA3/4K/xxxx.mkv
17:35:13.224 2834 2876 W vold : Found symlink /proc/7505/fd/43 referencing /storage/1E0E51B90E518AA3
17:35:13.224 2834 2876 W vold : Found symlink /proc/7505/fd/46 referencing /storage/1E0E51B90E518AA3/4K
17:35:13.224 2834 2876 W vold : Found symlink /proc/7505/fd/47 referencing /storage/1E0E51B90E518AA3/4K/xxx.mkv
另外调试的时候顺手把这些log 也打开
diff --git a/frameworks/av/media/libstagefright/MediaExtractorFactory.cpp b/frameworks/av/media/libstagefright/MediaExtractorFactory.cp
p
index 7d8ee24..e4dab38 100755
--- a/frameworks/av/media/libstagefright/MediaExtractorFactory.cpp
+++ b/frameworks/av/media/libstagefright/MediaExtractorFactory.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0
#define LOG_TAG "MediaExtractorFactory"
#include <utils/Log.h>
diff --git a/frameworks/av/media/libstagefright/StagefrightMediaScanner.cpp b/frameworks/av/media/libstagefright/StagefrightMediaScanne
r.cpp
index d8d0dcd..5280529 100755
--- a/frameworks/av/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/frameworks/av/media/libstagefright/StagefrightMediaScanner.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0
#define LOG_TAG "StagefrightMediaScanner"
#include <utils/Log.h>
@@ -74,6 +74,7 @@ MediaScanResult StagefrightMediaScanner::processFile(
client.setMimeType("application/octet-stream");
}
client.endFile();
+ ALOGV("processFile '%s'. Done", path);
return result;
}
diff --git a/frameworks/av/media/libstagefright/StagefrightMetadataRetriever.cpp b/frameworks/av/media/libstagefright/StagefrightMetada
taRetriever.cpp
index 62d0e46..19eea76 100755
--- a/frameworks/av/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/frameworks/av/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0
#define LOG_TAG "StagefrightMetadataRetriever"
#include <inttypes.h>
diff --git a/frameworks/av/services/mediaextractor/MediaExtractorService.cpp b/frameworks/av/services/mediaextractor/MediaExtractorServ
ice.cpp
index f0f44f5..aa03ba2 100755
--- a/frameworks/av/services/mediaextractor/MediaExtractorService.cpp
+++ b/frameworks/av/services/mediaextractor/MediaExtractorService.cpp
@@ -15,7 +15,7 @@
*/
#define LOG_TAG "MediaExtractorService"
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <utils/Vector.h>
这边发现是这个函数会执行比较久,
status_t StagefrightMetadataRetriever::getFrameAtIndex(
std::vector<sp<IMemory> >* frames,
int frameIndex, int numFrames, int colorFormat, bool metaOnly) {
ALOGV("getFrameAtIndex: frameIndex %d, numFrames %d, colorFormat: %d, metaOnly: %d",
frameIndex, numFrames, colorFormat, metaOnly);
return getFrameInternal(
frameIndex, numFrames, MediaSource::ReadOptions::SEEK_FRAME_INDEX,
colorFormat, metaOnly, NULL /*outFrame*/, frames);
}
而 继续往下走就是在获取 :kIncludeExtensiveMetaData这个flag的设定中
status_t StagefrightMetadataRetriever::getFrameInternal(
int64_t timeUs, int numFrames, int option, int colorFormat, bool metaOnly,
sp<IMemory>* outFrame, std::vector<sp<IMemory> >* outFrames) {
// ....
sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
i, MediaExtractor::kIncludeExtensiveMetaData);
// ...
这里就直接往mkv extractor中看
status_t MatroskaExtractor::getTrackMetaData(
MetaDataBase &meta,
size_t index, uint32_t flags) {
if (index >= mTracks.size()) {
return UNKNOWN_ERROR;
}
if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails
&& !isLiveStreaming()) {
findThumbnails();
mExtractedThumbnails = true;
}
meta = mTracks.itemAt(index).mMeta;
return OK;
}
逻辑很简单,就是findThumbnails 函数卡住,进入这个函数也能很快看到为什么会卡住了
void MatroskaExtractor::findThumbnails() {
for (size_t i = 0; i < mTracks.size(); ++i) {
TrackInfo *info = &mTracks.editItemAt(i);
const char *mime;
CHECK(info->mMeta.findCString(kKeyMIMEType, &mime));
if (strncasecmp(mime, "video/", 6)) {
continue;
}
BlockIterator iter(this, info->mTrackNum, i);
int32_t j = 0;
int64_t thumbnailTimeUs = 0;
size_t maxBlockSize = 0;
while (!iter.eos() && j < 20) {
if (iter.block()->IsKey()) {
++j;
size_t blockSize = 0;
for (int k = 0; k < iter.block()->GetFrameCount(); ++k) {
blockSize += iter.block()->GetFrame(k).len;
}
if (blockSize > maxBlockSize) {
maxBlockSize = blockSize;
thumbnailTimeUs = iter.blockTimeUs();
}
}
iter.advance();
}
info->mMeta.setInt64(kKeyThumbnailTime, thumbnailTimeUs);
}
}
1、while 循环中不断使用 iter.advance(); 读取 mkv 文件中的数据
2、如果是关键帧block,记录这个block 大小
3、一直读取,记录N次关键block 大小,
4、取N次中最大block的pts 返回
网友评论