StagefrightMetadataRetriever.cpp revision e3452d3fe1da014a6db9a326df08230e0d5339ec
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
12353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    decoder->start();
12453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
125f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    // Read one output buffer, ignore format change notifications
126f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    // and spurious empty buffers.
127f68c168d366e8aad58454917f96344398a02efd8Andreas Huber
128e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    MediaSource::ReadOptions options;
129e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    int64_t thumbNailTime;
130e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    if (trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
131e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        options.setSeekTo(thumbNailTime);
1320ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    } else {
1330ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        thumbNailTime = -1;
134e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber    }
135e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber
136f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    MediaBuffer *buffer = NULL;
137cfd55579c2e20514b181809dfaf30bd6f7e04c7eAndreas Huber    status_t err;
138cfd55579c2e20514b181809dfaf30bd6f7e04c7eAndreas Huber    do {
139f68c168d366e8aad58454917f96344398a02efd8Andreas Huber        if (buffer != NULL) {
140f68c168d366e8aad58454917f96344398a02efd8Andreas Huber            buffer->release();
141f68c168d366e8aad58454917f96344398a02efd8Andreas Huber            buffer = NULL;
142f68c168d366e8aad58454917f96344398a02efd8Andreas Huber        }
143e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        err = decoder->read(&buffer, &options);
144e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber        options.clearSeekTo();
145f68c168d366e8aad58454917f96344398a02efd8Andreas Huber    } while (err == INFO_FORMAT_CHANGED
146f68c168d366e8aad58454917f96344398a02efd8Andreas Huber             || (buffer != NULL && buffer->range_length() == 0));
14753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
14853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    if (err != OK) {
14953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        CHECK_EQ(buffer, NULL);
15053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
151ad28543022101d0b01845e3f53dcd57e524816efAndreas Huber        LOGV("decoding frame failed.");
15253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        decoder->stop();
15353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
15453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber        return NULL;
15553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    }
15653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
157ad28543022101d0b01845e3f53dcd57e524816efAndreas Huber    LOGV("successfully decoded video frame.");
15853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
1590ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    int64_t timeUs;
1600ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
1610ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (thumbNailTime >= 0) {
1620ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        if (timeUs != thumbNailTime) {
1630ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            const char *mime;
1640ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            CHECK(trackMeta->findCString(kKeyMIMEType, &mime));
1650ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
1660ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            LOGV("thumbNailTime = %lld us, timeUs = %lld us, mime = %s",
1670ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber                 thumbNailTime, timeUs, mime);
1680ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        }
1690ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
1700ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
1710ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    sp<MetaData> meta = decoder->getFormat();
17253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
17353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    int32_t width, height;
17453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(meta->findInt32(kKeyWidth, &width));
17553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(meta->findInt32(kKeyHeight, &height));
17653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
17753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    VideoFrame *frame = new VideoFrame;
17853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    frame->mWidth = width;
17953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    frame->mHeight = height;
18053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    frame->mDisplayWidth = width;
18153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    frame->mDisplayHeight = height;
18253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    frame->mSize = width * height * 2;
18353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    frame->mData = new uint8_t[frame->mSize];
18453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
18553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    int32_t srcFormat;
18653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(meta->findInt32(kKeyColorFormat, &srcFormat));
18753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
18853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    ColorConverter converter(
18953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber            (OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565);
19053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    CHECK(converter.isValid());
19153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
19253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    converter.convert(
19353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber            width, height,
19453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber            (const uint8_t *)buffer->data() + buffer->range_offset(),
19553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber            0,
19653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber            frame->mData, width * 2);
19753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
19853a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    buffer->release();
19953a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    buffer = NULL;
20053a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
20153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    decoder->stop();
20253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
20353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    return frame;
20453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
20553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
2060ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas HuberVideoFrame *StagefrightMetadataRetriever::captureFrame() {
2070ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    LOGV("captureFrame");
2080ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
209e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber    if (0 == (mMode & METADATA_MODE_FRAME_CAPTURE_ONLY)) {
210e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber        LOGV("captureFrame disabled by mode (0x%08x)", mMode);
211e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber
212e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber        return NULL;
213e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber    }
214e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber
2150ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (mExtractor.get() == NULL) {
2160ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("no extractor.");
2170ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        return NULL;
2180ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
2190ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2200ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    size_t n = mExtractor->countTracks();
2210ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    size_t i;
2220ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    for (i = 0; i < n; ++i) {
2230ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
2240ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2250ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        const char *mime;
2260ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        CHECK(meta->findCString(kKeyMIMEType, &mime));
2270ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2280ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        if (!strncasecmp(mime, "video/", 6)) {
2290ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            break;
2300ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        }
2310ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
2320ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2330ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (i == n) {
2340ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("no video track found.");
2350ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        return NULL;
2360ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
2370ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2380ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
2390ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber            i, MediaExtractor::kIncludeExtensiveMetaData);
2400ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2410ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    sp<MediaSource> source = mExtractor->getTrack(i);
2420ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2430ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (source.get() == NULL) {
2440ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("unable to instantiate video track.");
2450ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        return NULL;
2460ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
2470ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2480ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    VideoFrame *frame =
2490ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        extractVideoFrameWithCodecFlags(
2500ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber                &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs);
2510ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2520ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    if (frame == NULL) {
2530ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        LOGV("Software decoder failed to extract thumbnail, "
2540ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber             "trying hardware decoder.");
2550ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2560ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber        frame = extractVideoFrameWithCodecFlags(&mClient, trackMeta, source, 0);
2570ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    }
2580ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
2590ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber    return frame;
2600ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber}
2610ffc90f6edd5f09a49e2f97351723ef1e1a3128aAndreas Huber
26253a76bd0c918082847e52570c307ed3ba325992dAndreas HuberMediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() {
26353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    LOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO");
26453a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
265e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber    if (0 == (mMode & METADATA_MODE_METADATA_RETRIEVAL_ONLY)) {
266e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber        LOGV("extractAlbumArt/metadata retrieval disabled by mode");
267e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber
268e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber        return NULL;
269e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber    }
270e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber
271aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mExtractor == NULL) {
272aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return NULL;
273aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
274aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
275aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (!mParsedMetaData) {
276aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        parseMetaData();
277aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
278aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mParsedMetaData = true;
279aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
280aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
281aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mAlbumArt) {
282aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return new MediaAlbumArt(*mAlbumArt);
283aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
284aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
28553a76bd0c918082847e52570c307ed3ba325992dAndreas Huber    return NULL;
28653a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
28753a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
28853a76bd0c918082847e52570c307ed3ba325992dAndreas Huberconst char *StagefrightMetadataRetriever::extractMetadata(int keyCode) {
289e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber    if (0 == (mMode & METADATA_MODE_METADATA_RETRIEVAL_ONLY)) {
290e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber        LOGV("extractAlbumArt/metadata retrieval disabled by mode");
291e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber
292e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber        return NULL;
293e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber    }
294e3452d3fe1da014a6db9a326df08230e0d5339ecAndreas Huber
295aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (mExtractor == NULL) {
296aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return NULL;
297aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
298aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
299aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (!mParsedMetaData) {
300aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        parseMetaData();
301aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
302aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mParsedMetaData = true;
303aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
304aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
305aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    ssize_t index = mMetaData.indexOfKey(keyCode);
306aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
307aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (index < 0) {
308aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        return NULL;
309aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
310aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
311aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    return strdup(mMetaData.valueAt(index).string());
31253a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}
31353a76bd0c918082847e52570c307ed3ba325992dAndreas Huber
314aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Hubervoid StagefrightMetadataRetriever::parseMetaData() {
315aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    sp<MetaData> meta = mExtractor->getMetaData();
316aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
317aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    struct Map {
318aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        int from;
319aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        int to;
320aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    };
321aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    static const Map kMap[] = {
3221cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber        { kKeyMIMEType, METADATA_KEY_MIMETYPE },
3233a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber        { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER },
324655306f8a80b3e9fc52daf458ef319a8ed8c564cMarco Nelissen        { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER },
325aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyAlbum, METADATA_KEY_ALBUM },
326aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyArtist, METADATA_KEY_ARTIST },
327c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen        { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST },
3283a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber        { kKeyAuthor, METADATA_KEY_AUTHOR },
329aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyComposer, METADATA_KEY_COMPOSER },
3303a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber        { kKeyDate, METADATA_KEY_DATE },
331aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyGenre, METADATA_KEY_GENRE },
332aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyTitle, METADATA_KEY_TITLE },
333aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        { kKeyYear, METADATA_KEY_YEAR },
334c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber        { kKeyWriter, METADATA_KEY_WRITER },
335aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    };
336aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
337aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
338aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    for (size_t i = 0; i < kNumMapEntries; ++i) {
339aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        const char *value;
340aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        if (meta->findCString(kMap[i].from, &value)) {
341aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            mMetaData.add(kMap[i].to, String8(value));
342aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        }
343aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
344aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
345aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    const void *data;
346aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    uint32_t type;
347aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    size_t dataSize;
348aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    if (meta->findData(kKeyAlbumArt, &type, &data, &dataSize)) {
349aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mAlbumArt = new MediaAlbumArt;
350aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mAlbumArt->mSize = dataSize;
351aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        mAlbumArt->mData = new uint8_t[dataSize];
352aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        memcpy(mAlbumArt->mData, data, dataSize);
353aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
354aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
3553a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    size_t numTracks = mExtractor->countTracks();
3563a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber
3573a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    char tmp[32];
3583a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    sprintf(tmp, "%d", numTracks);
3593a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber
3603a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp));
3613a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber
362aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    // The overall duration is the duration of the longest track.
363aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    int64_t maxDurationUs = 0;
3643a3656ce8a34bf4a17e806c1db1073848de2728fAndreas Huber    for (size_t i = 0; i < numTracks; ++i) {
365aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);
366aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
367aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        int64_t durationUs;
368aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        if (trackMeta->findInt64(kKeyDuration, &durationUs)) {
369aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            if (durationUs > maxDurationUs) {
370aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber                maxDurationUs = durationUs;
371aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber            }
372aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber        }
373aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    }
374aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
375aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    // The duration value is a string representing the duration in ms.
376aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000);
377aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber    mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
378aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber}
379aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
380aee3c6394a367abf283936cb8b8bd85ed028c050Andreas Huber
38153a76bd0c918082847e52570c307ed3ba325992dAndreas Huber}  // namespace android
382