153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber/*
2aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber * Copyright (C) 2009 The Android Open Source Project
3aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber *
4aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber * you may not use this file except in compliance with the License.
6aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber * You may obtain a copy of the License at
7aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber *
8aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber *
10aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber * Unless required by applicable law or agreed to in writing, software
11aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber * See the License for the specific language governing permissions and
14aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber * limitations under the License.
15aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber */
1653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
1753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber//#define LOG_NDEBUG 0
1853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber#define LOG_TAG "StagefrightMetadataRetriever"
1953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber#include <utils/Log.h>
2053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
21e4a838051de5e56f44c71117073a035b804b5d04Andreas Huber#include "include/StagefrightMetadataRetriever.h"
2253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
2353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber#include <media/stagefright/ColorConverter.h>
2453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber#include <media/stagefright/DataSource.h>
2527366fc9540cb642ee4856957dabffe7ddf1f901Andreas Huber#include <media/stagefright/FileSource.h>
2653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber#include <media/stagefright/MediaDebug.h>
2753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber#include <media/stagefright/MediaExtractor.h>
2853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber#include <media/stagefright/MetaData.h>
2953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber#include <media/stagefright/OMXCodec.h>
30c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang#include <media/stagefright/MediaDefs.h>
3153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
3253a76bd0c918082847e52570c307ed3ba325992dAndreas Hubernamespace android {
3353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
34aee3c6394a367abf283936cb8b8bd85ed028c050Andreas HuberStagefrightMetadataRetriever::StagefrightMetadataRetriever()
35aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    : mParsedMetaData(false),
36aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber      mAlbumArt(NULL) {
3753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    LOGV("StagefrightMetadataRetriever()");
3853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
3953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    DataSource::RegisterDefaultSniffers();
4053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK_EQ(mClient.connect(), OK);
4153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
4253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
4353a76bd0c918082847e52570c307ed3ba325992dAndreas HuberStagefrightMetadataRetriever::~StagefrightMetadataRetriever() {
4453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    LOGV("~StagefrightMetadataRetriever()");
45aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
46aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    delete mAlbumArt;
47aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mAlbumArt = NULL;
48aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
4953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    mClient.disconnect();
5053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
5153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
525b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huberstatus_t StagefrightMetadataRetriever::setDataSource(
535b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber        const char *uri, const KeyedVector<String8, String8> *headers) {
5453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    LOGV("setDataSource(%s)", uri);
5553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
56aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mParsedMetaData = false;
57aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mMetaData.clear();
58aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    delete mAlbumArt;
59aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mAlbumArt = NULL;
60aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
615b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber    mSource = DataSource::CreateFromURI(uri, headers);
62aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
63aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mSource == NULL) {
64aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return UNKNOWN_ERROR;
65aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
66aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
67aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mExtractor = MediaExtractor::Create(mSource);
68aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
69aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mExtractor == NULL) {
70aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mSource.clear();
7153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
72aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return UNKNOWN_ERROR;
73aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
74aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
75aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    return OK;
7653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
7753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
78aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber// Warning caller retains ownership of the filedescriptor! Dup it if necessary.
7953a76bd0c918082847e52570c307ed3ba325992dAndreas Huberstatus_t StagefrightMetadataRetriever::setDataSource(
8053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        int fd, int64_t offset, int64_t length) {
81aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    fd = dup(fd);
82aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
8353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
8453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
85aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mParsedMetaData = false;
86aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mMetaData.clear();
87aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    delete mAlbumArt;
88aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mAlbumArt = NULL;
89aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
90aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mSource = new FileSource(fd, offset, length);
91aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
92aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    status_t err;
93aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if ((err = mSource->initCheck()) != OK) {
94aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mSource.clear();
95aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
96aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return err;
97aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
98aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
99aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mExtractor = MediaExtractor::Create(mSource);
100aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
101aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mExtractor == NULL) {
102aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mSource.clear();
103aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
104aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return UNKNOWN_ERROR;
105aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
10653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
10753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    return OK;
10853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
10953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
1100ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huberstatic VideoFrame *extractVideoFrameWithCodecFlags(
1110ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        OMXClient *client,
1120ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        const sp<MetaData> &trackMeta,
113faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        const sp<MediaSource> &source,
114faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        uint32_t flags,
115faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        int64_t frameTimeUs,
116faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        int seekMode) {
11753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    sp<MediaSource> decoder =
11853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        OMXCodec::Create(
1190ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber                client->interface(), source->getFormat(), false, source,
1205a40e394f1e6b0511542e171eaf4c3e5927efc13Andreas Huber                NULL, flags | OMXCodec::kClientNeedsFramebuffer);
12153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
12253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    if (decoder.get() == NULL) {
123ad28543022101d0b01845e3f53dcd57e524816efAndreas Huber        LOGV("unable to instantiate video decoder.");
12453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
12553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        return NULL;
12653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    }
12753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
1281919e5af3d8eb8bcf08e50efae2e79eaf065cf6bAndreas Huber    status_t err = decoder->start();
1291919e5af3d8eb8bcf08e50efae2e79eaf065cf6bAndreas Huber    if (err != OK) {
1301919e5af3d8eb8bcf08e50efae2e79eaf065cf6bAndreas Huber        LOGW("OMXCodec::start returned error %d (0x%08x)\n", err, err);
1311919e5af3d8eb8bcf08e50efae2e79eaf065cf6bAndreas Huber        return NULL;
1321919e5af3d8eb8bcf08e50efae2e79eaf065cf6bAndreas Huber    }
13353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
134f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    // Read one output buffer, ignore format change notifications
135f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    // and spurious empty buffers.
136f68c168d366e8aad58454917f96344398a02efd8Andreas Huber
137e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    MediaSource::ReadOptions options;
138faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong    if (seekMode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC ||
139faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        seekMode > MediaSource::ReadOptions::SEEK_CLOSEST) {
140faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong
141faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        LOGE("Unknown seek mode: %d", seekMode);
142faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        return NULL;
143faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong    }
144faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong
145faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong    MediaSource::ReadOptions::SeekMode mode =
146faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong            static_cast<MediaSource::ReadOptions::SeekMode>(seekMode);
147faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong
148e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    int64_t thumbNailTime;
149b1d49ded620fc9c80f793f32742bf1fef0281271Andreas Huber    if (frameTimeUs < 0) {
15087312e9a810f31a3de76eb7b41165fc02f552cc3Andreas Huber        if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)
15187312e9a810f31a3de76eb7b41165fc02f552cc3Andreas Huber                || thumbNailTime < 0) {
152b1d49ded620fc9c80f793f32742bf1fef0281271Andreas Huber            thumbNailTime = 0;
153b1d49ded620fc9c80f793f32742bf1fef0281271Andreas Huber        }
154faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        options.setSeekTo(thumbNailTime, mode);
1550ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    } else {
1560ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        thumbNailTime = -1;
157faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        options.setSeekTo(frameTimeUs, mode);
158e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    }
159e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber
160f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    MediaBuffer *buffer = NULL;
161cfd55579c2e20514b181809dfaf30bd6f7e04c7eAndreas Huber    do {
162f68c168d366e8aad58454917f96344398a02efd8Andreas Huber        if (buffer != NULL) {
163f68c168d366e8aad58454917f96344398a02efd8Andreas Huber            buffer->release();
164f68c168d366e8aad58454917f96344398a02efd8Andreas Huber            buffer = NULL;
165f68c168d366e8aad58454917f96344398a02efd8Andreas Huber        }
166e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        err = decoder->read(&buffer, &options);
167e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        options.clearSeekTo();
168f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    } while (err == INFO_FORMAT_CHANGED
169f68c168d366e8aad58454917f96344398a02efd8Andreas Huber             || (buffer != NULL && buffer->range_length() == 0));
17053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
17153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    if (err != OK) {
17253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        CHECK_EQ(buffer, NULL);
17353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
174ad28543022101d0b01845e3f53dcd57e524816efAndreas Huber        LOGV("decoding frame failed.");
17553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        decoder->stop();
17653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
17753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        return NULL;
17853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    }
17953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
180ad28543022101d0b01845e3f53dcd57e524816efAndreas Huber    LOGV("successfully decoded video frame.");
18153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
1821e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber    int32_t unreadable;
1831e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber    if (buffer->meta_data()->findInt32(kKeyIsUnreadable, &unreadable)
1841e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber            && unreadable != 0) {
1851e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber        LOGV("video frame is unreadable, decoder does not give us access "
1861e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber             "to the video data.");
1871e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber
1881e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber        buffer->release();
1891e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber        buffer = NULL;
1901e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber
1911e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber        decoder->stop();
1921e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber
1931e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber        return NULL;
1941e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber    }
1951e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber
1960ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    int64_t timeUs;
1970ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
1980ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (thumbNailTime >= 0) {
1990ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        if (timeUs != thumbNailTime) {
2000ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            const char *mime;
2010ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            CHECK(trackMeta->findCString(kKeyMIMEType, &mime));
2020ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2030ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            LOGV("thumbNailTime = %lld us, timeUs = %lld us, mime = %s",
2040ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber                 thumbNailTime, timeUs, mime);
2050ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        }
2060ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
2070ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2080ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    sp<MetaData> meta = decoder->getFormat();
20953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
21053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    int32_t width, height;
21153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(meta->findInt32(kKeyWidth, &width));
21253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(meta->findInt32(kKeyHeight, &height));
21353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
2141bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    int32_t crop_left, crop_top, crop_right, crop_bottom;
2151bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    if (!meta->findRect(
2161bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber                kKeyCropRect,
2171bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber                &crop_left, &crop_top, &crop_right, &crop_bottom)) {
2181bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber        crop_left = crop_top = 0;
2191bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber        crop_right = width - 1;
2201bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber        crop_bottom = height - 1;
2211bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    }
2221bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber
22353ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong    int32_t rotationAngle;
22453ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong    if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) {
22553ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong        rotationAngle = 0;  // By default, no rotation
22653ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong    }
22753ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong
22853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    VideoFrame *frame = new VideoFrame;
2291bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    frame->mWidth = crop_right - crop_left + 1;
2301bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    frame->mHeight = crop_bottom - crop_top + 1;
2311bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    frame->mDisplayWidth = frame->mWidth;
2321bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    frame->mDisplayHeight = frame->mHeight;
2331bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    frame->mSize = frame->mWidth * frame->mHeight * 2;
23453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    frame->mData = new uint8_t[frame->mSize];
23553ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong    frame->mRotationAngle = rotationAngle;
23653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
2379f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong    int32_t displayWidth, displayHeight;
2389f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong    if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
2399f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong        frame->mDisplayWidth = displayWidth;
2409f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong    }
2419f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong    if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
2429f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong        frame->mDisplayHeight = displayHeight;
2439f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong    }
2449f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong
24553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    int32_t srcFormat;
24653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(meta->findInt32(kKeyColorFormat, &srcFormat));
24753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
24853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    ColorConverter converter(
24953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber            (OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565);
25053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(converter.isValid());
25153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
252c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber    err = converter.convert(
25353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber            (const uint8_t *)buffer->data() + buffer->range_offset(),
2541bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber            width, height,
2551bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber            crop_left, crop_top, crop_right, crop_bottom,
2561bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber            frame->mData,
2571bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber            frame->mWidth,
2581bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber            frame->mHeight,
2591bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber            0, 0, frame->mWidth - 1, frame->mHeight - 1);
26053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
26153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    buffer->release();
26253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    buffer = NULL;
26353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
26453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    decoder->stop();
26553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
266c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber    if (err != OK) {
267c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber        LOGE("Colorconverter failed to convert frame.");
268c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber
269c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber        delete frame;
270c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber        frame = NULL;
271c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber    }
272c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber
27353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    return frame;
27453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
27553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
276faf09ba9405ff019b5ca7e2317debe4ff269d4f8James DongVideoFrame *StagefrightMetadataRetriever::getFrameAtTime(
277faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        int64_t timeUs, int option) {
2780ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
279faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong    LOGV("getFrameAtTime: %lld us option: %d", timeUs, option);
280e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber
2810ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (mExtractor.get() == NULL) {
2820ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("no extractor.");
2830ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        return NULL;
2840ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
2850ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
286612e16191a31758627dd039dec22f0b122c33ce6Andreas Huber    sp<MetaData> fileMeta = mExtractor->getMetaData();
287612e16191a31758627dd039dec22f0b122c33ce6Andreas Huber
288612e16191a31758627dd039dec22f0b122c33ce6Andreas Huber    if (fileMeta == NULL) {
289612e16191a31758627dd039dec22f0b122c33ce6Andreas Huber        LOGV("extractor doesn't publish metadata, failed to initialize?");
290612e16191a31758627dd039dec22f0b122c33ce6Andreas Huber        return NULL;
291612e16191a31758627dd039dec22f0b122c33ce6Andreas Huber    }
292612e16191a31758627dd039dec22f0b122c33ce6Andreas Huber
2935f63069f3256f8ba253d1331c5bef0d162d2bd67Glenn Kasten    int32_t drm = 0;
294612e16191a31758627dd039dec22f0b122c33ce6Andreas Huber    if (fileMeta->findInt32(kKeyIsDRM, &drm) && drm != 0) {
2955f63069f3256f8ba253d1331c5bef0d162d2bd67Glenn Kasten        LOGE("frame grab not allowed.");
2965f63069f3256f8ba253d1331c5bef0d162d2bd67Glenn Kasten        return NULL;
2975f63069f3256f8ba253d1331c5bef0d162d2bd67Glenn Kasten    }
2985f63069f3256f8ba253d1331c5bef0d162d2bd67Glenn Kasten
2990ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    size_t n = mExtractor->countTracks();
3000ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    size_t i;
3010ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    for (i = 0; i < n; ++i) {
3020ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
3030ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
3040ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        const char *mime;
3050ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        CHECK(meta->findCString(kKeyMIMEType, &mime));
3060ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
3070ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        if (!strncasecmp(mime, "video/", 6)) {
3080ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            break;
3090ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        }
3100ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
3110ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
3120ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (i == n) {
3130ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("no video track found.");
3140ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        return NULL;
3150ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
3160ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
3170ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
3180ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            i, MediaExtractor::kIncludeExtensiveMetaData);
3190ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
3200ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    sp<MediaSource> source = mExtractor->getTrack(i);
3210ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
3220ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (source.get() == NULL) {
3230ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("unable to instantiate video track.");
3240ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        return NULL;
3250ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
3260ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
327e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong    const void *data;
328e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong    uint32_t type;
329e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong    size_t dataSize;
330612e16191a31758627dd039dec22f0b122c33ce6Andreas Huber    if (fileMeta->findData(kKeyAlbumArt, &type, &data, &dataSize)
331e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong            && mAlbumArt == NULL) {
332e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong        mAlbumArt = new MediaAlbumArt;
333e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong        mAlbumArt->mSize = dataSize;
334e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong        mAlbumArt->mData = new uint8_t[dataSize];
335e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong        memcpy(mAlbumArt->mData, data, dataSize);
336e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong    }
337e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong
3380ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    VideoFrame *frame =
3390ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        extractVideoFrameWithCodecFlags(
340faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong                &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs,
341faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong                timeUs, option);
3420ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
3430ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (frame == NULL) {
3440ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("Software decoder failed to extract thumbnail, "
3450ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber             "trying hardware decoder.");
3460ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
347faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        frame = extractVideoFrameWithCodecFlags(&mClient, trackMeta, source, 0,
348faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong                        timeUs, option);
3490ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
3500ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
3510ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    return frame;
3520ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber}
3530ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
35453a76bd0c918082847e52570c307ed3ba325992dAndreas HuberMediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() {
35553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    LOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO");
35653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
357aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mExtractor == NULL) {
358aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return NULL;
359aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
360aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
361aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (!mParsedMetaData) {
362aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        parseMetaData();
363aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
364aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mParsedMetaData = true;
365aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
366aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
367aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mAlbumArt) {
368aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return new MediaAlbumArt(*mAlbumArt);
369aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
370aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
37153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    return NULL;
37253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
37353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
37453a76bd0c918082847e52570c307ed3ba325992dAndreas Huberconst char *StagefrightMetadataRetriever::extractMetadata(int keyCode) {
375aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mExtractor == NULL) {
376aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return NULL;
377aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
378aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
379aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (!mParsedMetaData) {
380aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        parseMetaData();
381aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
382aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mParsedMetaData = true;
383aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
384aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
385aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    ssize_t index = mMetaData.indexOfKey(keyCode);
386aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
387aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (index < 0) {
388aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return NULL;
389aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
390aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
391aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    return strdup(mMetaData.valueAt(index).string());
39253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
39353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
394aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Hubervoid StagefrightMetadataRetriever::parseMetaData() {
395aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    sp<MetaData> meta = mExtractor->getMetaData();
396aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
397612e16191a31758627dd039dec22f0b122c33ce6Andreas Huber    if (meta == NULL) {
398612e16191a31758627dd039dec22f0b122c33ce6Andreas Huber        LOGV("extractor doesn't publish metadata, failed to initialize?");
399612e16191a31758627dd039dec22f0b122c33ce6Andreas Huber        return;
400612e16191a31758627dd039dec22f0b122c33ce6Andreas Huber    }
401612e16191a31758627dd039dec22f0b122c33ce6Andreas Huber
402aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    struct Map {
403aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        int from;
404aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        int to;
405aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    };
406aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    static const Map kMap[] = {
4071cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber        { kKeyMIMEType, METADATA_KEY_MIMETYPE },
4083a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber        { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER },
409655306f8a80b3e9fc52daf458ef319a8ed8c564cMarco Nelissen        { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER },
410aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyAlbum, METADATA_KEY_ALBUM },
411aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyArtist, METADATA_KEY_ARTIST },
412c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST },
4133a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber        { kKeyAuthor, METADATA_KEY_AUTHOR },
414aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyComposer, METADATA_KEY_COMPOSER },
4153a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber        { kKeyDate, METADATA_KEY_DATE },
416aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyGenre, METADATA_KEY_GENRE },
417aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyTitle, METADATA_KEY_TITLE },
418aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyYear, METADATA_KEY_YEAR },
419c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        { kKeyWriter, METADATA_KEY_WRITER },
420ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen        { kKeyCompilation, METADATA_KEY_COMPILATION },
42177c500c9a1f763b31fb5a03c803b3523fcb72310James Dong        { kKeyLocation, METADATA_KEY_LOCATION },
422aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    };
423aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
424aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
425aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    for (size_t i = 0; i < kNumMapEntries; ++i) {
426aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        const char *value;
427aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        if (meta->findCString(kMap[i].from, &value)) {
428aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            mMetaData.add(kMap[i].to, String8(value));
429aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        }
430aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
431aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
432aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    const void *data;
433aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    uint32_t type;
434aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    size_t dataSize;
435e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong    if (meta->findData(kKeyAlbumArt, &type, &data, &dataSize)
436e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong            && mAlbumArt == NULL) {
437aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mAlbumArt = new MediaAlbumArt;
438aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mAlbumArt->mSize = dataSize;
439aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mAlbumArt->mData = new uint8_t[dataSize];
440aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        memcpy(mAlbumArt->mData, data, dataSize);
441aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
442aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
4433a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    size_t numTracks = mExtractor->countTracks();
4443a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber
4453a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    char tmp[32];
4463a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    sprintf(tmp, "%d", numTracks);
4473a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber
4483a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp));
4493a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber
450c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    bool hasAudio = false;
451c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    bool hasVideo = false;
452c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    int32_t videoWidth = -1;
453c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    int32_t videoHeight = -1;
454c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    int32_t audioBitrate = -1;
455c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
456aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    // The overall duration is the duration of the longest track.
457aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    int64_t maxDurationUs = 0;
458c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang    String8 timedTextLang;
4593a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    for (size_t i = 0; i < numTracks; ++i) {
460aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);
461aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
462aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        int64_t durationUs;
463aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        if (trackMeta->findInt64(kKeyDuration, &durationUs)) {
464aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            if (durationUs > maxDurationUs) {
465aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber                maxDurationUs = durationUs;
466aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            }
467aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        }
468c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
469c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        const char *mime;
470c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        if (trackMeta->findCString(kKeyMIMEType, &mime)) {
471c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber            if (!hasAudio && !strncasecmp("audio/", mime, 6)) {
472c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber                hasAudio = true;
473c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
474c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber                if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) {
475c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber                    audioBitrate = -1;
476c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber                }
477c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber            } else if (!hasVideo && !strncasecmp("video/", mime, 6)) {
478c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber                hasVideo = true;
479c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
480c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber                CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth));
481c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber                CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight));
482c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang            } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
483c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang                const char *lang;
484c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang                trackMeta->findCString(kKeyMediaLanguage, &lang);
485c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang                timedTextLang.append(String8(lang));
486c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang                timedTextLang.append(String8(":"));
487c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber            }
488c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        }
489aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
490aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
491c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang    // To save the language codes for all timed text tracks
492c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang    // If multiple text tracks present, the format will look
493c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang    // like "eng:chi"
494c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang    if (!timedTextLang.isEmpty()) {
495c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang        mMetaData.add(METADATA_KEY_TIMED_TEXT_LANGUAGES, timedTextLang);
496c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang    }
497c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang
498aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    // The duration value is a string representing the duration in ms.
499aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000);
500aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
501072f5247ef893e683728263a540bb93daafda376Andreas Huber
502c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    if (hasAudio) {
503c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        mMetaData.add(METADATA_KEY_HAS_AUDIO, String8("yes"));
504c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    }
505c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
506c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    if (hasVideo) {
507c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        mMetaData.add(METADATA_KEY_HAS_VIDEO, String8("yes"));
508c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
509c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        sprintf(tmp, "%d", videoWidth);
510c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        mMetaData.add(METADATA_KEY_VIDEO_WIDTH, String8(tmp));
511c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
512c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        sprintf(tmp, "%d", videoHeight);
513c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        mMetaData.add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp));
514c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    }
515c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
516c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    if (numTracks == 1 && hasAudio && audioBitrate >= 0) {
5179f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong        sprintf(tmp, "%d", audioBitrate);
518c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
519c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    } else {
520c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        off64_t sourceSize;
521c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        if (mSource->getSize(&sourceSize) == OK) {
522c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber            int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs);
523c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
524c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber            sprintf(tmp, "%lld", avgBitRate);
525c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber            mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
526c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        }
527c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    }
528c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
529072f5247ef893e683728263a540bb93daafda376Andreas Huber    if (numTracks == 1) {
530072f5247ef893e683728263a540bb93daafda376Andreas Huber        const char *fileMIME;
531072f5247ef893e683728263a540bb93daafda376Andreas Huber        CHECK(meta->findCString(kKeyMIMEType, &fileMIME));
532072f5247ef893e683728263a540bb93daafda376Andreas Huber
533072f5247ef893e683728263a540bb93daafda376Andreas Huber        if (!strcasecmp(fileMIME, "video/x-matroska")) {
534072f5247ef893e683728263a540bb93daafda376Andreas Huber            sp<MetaData> trackMeta = mExtractor->getTrackMetaData(0);
535072f5247ef893e683728263a540bb93daafda376Andreas Huber            const char *trackMIME;
536072f5247ef893e683728263a540bb93daafda376Andreas Huber            CHECK(trackMeta->findCString(kKeyMIMEType, &trackMIME));
537072f5247ef893e683728263a540bb93daafda376Andreas Huber
538072f5247ef893e683728263a540bb93daafda376Andreas Huber            if (!strncasecmp("audio/", trackMIME, 6)) {
539072f5247ef893e683728263a540bb93daafda376Andreas Huber                // The matroska file only contains a single audio track,
540072f5247ef893e683728263a540bb93daafda376Andreas Huber                // rewrite its mime type.
541072f5247ef893e683728263a540bb93daafda376Andreas Huber                mMetaData.add(
542072f5247ef893e683728263a540bb93daafda376Andreas Huber                        METADATA_KEY_MIMETYPE, String8("audio/x-matroska"));
543072f5247ef893e683728263a540bb93daafda376Andreas Huber            }
544072f5247ef893e683728263a540bb93daafda376Andreas Huber        }
545072f5247ef893e683728263a540bb93daafda376Andreas Huber    }
54682428a862f325238cfb5646bbd65de3f1a11e7ccGloria Wang
54782428a862f325238cfb5646bbd65de3f1a11e7ccGloria Wang    // To check whether the media file is drm-protected
54882428a862f325238cfb5646bbd65de3f1a11e7ccGloria Wang    if (mExtractor->getDrmFlag()) {
54982428a862f325238cfb5646bbd65de3f1a11e7ccGloria Wang        mMetaData.add(METADATA_KEY_IS_DRM, String8("1"));
55082428a862f325238cfb5646bbd65de3f1a11e7ccGloria Wang    }
551aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber}
552aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
55353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}  // namespace android
554