MediaScaner Issue之Extractor获取关键帧

2022-03-23  本文已影响0人  Nothing_655f

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 返回

上一篇下一篇

猜你喜欢

热点阅读