OSDN Git Service

stagefright-plugins: Parse file metadata tags
authorSteve Kondik <steve@cyngn.com>
Mon, 4 Jan 2016 09:56:36 +0000 (01:56 -0800)
committerSteve Kondik <steve@cyngn.com>
Mon, 4 Jan 2016 10:59:16 +0000 (02:59 -0800)
 * Convert from AVFormat tags into the corresponding Android
   tags when file metadata is requested.
 * Also extract embedded album art.

Change-Id: I49aec64dc30c9afd6510a25f8c2261029d8bdadf

extractor/FFmpegExtractor.cpp
extractor/FFmpegExtractor.h
utils/codec_utils.cpp
utils/codec_utils.h

index d881209..2ff3345 100644 (file)
@@ -116,7 +116,8 @@ FFmpegExtractor::FFmpegExtractor(const sp<DataSource> &source, const sp<AMessage
       mInitCheck(NO_INIT),
       mFFmpegInited(false),
       mFormatCtx(NULL),
-      mReaderThreadStarted(false) {
+      mReaderThreadStarted(false),
+      mParsedMetadata(false) {
     ALOGV("FFmpegExtractor::FFmpegExtractor");
 
     fetchStuffsFromSniffedMeta(meta);
@@ -198,6 +199,11 @@ sp<MetaData> FFmpegExtractor::getMetaData() {
         return NULL;
     }
 
+    if (!mParsedMetadata) {
+        parseMetadataTags(mFormatCtx, mMeta);
+        mParsedMetadata = true;
+    }
+
     return mMeta;
 }
 
index 141e25d..8fe3d9a 100644 (file)
@@ -130,6 +130,8 @@ private:
     static void *ReaderWrapper(void *me);
     void readerEntry();
 
+    bool mParsedMetadata;
+
     DISALLOW_EVIL_CONSTRUCTORS(FFmpegExtractor);
 };
 
index b228e9e..5cf30de 100644 (file)
@@ -519,5 +519,72 @@ int getDivXVersion(AVCodecContext *avctx)
     return -1;
 }
 
+status_t parseMetadataTags(AVFormatContext *ctx, const sp<MetaData> &meta) {
+    if (meta == NULL || ctx == NULL) {
+        return NO_INIT;
+    }
+
+    AVDictionary *dict = ctx->metadata;
+    if (dict == NULL) {
+        return NO_INIT;
+    }
+
+    struct MetadataMapping {
+        const char *from;
+        int to;
+    };
+
+    // avformat -> android mapping
+    static const MetadataMapping kMap[] = {
+        { "track", kKeyCDTrackNumber },
+        { "disc", kKeyDiscNumber },
+        { "album", kKeyAlbum },
+        { "artist", kKeyArtist },
+        { "album_artist", kKeyAlbumArtist },
+        { "composer", kKeyComposer },
+        { "date", kKeyDate },
+        { "genre", kKeyGenre },
+        { "title", kKeyTitle },
+        { "year", kKeyYear },
+        { "compilation", kKeyCompilation },
+        { "location", kKeyLocation },
+    };
+
+    static const size_t kNumEntries = sizeof(kMap) / sizeof(kMap[0]);
+
+    for (size_t i = 0; i < kNumEntries; ++i) {
+        AVDictionaryEntry *entry = av_dict_get(dict, kMap[i].from, NULL, 0);
+        if (entry != NULL) {
+            ALOGV("found key %s with value %s", entry->key, entry->value);
+            meta->setCString(kMap[i].to, entry->value);
+        }
+    }
+
+    // now look for album art- this will be in a separate stream
+    for (size_t i = 0; i < ctx->nb_streams; i++) {
+        if (ctx->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) {
+            AVPacket pkt = ctx->streams[i]->attached_pic;
+            if (pkt.size > 0) {
+                if (ctx->streams[i]->codec != NULL) {
+                    const char *mime;
+                    if (ctx->streams[i]->codec->codec_id == AV_CODEC_ID_MJPEG) {
+                        mime = MEDIA_MIMETYPE_IMAGE_JPEG;
+                    } else if (ctx->streams[i]->codec->codec_id == AV_CODEC_ID_PNG) {
+                        mime = "image/png";
+                    } else {
+                        mime = NULL;
+                    }
+                    if (mime != NULL) {
+                        ALOGV("found albumart in stream %d with type %s len %d", i, mime, pkt.size);
+                        meta->setData(kKeyAlbumArt, MetaData::TYPE_NONE, pkt.data, pkt.size);
+                        meta->setCString(kKeyAlbumArtMIME, mime);
+                    }
+                }
+            }
+        }
+    }
+    return OK;
+}
+
 }  // namespace android
 
index b630e07..c363e18 100644 (file)
@@ -66,6 +66,8 @@ status_t convertNal2AnnexB(uint8_t *dst, size_t dst_size,
 
 int getDivXVersion(AVCodecContext *avctx);
 
+status_t parseMetadataTags(AVFormatContext *ctx, const sp<MetaData> &meta);
+
 }  // namespace android
 
 #endif  // CODEC_UTILS_H_