Android StageFrightMediaScanner原始碼解析
1. 簡介
Android中在StageFrightMediaScanner實現對多媒體檔案的處理。
此外在StageFrightMediaScanner定義了支援的多媒體檔案類型。
檔案位置
frameworksavmedialibstagefrightStagefrightMediaScanner.cpp
編譯目標
libstagefright.so
2. processFile
processFile並沒有做什麼處理,主要是調用processFileInternal。
另外可以看到在processFile中調用MediaScannerClient的beginFile和endFile方法,時間上google並沒有實現beginFile和endFile方法。
(說實話Android5.0 真的很爛,很多功能根本就沒有開發完全)
MediaScanResult StagefrightMediaScanner::processFile( const char *path, const char *mimeType, MediaScannerClient &client) { //MediaScannerClient根本就沒有實現,所以不用關心 client.setLocale(locale()); client.beginFile(); MediaScanResult result = processFileInternal(path, mimeType, client); client.endFile(); return result;}
3. processFileInternal
processFileInternal可以說是MediaScanner處理多媒體檔案最終節點
在此函數中通過調用MediaMetadataRetriever擷取多媒體資訊。
調用MediaMetadataRetriever擷取媒體檔案資訊過程如下:
(1) MediaMetadataRetriever.setDataSource(file)
(2) MediaMetadataRetriever.extractMetadata(key)
MediaScanResult StagefrightMediaScanner::processFileInternal( const char *path, const char * /* mimeType */, MediaScannerClient &client) { const char *extension = strrchr(path, '.'); ///check file type if (!extension) { return MEDIA_SCAN_RESULT_SKIPPED; } if (!FileHasAcceptableExtension(extension)) { return MEDIA_SCAN_RESULT_SKIPPED; } //---------------------------------------- ///Init & setDataSource MediaMetadataRetriever sp mRetriever(new MediaMetadataRetriever); int fd = open(path, O_RDONLY | O_LARGEFILE); status_t status; if (fd < 0) { // couldn't open it locally, maybe the media server can? status = mRetriever->setDataSource(NULL /* httpService */, path); } else { status = mRetriever->setDataSource(fd, 0, 0x7ffffffffffffffL); close(fd); } //---------------------------------------- ///get MIMETYPE const char *value; if ((value = mRetriever->extractMetadata( METADATA_KEY_MIMETYPE)) != NULL) { status = client.setMimeType(value); if (status) { return MEDIA_SCAN_RESULT_ERROR; } } //---------------------------------------- ......... ///get metadata for (size_t i = 0; i < kNumEntries; ++i) { const char *value; if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) { status = client.addStringTag(kKeyMap[i].tag, value); if (status != OK) { return MEDIA_SCAN_RESULT_ERROR; } } } return MEDIA_SCAN_RESULT_OK;}