StagefrightMetadataRetriever.cpp revision 29357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47
12a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber/*
2fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * Copyright (C) 2009 The Android Open Source Project
3fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *
4fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * you may not use this file except in compliance with the License.
6fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * You may obtain a copy of the License at
7fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *
8fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *
10fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * Unless required by applicable law or agreed to in writing, software
11fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * See the License for the specific language governing permissions and
14fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * limitations under the License.
15fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber */
162a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
172a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber//#define LOG_NDEBUG 0
182a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#define LOG_TAG "StagefrightMetadataRetriever"
192a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <utils/Log.h>
202a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
2167e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber#include "include/StagefrightMetadataRetriever.h"
222a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
232a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/ColorConverter.h>
242a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/DataSource.h>
25bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber#include <media/stagefright/FileSource.h>
262a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/MediaDebug.h>
272a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/MediaExtractor.h>
282a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/MetaData.h>
292a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/OMXCodec.h>
307a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include <media/stagefright/MediaDefs.h>
312a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
322a4a7d5af053a17586a262a1267ba993e31790f1Andreas Hubernamespace android {
332a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
34fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberStagefrightMetadataRetriever::StagefrightMetadataRetriever()
35fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    : mParsedMetaData(false),
36fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mAlbumArt(NULL) {
373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("StagefrightMetadataRetriever()");
382a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
392a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    DataSource::RegisterDefaultSniffers();
402a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    CHECK_EQ(mClient.connect(), OK);
412a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}
422a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
432a4a7d5af053a17586a262a1267ba993e31790f1Andreas HuberStagefrightMetadataRetriever::~StagefrightMetadataRetriever() {
443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("~StagefrightMetadataRetriever()");
45fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
46fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    delete mAlbumArt;
47fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mAlbumArt = NULL;
48fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
492a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    mClient.disconnect();
502a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}
512a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
52af8791e112c8072452bd14ef3c43a47511d19542Andreas Huberstatus_t StagefrightMetadataRetriever::setDataSource(
53af8791e112c8072452bd14ef3c43a47511d19542Andreas Huber        const char *uri, const KeyedVector<String8, String8> *headers) {
543856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setDataSource(%s)", uri);
552a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
56fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mParsedMetaData = false;
57fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mMetaData.clear();
58fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    delete mAlbumArt;
59fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mAlbumArt = NULL;
60fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
61af8791e112c8072452bd14ef3c43a47511d19542Andreas Huber    mSource = DataSource::CreateFromURI(uri, headers);
62fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
63fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mSource == NULL) {
64fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return UNKNOWN_ERROR;
65fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
66fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
67fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mExtractor = MediaExtractor::Create(mSource);
68fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
69fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mExtractor == NULL) {
70fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mSource.clear();
712a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
72fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return UNKNOWN_ERROR;
73fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
74fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
75fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return OK;
762a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}
772a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
78fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber// Warning caller retains ownership of the filedescriptor! Dup it if necessary.
792a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huberstatus_t StagefrightMetadataRetriever::setDataSource(
802a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber        int fd, int64_t offset, int64_t length) {
81fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    fd = dup(fd);
82fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
842a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
85fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mParsedMetaData = false;
86fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mMetaData.clear();
87fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    delete mAlbumArt;
88fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mAlbumArt = NULL;
89fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
90fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mSource = new FileSource(fd, offset, length);
91fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
92fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    status_t err;
93fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if ((err = mSource->initCheck()) != OK) {
94fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mSource.clear();
95fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
96fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return err;
97fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
98fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
99fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mExtractor = MediaExtractor::Create(mSource);
100fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
101fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mExtractor == NULL) {
102fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mSource.clear();
103fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
104fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return UNKNOWN_ERROR;
105fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
1062a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1072a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    return OK;
1082a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}
1092a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1104e202e779a8495091ab189fd88fc295a3e619c61Andreas Huberstatic VideoFrame *extractVideoFrameWithCodecFlags(
1114e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        OMXClient *client,
1124e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        const sp<MetaData> &trackMeta,
11316afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong        const sp<MediaSource> &source,
11416afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong        uint32_t flags,
11516afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong        int64_t frameTimeUs,
11616afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong        int seekMode) {
1172a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    sp<MediaSource> decoder =
1182a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber        OMXCodec::Create(
1194e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber                client->interface(), source->getFormat(), false, source,
120f3712f026aad1fc46b1df18d1dba718281e39726Andreas Huber                NULL, flags | OMXCodec::kClientNeedsFramebuffer);
1212a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1222a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    if (decoder.get() == NULL) {
1233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("unable to instantiate video decoder.");
1242a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1252a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber        return NULL;
1262a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    }
1272a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
128139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber    status_t err = decoder->start();
129139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber    if (err != OK) {
1305ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("OMXCodec::start returned error %d (0x%08x)\n", err, err);
131139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber        return NULL;
132139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber    }
1332a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
134c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber    // Read one output buffer, ignore format change notifications
135c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber    // and spurious empty buffers.
136c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber
1377e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    MediaSource::ReadOptions options;
13816afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong    if (seekMode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC ||
13916afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong        seekMode > MediaSource::ReadOptions::SEEK_CLOSEST) {
14016afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong
14129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Unknown seek mode: %d", seekMode);
14216afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong        return NULL;
14316afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong    }
14416afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong
14516afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong    MediaSource::ReadOptions::SeekMode mode =
14616afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong            static_cast<MediaSource::ReadOptions::SeekMode>(seekMode);
14716afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong
1487e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    int64_t thumbNailTime;
149cb0cb25002f1b5fe0d02c997bac487b5b6c5c682Andreas Huber    if (frameTimeUs < 0) {
15021af757836167a328ddf1c0381909d53941528c4Andreas Huber        if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)
15121af757836167a328ddf1c0381909d53941528c4Andreas Huber                || thumbNailTime < 0) {
152cb0cb25002f1b5fe0d02c997bac487b5b6c5c682Andreas Huber            thumbNailTime = 0;
153cb0cb25002f1b5fe0d02c997bac487b5b6c5c682Andreas Huber        }
15416afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong        options.setSeekTo(thumbNailTime, mode);
1554e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    } else {
1564e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        thumbNailTime = -1;
15716afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong        options.setSeekTo(frameTimeUs, mode);
1587e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
1597e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
160c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber    MediaBuffer *buffer = NULL;
1617f281f87670c63775ea1ae8b24af31822d5ad416Andreas Huber    do {
162c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber        if (buffer != NULL) {
163c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber            buffer->release();
164c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber            buffer = NULL;
165c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber        }
1667e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        err = decoder->read(&buffer, &options);
1677e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        options.clearSeekTo();
168c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber    } while (err == INFO_FORMAT_CHANGED
169c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber             || (buffer != NULL && buffer->range_length() == 0));
1702a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1712a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    if (err != OK) {
1722a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber        CHECK_EQ(buffer, NULL);
1732a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1743856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("decoding frame failed.");
1752a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber        decoder->stop();
1762a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1772a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber        return NULL;
1782a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    }
1792a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("successfully decoded video frame.");
1812a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1822b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber    int32_t unreadable;
1832b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber    if (buffer->meta_data()->findInt32(kKeyIsUnreadable, &unreadable)
1842b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber            && unreadable != 0) {
1853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("video frame is unreadable, decoder does not give us access "
1862b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber             "to the video data.");
1872b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber
1882b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber        buffer->release();
1892b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber        buffer = NULL;
1902b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber
1912b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber        decoder->stop();
1922b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber
1932b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber        return NULL;
1942b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber    }
1952b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber
1964e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    int64_t timeUs;
1974e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
1984e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    if (thumbNailTime >= 0) {
1994e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        if (timeUs != thumbNailTime) {
2004e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber            const char *mime;
2014e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber            CHECK(trackMeta->findCString(kKeyMIMEType, &mime));
2024e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("thumbNailTime = %lld us, timeUs = %lld us, mime = %s",
2044e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber                 thumbNailTime, timeUs, mime);
2054e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        }
2064e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    }
2074e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2084e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    sp<MetaData> meta = decoder->getFormat();
2092a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
2102a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    int32_t width, height;
2112a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    CHECK(meta->findInt32(kKeyWidth, &width));
2122a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    CHECK(meta->findInt32(kKeyHeight, &height));
2132a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
214f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    int32_t crop_left, crop_top, crop_right, crop_bottom;
215f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    if (!meta->findRect(
216f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                kKeyCropRect,
217f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber                &crop_left, &crop_top, &crop_right, &crop_bottom)) {
218f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber        crop_left = crop_top = 0;
219f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber        crop_right = width - 1;
220f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber        crop_bottom = height - 1;
221f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    }
222f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber
223ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong    int32_t rotationAngle;
224ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong    if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) {
225ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong        rotationAngle = 0;  // By default, no rotation
226ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong    }
227ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong
2282a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    VideoFrame *frame = new VideoFrame;
229f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    frame->mWidth = crop_right - crop_left + 1;
230f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    frame->mHeight = crop_bottom - crop_top + 1;
231f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    frame->mDisplayWidth = frame->mWidth;
232f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    frame->mDisplayHeight = frame->mHeight;
233f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber    frame->mSize = frame->mWidth * frame->mHeight * 2;
2342a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    frame->mData = new uint8_t[frame->mSize];
235ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong    frame->mRotationAngle = rotationAngle;
2362a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
2371d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong    int32_t displayWidth, displayHeight;
2381d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong    if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
2391d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong        frame->mDisplayWidth = displayWidth;
2401d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong    }
2411d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong    if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
2421d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong        frame->mDisplayHeight = displayHeight;
2431d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong    }
2441d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong
2452a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    int32_t srcFormat;
2462a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    CHECK(meta->findInt32(kKeyColorFormat, &srcFormat));
2472a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
2482a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    ColorConverter converter(
2492a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber            (OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565);
2502a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    CHECK(converter.isValid());
2512a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
252b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber    err = converter.convert(
2532a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber            (const uint8_t *)buffer->data() + buffer->range_offset(),
254f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber            width, height,
255f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber            crop_left, crop_top, crop_right, crop_bottom,
256f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber            frame->mData,
257f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber            frame->mWidth,
258f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber            frame->mHeight,
259f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber            0, 0, frame->mWidth - 1, frame->mHeight - 1);
2602a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
2612a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    buffer->release();
2622a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    buffer = NULL;
2632a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
2642a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    decoder->stop();
2652a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
266b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber    if (err != OK) {
26729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Colorconverter failed to convert frame.");
268b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber
269b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber        delete frame;
270b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber        frame = NULL;
271b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber    }
272b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber
2732a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    return frame;
2742a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}
2752a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
27616afe2fb439cab6125bb46a07a8078d4ce1c1ea5James DongVideoFrame *StagefrightMetadataRetriever::getFrameAtTime(
27716afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong        int64_t timeUs, int option) {
2784e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("getFrameAtTime: %lld us option: %d", timeUs, option);
28093e1fb99a0c66784b49b105ce84a23baf054ee9cAndreas Huber
2814e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    if (mExtractor.get() == NULL) {
2823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("no extractor.");
2834e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        return NULL;
2844e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    }
2854e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
286e7484f36061a60aadadb01143d84964d931aa837Andreas Huber    sp<MetaData> fileMeta = mExtractor->getMetaData();
287e7484f36061a60aadadb01143d84964d931aa837Andreas Huber
288e7484f36061a60aadadb01143d84964d931aa837Andreas Huber    if (fileMeta == NULL) {
2893856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("extractor doesn't publish metadata, failed to initialize?");
290e7484f36061a60aadadb01143d84964d931aa837Andreas Huber        return NULL;
291e7484f36061a60aadadb01143d84964d931aa837Andreas Huber    }
292e7484f36061a60aadadb01143d84964d931aa837Andreas Huber
2938ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten    int32_t drm = 0;
294e7484f36061a60aadadb01143d84964d931aa837Andreas Huber    if (fileMeta->findInt32(kKeyIsDRM, &drm) && drm != 0) {
29529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("frame grab not allowed.");
2968ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten        return NULL;
2978ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten    }
2988ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten
2994e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    size_t n = mExtractor->countTracks();
3004e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    size_t i;
3014e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    for (i = 0; i < n; ++i) {
3024e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
3034e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
3044e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        const char *mime;
3054e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        CHECK(meta->findCString(kKeyMIMEType, &mime));
3064e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
3074e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        if (!strncasecmp(mime, "video/", 6)) {
3084e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber            break;
3094e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        }
3104e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    }
3114e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
3124e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    if (i == n) {
3133856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("no video track found.");
3144e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        return NULL;
3154e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    }
3164e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
3174e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
3184e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber            i, MediaExtractor::kIncludeExtensiveMetaData);
3194e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
3204e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    sp<MediaSource> source = mExtractor->getTrack(i);
3214e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
3224e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    if (source.get() == NULL) {
3233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("unable to instantiate video track.");
3244e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        return NULL;
3254e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    }
3264e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
327515e855eae78aa495da58356486aaa666cb57fd1James Dong    const void *data;
328515e855eae78aa495da58356486aaa666cb57fd1James Dong    uint32_t type;
329515e855eae78aa495da58356486aaa666cb57fd1James Dong    size_t dataSize;
330e7484f36061a60aadadb01143d84964d931aa837Andreas Huber    if (fileMeta->findData(kKeyAlbumArt, &type, &data, &dataSize)
331515e855eae78aa495da58356486aaa666cb57fd1James Dong            && mAlbumArt == NULL) {
332515e855eae78aa495da58356486aaa666cb57fd1James Dong        mAlbumArt = new MediaAlbumArt;
333515e855eae78aa495da58356486aaa666cb57fd1James Dong        mAlbumArt->mSize = dataSize;
334515e855eae78aa495da58356486aaa666cb57fd1James Dong        mAlbumArt->mData = new uint8_t[dataSize];
335515e855eae78aa495da58356486aaa666cb57fd1James Dong        memcpy(mAlbumArt->mData, data, dataSize);
336515e855eae78aa495da58356486aaa666cb57fd1James Dong    }
337515e855eae78aa495da58356486aaa666cb57fd1James Dong
3384e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    VideoFrame *frame =
3394e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        extractVideoFrameWithCodecFlags(
34016afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong                &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs,
34116afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong                timeUs, option);
3424e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
3434e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    if (frame == NULL) {
3443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("Software decoder failed to extract thumbnail, "
3454e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber             "trying hardware decoder.");
3464e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
34716afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong        frame = extractVideoFrameWithCodecFlags(&mClient, trackMeta, source, 0,
34816afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong                        timeUs, option);
3494e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    }
3504e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
3514e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    return frame;
3524e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber}
3534e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
3542a4a7d5af053a17586a262a1267ba993e31790f1Andreas HuberMediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() {
3553856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO");
3562a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
357fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mExtractor == NULL) {
358fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
359fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
360fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
361fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (!mParsedMetaData) {
362fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        parseMetaData();
363fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
364fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mParsedMetaData = true;
365fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
366fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
367fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mAlbumArt) {
368fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return new MediaAlbumArt(*mAlbumArt);
369fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
370fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
3712a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    return NULL;
3722a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}
3732a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
3742a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huberconst char *StagefrightMetadataRetriever::extractMetadata(int keyCode) {
375fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mExtractor == NULL) {
376fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
377fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
378fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
379fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (!mParsedMetaData) {
380fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        parseMetaData();
381fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
382fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mParsedMetaData = true;
383fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
384fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
385fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    ssize_t index = mMetaData.indexOfKey(keyCode);
386fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
387fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (index < 0) {
388fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
389fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
390fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
391fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return strdup(mMetaData.valueAt(index).string());
3922a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}
3932a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
394fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid StagefrightMetadataRetriever::parseMetaData() {
395fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    sp<MetaData> meta = mExtractor->getMetaData();
396fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
397e7484f36061a60aadadb01143d84964d931aa837Andreas Huber    if (meta == NULL) {
3983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("extractor doesn't publish metadata, failed to initialize?");
399e7484f36061a60aadadb01143d84964d931aa837Andreas Huber        return;
400e7484f36061a60aadadb01143d84964d931aa837Andreas Huber    }
401e7484f36061a60aadadb01143d84964d931aa837Andreas Huber
402fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    struct Map {
403fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        int from;
404fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        int to;
405fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    };
406fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    static const Map kMap[] = {
4077be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber        { kKeyMIMEType, METADATA_KEY_MIMETYPE },
408bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber        { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER },
4096c8a9a4132337a3419a72a735f0b40df0b82061fMarco Nelissen        { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER },
410fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        { kKeyAlbum, METADATA_KEY_ALBUM },
411fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        { kKeyArtist, METADATA_KEY_ARTIST },
41266ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST },
413bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber        { kKeyAuthor, METADATA_KEY_AUTHOR },
414fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        { kKeyComposer, METADATA_KEY_COMPOSER },
415bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber        { kKeyDate, METADATA_KEY_DATE },
416fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        { kKeyGenre, METADATA_KEY_GENRE },
417fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        { kKeyTitle, METADATA_KEY_TITLE },
418fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        { kKeyYear, METADATA_KEY_YEAR },
41972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        { kKeyWriter, METADATA_KEY_WRITER },
42011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        { kKeyCompilation, METADATA_KEY_COMPILATION },
4214948818cb91176df74c972ac27b2f392b5d148bcJames Dong        { kKeyLocation, METADATA_KEY_LOCATION },
422fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    };
423fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
424fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
425fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i < kNumMapEntries; ++i) {
426fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const char *value;
427fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (meta->findCString(kMap[i].from, &value)) {
428fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mMetaData.add(kMap[i].to, String8(value));
429fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
430fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
431fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
432fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    const void *data;
433fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    uint32_t type;
434fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t dataSize;
435515e855eae78aa495da58356486aaa666cb57fd1James Dong    if (meta->findData(kKeyAlbumArt, &type, &data, &dataSize)
436515e855eae78aa495da58356486aaa666cb57fd1James Dong            && mAlbumArt == NULL) {
437fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mAlbumArt = new MediaAlbumArt;
438fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mAlbumArt->mSize = dataSize;
439fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mAlbumArt->mData = new uint8_t[dataSize];
440fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        memcpy(mAlbumArt->mData, data, dataSize);
441fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
442fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
443bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber    size_t numTracks = mExtractor->countTracks();
444bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber
445bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber    char tmp[32];
446bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber    sprintf(tmp, "%d", numTracks);
447bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber
448bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber    mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp));
449bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber
4502256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber    bool hasAudio = false;
4512256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber    bool hasVideo = false;
4522256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber    int32_t videoWidth = -1;
4532256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber    int32_t videoHeight = -1;
4542256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber    int32_t audioBitrate = -1;
4552256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber
456fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    // The overall duration is the duration of the longest track.
457fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    int64_t maxDurationUs = 0;
4587a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    String8 timedTextLang;
459bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber    for (size_t i = 0; i < numTracks; ++i) {
460fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);
461fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
462fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        int64_t durationUs;
463fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (trackMeta->findInt64(kKeyDuration, &durationUs)) {
464fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (durationUs > maxDurationUs) {
465fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                maxDurationUs = durationUs;
466fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
467fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
4682256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber
4692256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber        const char *mime;
4702256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber        if (trackMeta->findCString(kKeyMIMEType, &mime)) {
4712256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber            if (!hasAudio && !strncasecmp("audio/", mime, 6)) {
4722256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber                hasAudio = true;
4732256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber
4742256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber                if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) {
4752256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber                    audioBitrate = -1;
4762256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber                }
4772256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber            } else if (!hasVideo && !strncasecmp("video/", mime, 6)) {
4782256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber                hasVideo = true;
4792256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber
4802256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber                CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth));
4812256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber                CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight));
4827a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
4837a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                const char *lang;
4847a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                trackMeta->findCString(kKeyMediaLanguage, &lang);
4857a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                timedTextLang.append(String8(lang));
4867a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                timedTextLang.append(String8(":"));
4872256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber            }
4882256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber        }
489fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
490fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
4917a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    // To save the language codes for all timed text tracks
4927a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    // If multiple text tracks present, the format will look
4937a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    // like "eng:chi"
4947a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    if (!timedTextLang.isEmpty()) {
4957a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        mMetaData.add(METADATA_KEY_TIMED_TEXT_LANGUAGES, timedTextLang);
4967a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    }
4977a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
498fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    // The duration value is a string representing the duration in ms.
499fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000);
500fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
501093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
5022256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber    if (hasAudio) {
5032256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber        mMetaData.add(METADATA_KEY_HAS_AUDIO, String8("yes"));
5042256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber    }
5052256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber
5062256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber    if (hasVideo) {
5072256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber        mMetaData.add(METADATA_KEY_HAS_VIDEO, String8("yes"));
5082256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber
5092256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber        sprintf(tmp, "%d", videoWidth);
5102256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber        mMetaData.add(METADATA_KEY_VIDEO_WIDTH, String8(tmp));
5112256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber
5122256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber        sprintf(tmp, "%d", videoHeight);
5132256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber        mMetaData.add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp));
5142256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber    }
5152256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber
5162256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber    if (numTracks == 1 && hasAudio && audioBitrate >= 0) {
5171d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong        sprintf(tmp, "%d", audioBitrate);
5182256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber        mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
5192256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber    } else {
5202256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber        off64_t sourceSize;
5212256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber        if (mSource->getSize(&sourceSize) == OK) {
5222256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber            int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs);
5232256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber
5242256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber            sprintf(tmp, "%lld", avgBitRate);
5252256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber            mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
5262256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber        }
5272256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber    }
5282256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber
529093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    if (numTracks == 1) {
530093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        const char *fileMIME;
531093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        CHECK(meta->findCString(kKeyMIMEType, &fileMIME));
532093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
533093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        if (!strcasecmp(fileMIME, "video/x-matroska")) {
534093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            sp<MetaData> trackMeta = mExtractor->getTrackMetaData(0);
535093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            const char *trackMIME;
536093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            CHECK(trackMeta->findCString(kKeyMIMEType, &trackMIME));
537093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber
538093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            if (!strncasecmp("audio/", trackMIME, 6)) {
539093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                // The matroska file only contains a single audio track,
540093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                // rewrite its mime type.
541093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                mMetaData.add(
542093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber                        METADATA_KEY_MIMETYPE, String8("audio/x-matroska"));
543093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber            }
544093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        }
545093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber    }
5460d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang
5470d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang    // To check whether the media file is drm-protected
5480d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang    if (mExtractor->getDrmFlag()) {
5490d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang        mMetaData.add(METADATA_KEY_IS_DRM, String8("1"));
5500d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang    }
551fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
552fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
5532a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}  // namespace android
554