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