StagefrightMetadataRetriever.cpp revision 87312e9a810f31a3de76eb7b41165fc02f552cc3
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>
3053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
3153a76bd0c918082847e52570c307ed3ba325992dAndreas Hubernamespace android {
3253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
33aee3c6394a367abf283936cb8b8bd85ed028c050Andreas HuberStagefrightMetadataRetriever::StagefrightMetadataRetriever()
34aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    : mParsedMetaData(false),
35aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber      mAlbumArt(NULL) {
3653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    LOGV("StagefrightMetadataRetriever()");
3753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
3853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    DataSource::RegisterDefaultSniffers();
3953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK_EQ(mClient.connect(), OK);
4053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
4153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
4253a76bd0c918082847e52570c307ed3ba325992dAndreas HuberStagefrightMetadataRetriever::~StagefrightMetadataRetriever() {
4353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    LOGV("~StagefrightMetadataRetriever()");
44aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
45aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    delete mAlbumArt;
46aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mAlbumArt = NULL;
47aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
4853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    mClient.disconnect();
4953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
5053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
515b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huberstatus_t StagefrightMetadataRetriever::setDataSource(
525b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber        const char *uri, const KeyedVector<String8, String8> *headers) {
5353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    LOGV("setDataSource(%s)", uri);
5453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
55aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mParsedMetaData = false;
56aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mMetaData.clear();
57aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    delete mAlbumArt;
58aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mAlbumArt = NULL;
59aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
605b7ced6a4ebcec34a36d0779773bc9e671732dbfAndreas Huber    mSource = DataSource::CreateFromURI(uri, headers);
61aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
62aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mSource == NULL) {
63aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return UNKNOWN_ERROR;
64aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
65aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
66aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mExtractor = MediaExtractor::Create(mSource);
67aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
68aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mExtractor == NULL) {
69aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mSource.clear();
7053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
71aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return UNKNOWN_ERROR;
72aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
73aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
74aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    return OK;
7553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
7653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
77aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber// Warning caller retains ownership of the filedescriptor! Dup it if necessary.
7853a76bd0c918082847e52570c307ed3ba325992dAndreas Huberstatus_t StagefrightMetadataRetriever::setDataSource(
7953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        int fd, int64_t offset, int64_t length) {
80aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    fd = dup(fd);
81aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
8253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
8353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
84aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mParsedMetaData = false;
85aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mMetaData.clear();
86aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    delete mAlbumArt;
87aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mAlbumArt = NULL;
88aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
89aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mSource = new FileSource(fd, offset, length);
90aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
91aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    status_t err;
92aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if ((err = mSource->initCheck()) != OK) {
93aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mSource.clear();
94aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
95aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return err;
96aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
97aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
98aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mExtractor = MediaExtractor::Create(mSource);
99aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
100aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mExtractor == NULL) {
101aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mSource.clear();
102aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
103aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return UNKNOWN_ERROR;
104aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
10553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
10653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    return OK;
10753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
10853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
1090ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huberstatic VideoFrame *extractVideoFrameWithCodecFlags(
1100ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        OMXClient *client,
1110ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        const sp<MetaData> &trackMeta,
112faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        const sp<MediaSource> &source,
113faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        uint32_t flags,
114faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        int64_t frameTimeUs,
115faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        int seekMode) {
11653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    sp<MediaSource> decoder =
11753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        OMXCodec::Create(
1180ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber                client->interface(), source->getFormat(), false, source,
1195a40e394f1e6b0511542e171eaf4c3e5927efc13Andreas Huber                NULL, flags | OMXCodec::kClientNeedsFramebuffer);
12053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
12153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    if (decoder.get() == NULL) {
122ad28543022101d0b01845e3f53dcd57e524816efAndreas Huber        LOGV("unable to instantiate video decoder.");
12353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
12453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        return NULL;
12553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    }
12653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
1271919e5af3d8eb8bcf08e50efae2e79eaf065cf6bAndreas Huber    status_t err = decoder->start();
1281919e5af3d8eb8bcf08e50efae2e79eaf065cf6bAndreas Huber    if (err != OK) {
1291919e5af3d8eb8bcf08e50efae2e79eaf065cf6bAndreas Huber        LOGW("OMXCodec::start returned error %d (0x%08x)\n", err, err);
1301919e5af3d8eb8bcf08e50efae2e79eaf065cf6bAndreas Huber        return NULL;
1311919e5af3d8eb8bcf08e50efae2e79eaf065cf6bAndreas Huber    }
13253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
133f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    // Read one output buffer, ignore format change notifications
134f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    // and spurious empty buffers.
135f68c168d366e8aad58454917f96344398a02efd8Andreas Huber
136e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    MediaSource::ReadOptions options;
137faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong    if (seekMode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC ||
138faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        seekMode > MediaSource::ReadOptions::SEEK_CLOSEST) {
139faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong
140faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        LOGE("Unknown seek mode: %d", seekMode);
141faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        return NULL;
142faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong    }
143faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong
144faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong    MediaSource::ReadOptions::SeekMode mode =
145faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong            static_cast<MediaSource::ReadOptions::SeekMode>(seekMode);
146faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong
147e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    int64_t thumbNailTime;
148b1d49ded620fc9c80f793f32742bf1fef0281271Andreas Huber    if (frameTimeUs < 0) {
14987312e9a810f31a3de76eb7b41165fc02f552cc3Andreas Huber        if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)
15087312e9a810f31a3de76eb7b41165fc02f552cc3Andreas Huber                || thumbNailTime < 0) {
151b1d49ded620fc9c80f793f32742bf1fef0281271Andreas Huber            thumbNailTime = 0;
152b1d49ded620fc9c80f793f32742bf1fef0281271Andreas Huber        }
153faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        options.setSeekTo(thumbNailTime, mode);
1540ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    } else {
1550ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        thumbNailTime = -1;
156faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        options.setSeekTo(frameTimeUs, mode);
157e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    }
158e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber
159f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    MediaBuffer *buffer = NULL;
160cfd55579c2e20514b181809dfaf30bd6f7e04c7eAndreas Huber    do {
161f68c168d366e8aad58454917f96344398a02efd8Andreas Huber        if (buffer != NULL) {
162f68c168d366e8aad58454917f96344398a02efd8Andreas Huber            buffer->release();
163f68c168d366e8aad58454917f96344398a02efd8Andreas Huber            buffer = NULL;
164f68c168d366e8aad58454917f96344398a02efd8Andreas Huber        }
165e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        err = decoder->read(&buffer, &options);
166e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        options.clearSeekTo();
167f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    } while (err == INFO_FORMAT_CHANGED
168f68c168d366e8aad58454917f96344398a02efd8Andreas Huber             || (buffer != NULL && buffer->range_length() == 0));
16953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
17053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    if (err != OK) {
17153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        CHECK_EQ(buffer, NULL);
17253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
173ad28543022101d0b01845e3f53dcd57e524816efAndreas Huber        LOGV("decoding frame failed.");
17453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        decoder->stop();
17553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
17653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        return NULL;
17753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    }
17853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
179ad28543022101d0b01845e3f53dcd57e524816efAndreas Huber    LOGV("successfully decoded video frame.");
18053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
1811e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber    int32_t unreadable;
1821e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber    if (buffer->meta_data()->findInt32(kKeyIsUnreadable, &unreadable)
1831e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber            && unreadable != 0) {
1841e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber        LOGV("video frame is unreadable, decoder does not give us access "
1851e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber             "to the video data.");
1861e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber
1871e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber        buffer->release();
1881e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber        buffer = NULL;
1891e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber
1901e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber        decoder->stop();
1911e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber
1921e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber        return NULL;
1931e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber    }
1941e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber
1950ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    int64_t timeUs;
1960ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
1970ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (thumbNailTime >= 0) {
1980ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        if (timeUs != thumbNailTime) {
1990ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            const char *mime;
2000ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            CHECK(trackMeta->findCString(kKeyMIMEType, &mime));
2010ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2020ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            LOGV("thumbNailTime = %lld us, timeUs = %lld us, mime = %s",
2030ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber                 thumbNailTime, timeUs, mime);
2040ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        }
2050ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
2060ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2070ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    sp<MetaData> meta = decoder->getFormat();
20853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
20953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    int32_t width, height;
21053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(meta->findInt32(kKeyWidth, &width));
21153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(meta->findInt32(kKeyHeight, &height));
21253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
2131bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    int32_t crop_left, crop_top, crop_right, crop_bottom;
2141bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    if (!meta->findRect(
2151bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber                kKeyCropRect,
2161bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber                &crop_left, &crop_top, &crop_right, &crop_bottom)) {
2171bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber        crop_left = crop_top = 0;
2181bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber        crop_right = width - 1;
2191bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber        crop_bottom = height - 1;
2201bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    }
2211bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber
22253ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong    int32_t rotationAngle;
22353ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong    if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) {
22453ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong        rotationAngle = 0;  // By default, no rotation
22553ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong    }
22653ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong
22753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    VideoFrame *frame = new VideoFrame;
2281bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    frame->mWidth = crop_right - crop_left + 1;
2291bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    frame->mHeight = crop_bottom - crop_top + 1;
2301bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    frame->mDisplayWidth = frame->mWidth;
2311bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    frame->mDisplayHeight = frame->mHeight;
2321bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber    frame->mSize = frame->mWidth * frame->mHeight * 2;
23353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    frame->mData = new uint8_t[frame->mSize];
23453ebc72fd83f83bb5536d5917390aae03b7f5cadJames Dong    frame->mRotationAngle = rotationAngle;
23553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
2369f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong    int32_t displayWidth, displayHeight;
2379f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong    if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
2389f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong        frame->mDisplayWidth = displayWidth;
2399f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong    }
2409f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong    if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) {
2419f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong        frame->mDisplayHeight = displayHeight;
2429f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong    }
2439f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong
24453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    int32_t srcFormat;
24553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(meta->findInt32(kKeyColorFormat, &srcFormat));
24653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
24753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    ColorConverter converter(
24853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber            (OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565);
24953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(converter.isValid());
25053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
251c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber    err = converter.convert(
25253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber            (const uint8_t *)buffer->data() + buffer->range_offset(),
2531bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber            width, height,
2541bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber            crop_left, crop_top, crop_right, crop_bottom,
2551bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber            frame->mData,
2561bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber            frame->mWidth,
2571bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber            frame->mHeight,
2581bb0ffd0981bec26f906bc62d449e136111af4f8Andreas Huber            0, 0, frame->mWidth - 1, frame->mHeight - 1);
25953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
26053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    buffer->release();
26153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    buffer = NULL;
26253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
26353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    decoder->stop();
26453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
265c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber    if (err != OK) {
266c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber        LOGE("Colorconverter failed to convert frame.");
267c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber
268c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber        delete frame;
269c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber        frame = NULL;
270c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber    }
271c0dbe3a4457020bdba6ce311d383faecb7950a90Andreas Huber
27253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    return frame;
27353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
27453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
275faf09ba9405ff019b5ca7e2317debe4ff269d4f8James DongVideoFrame *StagefrightMetadataRetriever::getFrameAtTime(
276faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        int64_t timeUs, int option) {
2770ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
278faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong    LOGV("getFrameAtTime: %lld us option: %d", timeUs, option);
279e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber
2800ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (mExtractor.get() == NULL) {
2810ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("no extractor.");
2820ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        return NULL;
2830ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
2840ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2855f63069f3256f8ba253d1331c5bef0d162d2bd67Glenn Kasten    int32_t drm = 0;
2865f63069f3256f8ba253d1331c5bef0d162d2bd67Glenn Kasten    if (mExtractor->getMetaData()->findInt32(kKeyIsDRM, &drm) && drm != 0) {
2875f63069f3256f8ba253d1331c5bef0d162d2bd67Glenn Kasten        LOGE("frame grab not allowed.");
2885f63069f3256f8ba253d1331c5bef0d162d2bd67Glenn Kasten        return NULL;
2895f63069f3256f8ba253d1331c5bef0d162d2bd67Glenn Kasten    }
2905f63069f3256f8ba253d1331c5bef0d162d2bd67Glenn Kasten
2910ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    size_t n = mExtractor->countTracks();
2920ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    size_t i;
2930ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    for (i = 0; i < n; ++i) {
2940ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
2950ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2960ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        const char *mime;
2970ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        CHECK(meta->findCString(kKeyMIMEType, &mime));
2980ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2990ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        if (!strncasecmp(mime, "video/", 6)) {
3000ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            break;
3010ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        }
3020ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
3030ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
3040ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (i == n) {
3050ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("no video track found.");
3060ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        return NULL;
3070ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
3080ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
3090ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
3100ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            i, MediaExtractor::kIncludeExtensiveMetaData);
3110ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
3120ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    sp<MediaSource> source = mExtractor->getTrack(i);
3130ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
3140ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (source.get() == NULL) {
3150ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("unable to instantiate video track.");
3160ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        return NULL;
3170ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
3180ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
3190ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    VideoFrame *frame =
3200ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        extractVideoFrameWithCodecFlags(
321faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong                &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs,
322faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong                timeUs, option);
3230ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
3240ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (frame == NULL) {
3250ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("Software decoder failed to extract thumbnail, "
3260ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber             "trying hardware decoder.");
3270ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
328faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong        frame = extractVideoFrameWithCodecFlags(&mClient, trackMeta, source, 0,
329faf09ba9405ff019b5ca7e2317debe4ff269d4f8James Dong                        timeUs, option);
3300ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
3310ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
3320ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    return frame;
3330ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber}
3340ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
33553a76bd0c918082847e52570c307ed3ba325992dAndreas HuberMediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() {
33653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    LOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO");
33753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
338aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mExtractor == NULL) {
339aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return NULL;
340aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
341aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
342aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (!mParsedMetaData) {
343aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        parseMetaData();
344aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
345aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mParsedMetaData = true;
346aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
347aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
348aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mAlbumArt) {
349aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return new MediaAlbumArt(*mAlbumArt);
350aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
351aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
35253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    return NULL;
35353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
35453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
35553a76bd0c918082847e52570c307ed3ba325992dAndreas Huberconst char *StagefrightMetadataRetriever::extractMetadata(int keyCode) {
356aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mExtractor == NULL) {
357aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return NULL;
358aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
359aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
360aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (!mParsedMetaData) {
361aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        parseMetaData();
362aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
363aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mParsedMetaData = true;
364aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
365aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
366aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    ssize_t index = mMetaData.indexOfKey(keyCode);
367aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
368aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (index < 0) {
369aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return NULL;
370aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
371aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
372aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    return strdup(mMetaData.valueAt(index).string());
37353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
37453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
375aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Hubervoid StagefrightMetadataRetriever::parseMetaData() {
376aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    sp<MetaData> meta = mExtractor->getMetaData();
377aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
378aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    struct Map {
379aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        int from;
380aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        int to;
381aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    };
382aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    static const Map kMap[] = {
3831cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber        { kKeyMIMEType, METADATA_KEY_MIMETYPE },
3843a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber        { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER },
385655306f8a80b3e9fc52daf458ef319a8ed8c564cMarco Nelissen        { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER },
386aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyAlbum, METADATA_KEY_ALBUM },
387aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyArtist, METADATA_KEY_ARTIST },
388c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST },
3893a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber        { kKeyAuthor, METADATA_KEY_AUTHOR },
390aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyComposer, METADATA_KEY_COMPOSER },
3913a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber        { kKeyDate, METADATA_KEY_DATE },
392aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyGenre, METADATA_KEY_GENRE },
393aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyTitle, METADATA_KEY_TITLE },
394aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyYear, METADATA_KEY_YEAR },
395c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        { kKeyWriter, METADATA_KEY_WRITER },
396ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen        { kKeyCompilation, METADATA_KEY_COMPILATION },
397aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    };
398aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
399aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
400aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    for (size_t i = 0; i < kNumMapEntries; ++i) {
401aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        const char *value;
402aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        if (meta->findCString(kMap[i].from, &value)) {
403aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            mMetaData.add(kMap[i].to, String8(value));
404aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        }
405aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
406aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
407aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    const void *data;
408aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    uint32_t type;
409aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    size_t dataSize;
410aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (meta->findData(kKeyAlbumArt, &type, &data, &dataSize)) {
411aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mAlbumArt = new MediaAlbumArt;
412aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mAlbumArt->mSize = dataSize;
413aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mAlbumArt->mData = new uint8_t[dataSize];
414aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        memcpy(mAlbumArt->mData, data, dataSize);
415aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
416aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
4173a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    size_t numTracks = mExtractor->countTracks();
4183a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber
4193a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    char tmp[32];
4203a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    sprintf(tmp, "%d", numTracks);
4213a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber
4223a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp));
4233a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber
424c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    bool hasAudio = false;
425c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    bool hasVideo = false;
426c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    int32_t videoWidth = -1;
427c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    int32_t videoHeight = -1;
428c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    int32_t audioBitrate = -1;
429c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
430aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    // The overall duration is the duration of the longest track.
431aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    int64_t maxDurationUs = 0;
4323a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    for (size_t i = 0; i < numTracks; ++i) {
433aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);
434aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
435aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        int64_t durationUs;
436aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        if (trackMeta->findInt64(kKeyDuration, &durationUs)) {
437aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            if (durationUs > maxDurationUs) {
438aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber                maxDurationUs = durationUs;
439aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            }
440aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        }
441c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
442c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        const char *mime;
443c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        if (trackMeta->findCString(kKeyMIMEType, &mime)) {
444c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber            if (!hasAudio && !strncasecmp("audio/", mime, 6)) {
445c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber                hasAudio = true;
446c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
447c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber                if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) {
448c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber                    audioBitrate = -1;
449c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber                }
450c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber            } else if (!hasVideo && !strncasecmp("video/", mime, 6)) {
451c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber                hasVideo = true;
452c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
453c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber                CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth));
454c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber                CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight));
455c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber            }
456c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        }
457aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
458aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
459aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    // The duration value is a string representing the duration in ms.
460aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000);
461aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
462072f5247ef893e683728263a540bb93daafda376Andreas Huber
463c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    if (hasAudio) {
464c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        mMetaData.add(METADATA_KEY_HAS_AUDIO, String8("yes"));
465c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    }
466c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
467c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    if (hasVideo) {
468c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        mMetaData.add(METADATA_KEY_HAS_VIDEO, String8("yes"));
469c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
470c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        sprintf(tmp, "%d", videoWidth);
471c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        mMetaData.add(METADATA_KEY_VIDEO_WIDTH, String8(tmp));
472c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
473c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        sprintf(tmp, "%d", videoHeight);
474c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        mMetaData.add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp));
475c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    }
476c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
477c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    if (numTracks == 1 && hasAudio && audioBitrate >= 0) {
4789f2cde3cdb3e2de97f450d0f4e2b52aae86ce5a3James Dong        sprintf(tmp, "%d", audioBitrate);
479c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
480c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    } else {
481c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        off64_t sourceSize;
482c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        if (mSource->getSize(&sourceSize) == OK) {
483c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber            int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs);
484c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
485c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber            sprintf(tmp, "%lld", avgBitRate);
486c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber            mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
487c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber        }
488c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber    }
489c4c38fc1ea06086ea3c7ba12f59ecfacd5fa716bAndreas Huber
490072f5247ef893e683728263a540bb93daafda376Andreas Huber    if (numTracks == 1) {
491072f5247ef893e683728263a540bb93daafda376Andreas Huber        const char *fileMIME;
492072f5247ef893e683728263a540bb93daafda376Andreas Huber        CHECK(meta->findCString(kKeyMIMEType, &fileMIME));
493072f5247ef893e683728263a540bb93daafda376Andreas Huber
494072f5247ef893e683728263a540bb93daafda376Andreas Huber        if (!strcasecmp(fileMIME, "video/x-matroska")) {
495072f5247ef893e683728263a540bb93daafda376Andreas Huber            sp<MetaData> trackMeta = mExtractor->getTrackMetaData(0);
496072f5247ef893e683728263a540bb93daafda376Andreas Huber            const char *trackMIME;
497072f5247ef893e683728263a540bb93daafda376Andreas Huber            CHECK(trackMeta->findCString(kKeyMIMEType, &trackMIME));
498072f5247ef893e683728263a540bb93daafda376Andreas Huber
499072f5247ef893e683728263a540bb93daafda376Andreas Huber            if (!strncasecmp("audio/", trackMIME, 6)) {
500072f5247ef893e683728263a540bb93daafda376Andreas Huber                // The matroska file only contains a single audio track,
501072f5247ef893e683728263a540bb93daafda376Andreas Huber                // rewrite its mime type.
502072f5247ef893e683728263a540bb93daafda376Andreas Huber                mMetaData.add(
503072f5247ef893e683728263a540bb93daafda376Andreas Huber                        METADATA_KEY_MIMETYPE, String8("audio/x-matroska"));
504072f5247ef893e683728263a540bb93daafda376Andreas Huber            }
505072f5247ef893e683728263a540bb93daafda376Andreas Huber        }
506072f5247ef893e683728263a540bb93daafda376Andreas Huber    }
507aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber}
508aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
50953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}  // namespace android
510