StagefrightMetadataRetriever.cpp revision 72b8c5ae6a5f97a4fcfc6d23d33159d6ae50179c
12a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber/*
2fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * Copyright (C) 2009 The Android Open Source Project
3fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *
4fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * you may not use this file except in compliance with the License.
6fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * You may obtain a copy of the License at
7fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *
8fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *
10fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * Unless required by applicable law or agreed to in writing, software
11fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * See the License for the specific language governing permissions and
14fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber * limitations under the License.
15fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber */
162a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
172a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber//#define LOG_NDEBUG 0
182a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#define LOG_TAG "StagefrightMetadataRetriever"
192a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <utils/Log.h>
202a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
2167e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber#include "include/StagefrightMetadataRetriever.h"
222a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
232a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/CachingDataSource.h>
242a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/ColorConverter.h>
252a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/DataSource.h>
26bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber#include <media/stagefright/FileSource.h>
272a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/HTTPDataSource.h>
282a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/MediaDebug.h>
292a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/MediaExtractor.h>
302a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/MetaData.h>
312a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/OMXCodec.h>
322a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
332a4a7d5af053a17586a262a1267ba993e31790f1Andreas Hubernamespace android {
342a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
35fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberStagefrightMetadataRetriever::StagefrightMetadataRetriever()
36fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    : mParsedMetaData(false),
37fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber      mAlbumArt(NULL) {
382a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    LOGV("StagefrightMetadataRetriever()");
392a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
402a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    DataSource::RegisterDefaultSniffers();
412a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    CHECK_EQ(mClient.connect(), OK);
422a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}
432a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
442a4a7d5af053a17586a262a1267ba993e31790f1Andreas HuberStagefrightMetadataRetriever::~StagefrightMetadataRetriever() {
452a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    LOGV("~StagefrightMetadataRetriever()");
46fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
47fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    delete mAlbumArt;
48fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mAlbumArt = NULL;
49fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
502a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    mClient.disconnect();
512a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}
522a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
532a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huberstatus_t StagefrightMetadataRetriever::setDataSource(const char *uri) {
542a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    LOGV("setDataSource(%s)", uri);
552a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
56fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mParsedMetaData = false;
57fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mMetaData.clear();
58fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    delete mAlbumArt;
59fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mAlbumArt = NULL;
60fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
61fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mSource = DataSource::CreateFromURI(uri);
62fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
63fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mSource == NULL) {
64fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return UNKNOWN_ERROR;
65fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
66fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
67fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mExtractor = MediaExtractor::Create(mSource);
68fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
69fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mExtractor == NULL) {
70fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mSource.clear();
712a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
72fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return UNKNOWN_ERROR;
73fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
74fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
75fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return OK;
762a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}
772a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
78fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber// Warning caller retains ownership of the filedescriptor! Dup it if necessary.
792a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huberstatus_t StagefrightMetadataRetriever::setDataSource(
802a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber        int fd, int64_t offset, int64_t length) {
81fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    fd = dup(fd);
82fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
832a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
842a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
85fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mParsedMetaData = false;
86fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mMetaData.clear();
87fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    delete mAlbumArt;
88fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mAlbumArt = NULL;
89fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
90fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mSource = new FileSource(fd, offset, length);
91fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
92fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    status_t err;
93fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if ((err = mSource->initCheck()) != OK) {
94fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mSource.clear();
95fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
96fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return err;
97fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
98fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
99fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mExtractor = MediaExtractor::Create(mSource);
100fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
101fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mExtractor == NULL) {
102fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mSource.clear();
103fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
104fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return UNKNOWN_ERROR;
105fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
1062a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1072a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    return OK;
1082a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}
1092a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1104e202e779a8495091ab189fd88fc295a3e619c61Andreas Huberstatic VideoFrame *extractVideoFrameWithCodecFlags(
1114e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        OMXClient *client,
1124e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        const sp<MetaData> &trackMeta,
1134e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        const sp<MediaSource> &source, uint32_t flags) {
1142a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    sp<MediaSource> decoder =
1152a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber        OMXCodec::Create(
1164e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber                client->interface(), source->getFormat(), false, source,
1174e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber                NULL, flags);
1182a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1192a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    if (decoder.get() == NULL) {
12047bed1a7755ed58fa5d4c0d35b20468deb83bd60Andreas Huber        LOGV("unable to instantiate video decoder.");
1212a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1222a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber        return NULL;
1232a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    }
1242a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1252a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    decoder->start();
1262a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
127c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber    // Read one output buffer, ignore format change notifications
128c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber    // and spurious empty buffers.
129c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber
1307e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    MediaSource::ReadOptions options;
1317e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    int64_t thumbNailTime;
1327e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if (trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
1337e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        options.setSeekTo(thumbNailTime);
1344e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    } else {
1354e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        thumbNailTime = -1;
1367e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
1377e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
138c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber    MediaBuffer *buffer = NULL;
1397f281f87670c63775ea1ae8b24af31822d5ad416Andreas Huber    status_t err;
1407f281f87670c63775ea1ae8b24af31822d5ad416Andreas Huber    do {
141c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber        if (buffer != NULL) {
142c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber            buffer->release();
143c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber            buffer = NULL;
144c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber        }
1457e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        err = decoder->read(&buffer, &options);
1467e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        options.clearSeekTo();
147c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber    } while (err == INFO_FORMAT_CHANGED
148c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber             || (buffer != NULL && buffer->range_length() == 0));
1492a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1502a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    if (err != OK) {
1512a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber        CHECK_EQ(buffer, NULL);
1522a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
15347bed1a7755ed58fa5d4c0d35b20468deb83bd60Andreas Huber        LOGV("decoding frame failed.");
1542a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber        decoder->stop();
1552a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1562a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber        return NULL;
1572a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    }
1582a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
15947bed1a7755ed58fa5d4c0d35b20468deb83bd60Andreas Huber    LOGV("successfully decoded video frame.");
1602a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1614e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    int64_t timeUs;
1624e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
1634e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    if (thumbNailTime >= 0) {
1644e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        if (timeUs != thumbNailTime) {
1654e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber            const char *mime;
1664e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber            CHECK(trackMeta->findCString(kKeyMIMEType, &mime));
1674e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
1684e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber            LOGV("thumbNailTime = %lld us, timeUs = %lld us, mime = %s",
1694e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber                 thumbNailTime, timeUs, mime);
1704e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        }
1714e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    }
1724e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
1734e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    sp<MetaData> meta = decoder->getFormat();
1742a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1752a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    int32_t width, height;
1762a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    CHECK(meta->findInt32(kKeyWidth, &width));
1772a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    CHECK(meta->findInt32(kKeyHeight, &height));
1782a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1792a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    VideoFrame *frame = new VideoFrame;
1802a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    frame->mWidth = width;
1812a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    frame->mHeight = height;
1822a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    frame->mDisplayWidth = width;
1832a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    frame->mDisplayHeight = height;
1842a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    frame->mSize = width * height * 2;
1852a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    frame->mData = new uint8_t[frame->mSize];
1862a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1872a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    int32_t srcFormat;
1882a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    CHECK(meta->findInt32(kKeyColorFormat, &srcFormat));
1892a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1902a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    ColorConverter converter(
1912a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber            (OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565);
1922a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    CHECK(converter.isValid());
1932a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
1942a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    converter.convert(
1952a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber            width, height,
1962a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber            (const uint8_t *)buffer->data() + buffer->range_offset(),
1972a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber            0,
1982a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber            frame->mData, width * 2);
1992a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
2002a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    buffer->release();
2012a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    buffer = NULL;
2022a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
2032a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    decoder->stop();
2042a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
2052a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    return frame;
2062a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}
2072a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
2084e202e779a8495091ab189fd88fc295a3e619c61Andreas HuberVideoFrame *StagefrightMetadataRetriever::captureFrame() {
2094e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    LOGV("captureFrame");
2104e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2114e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    if (mExtractor.get() == NULL) {
2124e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        LOGV("no extractor.");
2134e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        return NULL;
2144e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    }
2154e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2164e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    size_t n = mExtractor->countTracks();
2174e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    size_t i;
2184e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    for (i = 0; i < n; ++i) {
2194e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
2204e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2214e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        const char *mime;
2224e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        CHECK(meta->findCString(kKeyMIMEType, &mime));
2234e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2244e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        if (!strncasecmp(mime, "video/", 6)) {
2254e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber            break;
2264e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        }
2274e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    }
2284e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2294e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    if (i == n) {
2304e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        LOGV("no video track found.");
2314e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        return NULL;
2324e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    }
2334e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2344e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
2354e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber            i, MediaExtractor::kIncludeExtensiveMetaData);
2364e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2374e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    sp<MediaSource> source = mExtractor->getTrack(i);
2384e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2394e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    if (source.get() == NULL) {
2404e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        LOGV("unable to instantiate video track.");
2414e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        return NULL;
2424e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    }
2434e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2444e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    VideoFrame *frame =
2454e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        extractVideoFrameWithCodecFlags(
2464e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber                &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs);
2474e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2484e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    if (frame == NULL) {
2494e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        LOGV("Software decoder failed to extract thumbnail, "
2504e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber             "trying hardware decoder.");
2514e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2524e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber        frame = extractVideoFrameWithCodecFlags(&mClient, trackMeta, source, 0);
2534e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    }
2544e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2554e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber    return frame;
2564e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber}
2574e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber
2582a4a7d5af053a17586a262a1267ba993e31790f1Andreas HuberMediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() {
2592a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    LOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO");
2602a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
261fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mExtractor == NULL) {
262fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
263fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
264fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
265fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (!mParsedMetaData) {
266fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        parseMetaData();
267fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
268fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mParsedMetaData = true;
269fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
270fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
271fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mAlbumArt) {
272fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return new MediaAlbumArt(*mAlbumArt);
273fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
274fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
2752a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber    return NULL;
2762a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}
2772a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
2782a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huberconst char *StagefrightMetadataRetriever::extractMetadata(int keyCode) {
279fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    LOGV("extractMetadata %d", keyCode);
2802a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
281fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (mExtractor == NULL) {
282fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
283fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
284fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
285fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (!mParsedMetaData) {
286fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        parseMetaData();
287fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
288fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mParsedMetaData = true;
289fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
290fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
291fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    ssize_t index = mMetaData.indexOfKey(keyCode);
292fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
293fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (index < 0) {
294fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
295fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
296fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
297fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return strdup(mMetaData.valueAt(index).string());
2982a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}
2992a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber
300fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid StagefrightMetadataRetriever::parseMetaData() {
301fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    sp<MetaData> meta = mExtractor->getMetaData();
302fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
303fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    struct Map {
304fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        int from;
305fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        int to;
306fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    };
307fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    static const Map kMap[] = {
3087be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber        { kKeyMIMEType, METADATA_KEY_MIMETYPE },
309bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber        { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER },
310fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        { kKeyAlbum, METADATA_KEY_ALBUM },
311fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        { kKeyArtist, METADATA_KEY_ARTIST },
312bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber        { kKeyAuthor, METADATA_KEY_AUTHOR },
313fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        { kKeyComposer, METADATA_KEY_COMPOSER },
314bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber        { kKeyDate, METADATA_KEY_DATE },
315fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        { kKeyGenre, METADATA_KEY_GENRE },
316fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        { kKeyTitle, METADATA_KEY_TITLE },
317fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        { kKeyYear, METADATA_KEY_YEAR },
31872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        { kKeyWriter, METADATA_KEY_WRITER },
319fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    };
320fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
321fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
322fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i < kNumMapEntries; ++i) {
323fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const char *value;
324fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (meta->findCString(kMap[i].from, &value)) {
325fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            mMetaData.add(kMap[i].to, String8(value));
326fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
327fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
328fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
329fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    const void *data;
330fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    uint32_t type;
331fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    size_t dataSize;
332fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (meta->findData(kKeyAlbumArt, &type, &data, &dataSize)) {
333fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mAlbumArt = new MediaAlbumArt;
334fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mAlbumArt->mSize = dataSize;
335fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        mAlbumArt->mData = new uint8_t[dataSize];
336fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        memcpy(mAlbumArt->mData, data, dataSize);
337fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
338fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
339bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber    size_t numTracks = mExtractor->countTracks();
340bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber
341bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber    char tmp[32];
342bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber    sprintf(tmp, "%d", numTracks);
343bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber
344bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber    mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp));
345bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber
346fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    // The overall duration is the duration of the longest track.
347fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    int64_t maxDurationUs = 0;
348bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber    for (size_t i = 0; i < numTracks; ++i) {
349fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);
350fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
351fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        int64_t durationUs;
352fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (trackMeta->findInt64(kKeyDuration, &durationUs)) {
353fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            if (durationUs > maxDurationUs) {
354fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber                maxDurationUs = durationUs;
355fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            }
356fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
357fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
358fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
359fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    // The duration value is a string representing the duration in ms.
360fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000);
361fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
362fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
363fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
364fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
3652a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber}  // namespace android
366