美文网首页
MediaScaner Issue之Extractor获取关键帧

MediaScaner Issue之Extractor获取关键帧

作者: Nothing_655f | 来源:发表于2022-03-23 20:37 被阅读0次

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

    相关文章

      网友评论

          本文标题:MediaScaner Issue之Extractor获取关键帧

          本文链接:https://www.haomeiwen.com/subject/ggrhjrtx.html