StagefrightMetadataRetriever.cpp revision 1e1941638398e5e3e1d7b9ad88e66f574576bcfa
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
5153a76bd0c918082847e52570c307ed3ba325992dAndreas Huberstatus_t StagefrightMetadataRetriever::setDataSource(const char *uri) {
5253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    LOGV("setDataSource(%s)", uri);
5353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
54aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mParsedMetaData = false;
55aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mMetaData.clear();
56aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    delete mAlbumArt;
57aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mAlbumArt = NULL;
58aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
59aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mSource = DataSource::CreateFromURI(uri);
60aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
61aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mSource == NULL) {
62aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return UNKNOWN_ERROR;
63aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
64aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
65aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mExtractor = MediaExtractor::Create(mSource);
66aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
67aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mExtractor == NULL) {
68aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mSource.clear();
6953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
70aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return UNKNOWN_ERROR;
71aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
72aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
73aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    return OK;
7453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
7553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
76aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber// Warning caller retains ownership of the filedescriptor! Dup it if necessary.
7753a76bd0c918082847e52570c307ed3ba325992dAndreas Huberstatus_t StagefrightMetadataRetriever::setDataSource(
7853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        int fd, int64_t offset, int64_t length) {
79aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    fd = dup(fd);
80aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
8153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
8253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
83aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mParsedMetaData = false;
84aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mMetaData.clear();
85aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    delete mAlbumArt;
86aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mAlbumArt = NULL;
87aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
88aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mSource = new FileSource(fd, offset, length);
89aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
90aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    status_t err;
91aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if ((err = mSource->initCheck()) != OK) {
92aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mSource.clear();
93aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
94aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return err;
95aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
96aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
97aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mExtractor = MediaExtractor::Create(mSource);
98aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
99aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mExtractor == NULL) {
100aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mSource.clear();
101aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
102aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return UNKNOWN_ERROR;
103aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
10453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
10553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    return OK;
10653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
10753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
1080ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huberstatic VideoFrame *extractVideoFrameWithCodecFlags(
1090ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        OMXClient *client,
1100ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        const sp<MetaData> &trackMeta,
1110ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        const sp<MediaSource> &source, uint32_t flags) {
11253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    sp<MediaSource> decoder =
11353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        OMXCodec::Create(
1140ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber                client->interface(), source->getFormat(), false, source,
1150ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber                NULL, flags);
11653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
11753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    if (decoder.get() == NULL) {
118ad28543022101d0b01845e3f53dcd57e524816efAndreas Huber        LOGV("unable to instantiate video decoder.");
11953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
12053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        return NULL;
12153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    }
12253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
1231919e5af3d8eb8bcf08e50efae2e79eaf065cf6bAndreas Huber    status_t err = decoder->start();
1241919e5af3d8eb8bcf08e50efae2e79eaf065cf6bAndreas Huber    if (err != OK) {
1251919e5af3d8eb8bcf08e50efae2e79eaf065cf6bAndreas Huber        LOGW("OMXCodec::start returned error %d (0x%08x)\n", err, err);
1261919e5af3d8eb8bcf08e50efae2e79eaf065cf6bAndreas Huber        return NULL;
1271919e5af3d8eb8bcf08e50efae2e79eaf065cf6bAndreas Huber    }
12853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
129f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    // Read one output buffer, ignore format change notifications
130f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    // and spurious empty buffers.
131f68c168d366e8aad58454917f96344398a02efd8Andreas Huber
132e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    MediaSource::ReadOptions options;
133e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    int64_t thumbNailTime;
134e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    if (trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
135e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        options.setSeekTo(thumbNailTime);
1360ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    } else {
1370ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        thumbNailTime = -1;
138e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    }
139e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber
140f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    MediaBuffer *buffer = NULL;
141cfd55579c2e20514b181809dfaf30bd6f7e04c7eAndreas Huber    do {
142f68c168d366e8aad58454917f96344398a02efd8Andreas Huber        if (buffer != NULL) {
143f68c168d366e8aad58454917f96344398a02efd8Andreas Huber            buffer->release();
144f68c168d366e8aad58454917f96344398a02efd8Andreas Huber            buffer = NULL;
145f68c168d366e8aad58454917f96344398a02efd8Andreas Huber        }
146e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        err = decoder->read(&buffer, &options);
147e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        options.clearSeekTo();
148f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    } while (err == INFO_FORMAT_CHANGED
149f68c168d366e8aad58454917f96344398a02efd8Andreas Huber             || (buffer != NULL && buffer->range_length() == 0));
15053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
15153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    if (err != OK) {
15253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        CHECK_EQ(buffer, NULL);
15353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
154ad28543022101d0b01845e3f53dcd57e524816efAndreas Huber        LOGV("decoding frame failed.");
15553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        decoder->stop();
15653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
15753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        return NULL;
15853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    }
15953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
160ad28543022101d0b01845e3f53dcd57e524816efAndreas Huber    LOGV("successfully decoded video frame.");
16153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
1621e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber    int32_t unreadable;
1631e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber    if (buffer->meta_data()->findInt32(kKeyIsUnreadable, &unreadable)
1641e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber            && unreadable != 0) {
1651e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber        LOGV("video frame is unreadable, decoder does not give us access "
1661e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber             "to the video data.");
1671e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber
1681e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber        buffer->release();
1691e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber        buffer = NULL;
1701e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber
1711e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber        decoder->stop();
1721e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber
1731e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber        return NULL;
1741e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber    }
1751e1941638398e5e3e1d7b9ad88e66f574576bcfaAndreas Huber
1760ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    int64_t timeUs;
1770ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
1780ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (thumbNailTime >= 0) {
1790ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        if (timeUs != thumbNailTime) {
1800ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            const char *mime;
1810ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            CHECK(trackMeta->findCString(kKeyMIMEType, &mime));
1820ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
1830ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            LOGV("thumbNailTime = %lld us, timeUs = %lld us, mime = %s",
1840ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber                 thumbNailTime, timeUs, mime);
1850ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        }
1860ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
1870ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
1880ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    sp<MetaData> meta = decoder->getFormat();
18953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
19053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    int32_t width, height;
19153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(meta->findInt32(kKeyWidth, &width));
19253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(meta->findInt32(kKeyHeight, &height));
19353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
19453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    VideoFrame *frame = new VideoFrame;
19553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    frame->mWidth = width;
19653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    frame->mHeight = height;
19753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    frame->mDisplayWidth = width;
19853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    frame->mDisplayHeight = height;
19953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    frame->mSize = width * height * 2;
20053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    frame->mData = new uint8_t[frame->mSize];
20153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
20253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    int32_t srcFormat;
20353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(meta->findInt32(kKeyColorFormat, &srcFormat));
20453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
20553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    ColorConverter converter(
20653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber            (OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565);
20753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(converter.isValid());
20853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
20953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    converter.convert(
21053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber            width, height,
21153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber            (const uint8_t *)buffer->data() + buffer->range_offset(),
21253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber            0,
21353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber            frame->mData, width * 2);
21453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
21553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    buffer->release();
21653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    buffer = NULL;
21753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
21853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    decoder->stop();
21953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
22053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    return frame;
22153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
22253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
2230ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas HuberVideoFrame *StagefrightMetadataRetriever::captureFrame() {
2240ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    LOGV("captureFrame");
2250ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
226e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber    if (0 == (mMode & METADATA_MODE_FRAME_CAPTURE_ONLY)) {
227e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber        LOGV("captureFrame disabled by mode (0x%08x)", mMode);
228e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber
229e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber        return NULL;
230e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber    }
231e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber
2320ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (mExtractor.get() == NULL) {
2330ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("no extractor.");
2340ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        return NULL;
2350ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
2360ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2370ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    size_t n = mExtractor->countTracks();
2380ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    size_t i;
2390ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    for (i = 0; i < n; ++i) {
2400ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
2410ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2420ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        const char *mime;
2430ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        CHECK(meta->findCString(kKeyMIMEType, &mime));
2440ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2450ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        if (!strncasecmp(mime, "video/", 6)) {
2460ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            break;
2470ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        }
2480ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
2490ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2500ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (i == n) {
2510ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("no video track found.");
2520ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        return NULL;
2530ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
2540ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2550ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
2560ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            i, MediaExtractor::kIncludeExtensiveMetaData);
2570ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2580ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    sp<MediaSource> source = mExtractor->getTrack(i);
2590ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2600ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (source.get() == NULL) {
2610ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("unable to instantiate video track.");
2620ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        return NULL;
2630ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
2640ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2650ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    VideoFrame *frame =
2660ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        extractVideoFrameWithCodecFlags(
2670ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber                &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs);
2680ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2690ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (frame == NULL) {
2700ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("Software decoder failed to extract thumbnail, "
2710ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber             "trying hardware decoder.");
2720ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2730ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        frame = extractVideoFrameWithCodecFlags(&mClient, trackMeta, source, 0);
2740ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
2750ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2760ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    return frame;
2770ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber}
2780ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
27953a76bd0c918082847e52570c307ed3ba325992dAndreas HuberMediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() {
28053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    LOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO");
28153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
282e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber    if (0 == (mMode & METADATA_MODE_METADATA_RETRIEVAL_ONLY)) {
283e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber        LOGV("extractAlbumArt/metadata retrieval disabled by mode");
284e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber
285e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber        return NULL;
286e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber    }
287e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber
288aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mExtractor == NULL) {
289aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return NULL;
290aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
291aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
292aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (!mParsedMetaData) {
293aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        parseMetaData();
294aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
295aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mParsedMetaData = true;
296aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
297aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
298aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mAlbumArt) {
299aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return new MediaAlbumArt(*mAlbumArt);
300aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
301aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
30253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    return NULL;
30353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
30453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
30553a76bd0c918082847e52570c307ed3ba325992dAndreas Huberconst char *StagefrightMetadataRetriever::extractMetadata(int keyCode) {
306e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber    if (0 == (mMode & METADATA_MODE_METADATA_RETRIEVAL_ONLY)) {
307e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber        LOGV("extractAlbumArt/metadata retrieval disabled by mode");
308e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber
309e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber        return NULL;
310e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber    }
311e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber
312aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mExtractor == NULL) {
313aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return NULL;
314aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
315aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
316aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (!mParsedMetaData) {
317aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        parseMetaData();
318aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
319aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mParsedMetaData = true;
320aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
321aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
322aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    ssize_t index = mMetaData.indexOfKey(keyCode);
323aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
324aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (index < 0) {
325aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return NULL;
326aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
327aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
328aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    return strdup(mMetaData.valueAt(index).string());
32953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
33053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
331aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Hubervoid StagefrightMetadataRetriever::parseMetaData() {
332aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    sp<MetaData> meta = mExtractor->getMetaData();
333aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
334aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    struct Map {
335aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        int from;
336aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        int to;
337aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    };
338aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    static const Map kMap[] = {
3391cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber        { kKeyMIMEType, METADATA_KEY_MIMETYPE },
3403a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber        { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER },
341655306f8a80b3e9fc52daf458ef319a8ed8c564cMarco Nelissen        { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER },
342aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyAlbum, METADATA_KEY_ALBUM },
343aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyArtist, METADATA_KEY_ARTIST },
344c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST },
3453a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber        { kKeyAuthor, METADATA_KEY_AUTHOR },
346aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyComposer, METADATA_KEY_COMPOSER },
3473a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber        { kKeyDate, METADATA_KEY_DATE },
348aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyGenre, METADATA_KEY_GENRE },
349aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyTitle, METADATA_KEY_TITLE },
350aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyYear, METADATA_KEY_YEAR },
351c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        { kKeyWriter, METADATA_KEY_WRITER },
352aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    };
353aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
354aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
355aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    for (size_t i = 0; i < kNumMapEntries; ++i) {
356aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        const char *value;
357aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        if (meta->findCString(kMap[i].from, &value)) {
358aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            mMetaData.add(kMap[i].to, String8(value));
359aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        }
360aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
361aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
362aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    const void *data;
363aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    uint32_t type;
364aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    size_t dataSize;
365aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (meta->findData(kKeyAlbumArt, &type, &data, &dataSize)) {
366aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mAlbumArt = new MediaAlbumArt;
367aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mAlbumArt->mSize = dataSize;
368aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mAlbumArt->mData = new uint8_t[dataSize];
369aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        memcpy(mAlbumArt->mData, data, dataSize);
370aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
371aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
3723a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    size_t numTracks = mExtractor->countTracks();
3733a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber
3743a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    char tmp[32];
3753a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    sprintf(tmp, "%d", numTracks);
3763a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber
3773a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp));
3783a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber
379aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    // The overall duration is the duration of the longest track.
380aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    int64_t maxDurationUs = 0;
3813a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    for (size_t i = 0; i < numTracks; ++i) {
382aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);
383aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
384aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        int64_t durationUs;
385aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        if (trackMeta->findInt64(kKeyDuration, &durationUs)) {
386aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            if (durationUs > maxDurationUs) {
387aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber                maxDurationUs = durationUs;
388aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            }
389aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        }
390aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
391aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
392aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    // The duration value is a string representing the duration in ms.
393aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000);
394aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
395072f5247ef893e683728263a540bb93daafda376Andreas Huber
396072f5247ef893e683728263a540bb93daafda376Andreas Huber    if (numTracks == 1) {
397072f5247ef893e683728263a540bb93daafda376Andreas Huber        const char *fileMIME;
398072f5247ef893e683728263a540bb93daafda376Andreas Huber        CHECK(meta->findCString(kKeyMIMEType, &fileMIME));
399072f5247ef893e683728263a540bb93daafda376Andreas Huber
400072f5247ef893e683728263a540bb93daafda376Andreas Huber        if (!strcasecmp(fileMIME, "video/x-matroska")) {
401072f5247ef893e683728263a540bb93daafda376Andreas Huber            sp<MetaData> trackMeta = mExtractor->getTrackMetaData(0);
402072f5247ef893e683728263a540bb93daafda376Andreas Huber            const char *trackMIME;
403072f5247ef893e683728263a540bb93daafda376Andreas Huber            CHECK(trackMeta->findCString(kKeyMIMEType, &trackMIME));
404072f5247ef893e683728263a540bb93daafda376Andreas Huber
405072f5247ef893e683728263a540bb93daafda376Andreas Huber            if (!strncasecmp("audio/", trackMIME, 6)) {
406072f5247ef893e683728263a540bb93daafda376Andreas Huber                // The matroska file only contains a single audio track,
407072f5247ef893e683728263a540bb93daafda376Andreas Huber                // rewrite its mime type.
408072f5247ef893e683728263a540bb93daafda376Andreas Huber                mMetaData.add(
409072f5247ef893e683728263a540bb93daafda376Andreas Huber                        METADATA_KEY_MIMETYPE, String8("audio/x-matroska"));
410072f5247ef893e683728263a540bb93daafda376Andreas Huber            }
411072f5247ef893e683728263a540bb93daafda376Andreas Huber        }
412072f5247ef893e683728263a540bb93daafda376Andreas Huber    }
413aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber}
414aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
415aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
41653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}  // namespace android
417