StagefrightMetadataRetriever.cpp revision 29357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47
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/ColorConverter.h> 242a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/DataSource.h> 25bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber#include <media/stagefright/FileSource.h> 262a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/MediaDebug.h> 272a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/MediaExtractor.h> 282a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/MetaData.h> 292a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/OMXCodec.h> 307a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include <media/stagefright/MediaDefs.h> 312a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 322a4a7d5af053a17586a262a1267ba993e31790f1Andreas Hubernamespace android { 332a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 34fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberStagefrightMetadataRetriever::StagefrightMetadataRetriever() 35fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber : mParsedMetaData(false), 36fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mAlbumArt(NULL) { 373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("StagefrightMetadataRetriever()"); 382a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 392a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber DataSource::RegisterDefaultSniffers(); 402a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber CHECK_EQ(mClient.connect(), OK); 412a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 422a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 432a4a7d5af053a17586a262a1267ba993e31790f1Andreas HuberStagefrightMetadataRetriever::~StagefrightMetadataRetriever() { 443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("~StagefrightMetadataRetriever()"); 45fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 46fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber delete mAlbumArt; 47fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mAlbumArt = NULL; 48fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 492a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber mClient.disconnect(); 502a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 512a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 52af8791e112c8072452bd14ef3c43a47511d19542Andreas Huberstatus_t StagefrightMetadataRetriever::setDataSource( 53af8791e112c8072452bd14ef3c43a47511d19542Andreas Huber const char *uri, const KeyedVector<String8, String8> *headers) { 543856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setDataSource(%s)", uri); 552a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 56fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mParsedMetaData = false; 57fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mMetaData.clear(); 58fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber delete mAlbumArt; 59fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mAlbumArt = NULL; 60fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 61af8791e112c8072452bd14ef3c43a47511d19542Andreas Huber mSource = DataSource::CreateFromURI(uri, headers); 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 833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("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, 11316afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong const sp<MediaSource> &source, 11416afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong uint32_t flags, 11516afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong int64_t frameTimeUs, 11616afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong int seekMode) { 1172a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber sp<MediaSource> decoder = 1182a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber OMXCodec::Create( 1194e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber client->interface(), source->getFormat(), false, source, 120f3712f026aad1fc46b1df18d1dba718281e39726Andreas Huber NULL, flags | OMXCodec::kClientNeedsFramebuffer); 1212a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1222a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber if (decoder.get() == NULL) { 1233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("unable to instantiate video decoder."); 1242a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1252a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber return NULL; 1262a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 1272a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 128139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber status_t err = decoder->start(); 129139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber if (err != OK) { 1305ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("OMXCodec::start returned error %d (0x%08x)\n", err, err); 131139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber return NULL; 132139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber } 1332a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 134c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber // Read one output buffer, ignore format change notifications 135c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber // and spurious empty buffers. 136c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber 1377e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber MediaSource::ReadOptions options; 13816afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong if (seekMode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC || 13916afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong seekMode > MediaSource::ReadOptions::SEEK_CLOSEST) { 14016afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong 14129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown seek mode: %d", seekMode); 14216afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong return NULL; 14316afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong } 14416afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong 14516afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong MediaSource::ReadOptions::SeekMode mode = 14616afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong static_cast<MediaSource::ReadOptions::SeekMode>(seekMode); 14716afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong 1487e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber int64_t thumbNailTime; 149cb0cb25002f1b5fe0d02c997bac487b5b6c5c682Andreas Huber if (frameTimeUs < 0) { 15021af757836167a328ddf1c0381909d53941528c4Andreas Huber if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime) 15121af757836167a328ddf1c0381909d53941528c4Andreas Huber || thumbNailTime < 0) { 152cb0cb25002f1b5fe0d02c997bac487b5b6c5c682Andreas Huber thumbNailTime = 0; 153cb0cb25002f1b5fe0d02c997bac487b5b6c5c682Andreas Huber } 15416afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong options.setSeekTo(thumbNailTime, mode); 1554e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } else { 1564e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber thumbNailTime = -1; 15716afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong options.setSeekTo(frameTimeUs, mode); 1587e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 1597e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 160c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber MediaBuffer *buffer = NULL; 1617f281f87670c63775ea1ae8b24af31822d5ad416Andreas Huber do { 162c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber if (buffer != NULL) { 163c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber buffer->release(); 164c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber buffer = NULL; 165c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber } 1667e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber err = decoder->read(&buffer, &options); 1677e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber options.clearSeekTo(); 168c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber } while (err == INFO_FORMAT_CHANGED 169c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber || (buffer != NULL && buffer->range_length() == 0)); 1702a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1712a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber if (err != OK) { 1722a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber CHECK_EQ(buffer, NULL); 1732a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1743856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("decoding frame failed."); 1752a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber decoder->stop(); 1762a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1772a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber return NULL; 1782a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 1792a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("successfully decoded video frame."); 1812a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1822b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber int32_t unreadable; 1832b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber if (buffer->meta_data()->findInt32(kKeyIsUnreadable, &unreadable) 1842b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber && unreadable != 0) { 1853856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("video frame is unreadable, decoder does not give us access " 1862b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber "to the video data."); 1872b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber 1882b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber buffer->release(); 1892b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber buffer = NULL; 1902b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber 1912b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber decoder->stop(); 1922b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber 1932b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber return NULL; 1942b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber } 1952b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber 1964e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber int64_t timeUs; 1974e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); 1984e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber if (thumbNailTime >= 0) { 1994e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber if (timeUs != thumbNailTime) { 2004e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber const char *mime; 2014e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber CHECK(trackMeta->findCString(kKeyMIMEType, &mime)); 2024e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 2033856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("thumbNailTime = %lld us, timeUs = %lld us, mime = %s", 2044e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber thumbNailTime, timeUs, mime); 2054e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 2064e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 2074e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 2084e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber sp<MetaData> meta = decoder->getFormat(); 2092a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2102a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber int32_t width, height; 2112a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber CHECK(meta->findInt32(kKeyWidth, &width)); 2122a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber CHECK(meta->findInt32(kKeyHeight, &height)); 2132a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 214f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber int32_t crop_left, crop_top, crop_right, crop_bottom; 215f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber if (!meta->findRect( 216f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber kKeyCropRect, 217f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber &crop_left, &crop_top, &crop_right, &crop_bottom)) { 218f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber crop_left = crop_top = 0; 219f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber crop_right = width - 1; 220f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber crop_bottom = height - 1; 221f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber } 222f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 223ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong int32_t rotationAngle; 224ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) { 225ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong rotationAngle = 0; // By default, no rotation 226ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong } 227ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong 2282a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber VideoFrame *frame = new VideoFrame; 229f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber frame->mWidth = crop_right - crop_left + 1; 230f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber frame->mHeight = crop_bottom - crop_top + 1; 231f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber frame->mDisplayWidth = frame->mWidth; 232f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber frame->mDisplayHeight = frame->mHeight; 233f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber frame->mSize = frame->mWidth * frame->mHeight * 2; 2342a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber frame->mData = new uint8_t[frame->mSize]; 235ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong frame->mRotationAngle = rotationAngle; 2362a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2371d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong int32_t displayWidth, displayHeight; 2381d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) { 2391d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong frame->mDisplayWidth = displayWidth; 2401d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong } 2411d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong if (meta->findInt32(kKeyDisplayHeight, &displayHeight)) { 2421d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong frame->mDisplayHeight = displayHeight; 2431d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong } 2441d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong 2452a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber int32_t srcFormat; 2462a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber CHECK(meta->findInt32(kKeyColorFormat, &srcFormat)); 2472a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2482a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber ColorConverter converter( 2492a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber (OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565); 2502a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber CHECK(converter.isValid()); 2512a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 252b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber err = converter.convert( 2532a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(), 254f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber width, height, 255f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber crop_left, crop_top, crop_right, crop_bottom, 256f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber frame->mData, 257f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber frame->mWidth, 258f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber frame->mHeight, 259f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 0, 0, frame->mWidth - 1, frame->mHeight - 1); 2602a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2612a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber buffer->release(); 2622a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber buffer = NULL; 2632a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2642a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber decoder->stop(); 2652a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 266b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber if (err != OK) { 26729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Colorconverter failed to convert frame."); 268b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber 269b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber delete frame; 270b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber frame = NULL; 271b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber } 272b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber 2732a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber return frame; 2742a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 2752a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 27616afe2fb439cab6125bb46a07a8078d4ce1c1ea5James DongVideoFrame *StagefrightMetadataRetriever::getFrameAtTime( 27716afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong int64_t timeUs, int option) { 2784e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 2793856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("getFrameAtTime: %lld us option: %d", timeUs, option); 28093e1fb99a0c66784b49b105ce84a23baf054ee9cAndreas Huber 2814e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber if (mExtractor.get() == NULL) { 2823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("no extractor."); 2834e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber return NULL; 2844e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 2854e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 286e7484f36061a60aadadb01143d84964d931aa837Andreas Huber sp<MetaData> fileMeta = mExtractor->getMetaData(); 287e7484f36061a60aadadb01143d84964d931aa837Andreas Huber 288e7484f36061a60aadadb01143d84964d931aa837Andreas Huber if (fileMeta == NULL) { 2893856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("extractor doesn't publish metadata, failed to initialize?"); 290e7484f36061a60aadadb01143d84964d931aa837Andreas Huber return NULL; 291e7484f36061a60aadadb01143d84964d931aa837Andreas Huber } 292e7484f36061a60aadadb01143d84964d931aa837Andreas Huber 2938ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten int32_t drm = 0; 294e7484f36061a60aadadb01143d84964d931aa837Andreas Huber if (fileMeta->findInt32(kKeyIsDRM, &drm) && drm != 0) { 29529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("frame grab not allowed."); 2968ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten return NULL; 2978ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten } 2988ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten 2994e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber size_t n = mExtractor->countTracks(); 3004e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber size_t i; 3014e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber for (i = 0; i < n; ++i) { 3024e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber sp<MetaData> meta = mExtractor->getTrackMetaData(i); 3034e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 3044e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber const char *mime; 3054e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber CHECK(meta->findCString(kKeyMIMEType, &mime)); 3064e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 3074e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber if (!strncasecmp(mime, "video/", 6)) { 3084e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber break; 3094e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 3104e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 3114e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 3124e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber if (i == n) { 3133856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("no video track found."); 3144e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber return NULL; 3154e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 3164e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 3174e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber sp<MetaData> trackMeta = mExtractor->getTrackMetaData( 3184e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber i, MediaExtractor::kIncludeExtensiveMetaData); 3194e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 3204e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber sp<MediaSource> source = mExtractor->getTrack(i); 3214e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 3224e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber if (source.get() == NULL) { 3233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("unable to instantiate video track."); 3244e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber return NULL; 3254e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 3264e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 327515e855eae78aa495da58356486aaa666cb57fd1James Dong const void *data; 328515e855eae78aa495da58356486aaa666cb57fd1James Dong uint32_t type; 329515e855eae78aa495da58356486aaa666cb57fd1James Dong size_t dataSize; 330e7484f36061a60aadadb01143d84964d931aa837Andreas Huber if (fileMeta->findData(kKeyAlbumArt, &type, &data, &dataSize) 331515e855eae78aa495da58356486aaa666cb57fd1James Dong && mAlbumArt == NULL) { 332515e855eae78aa495da58356486aaa666cb57fd1James Dong mAlbumArt = new MediaAlbumArt; 333515e855eae78aa495da58356486aaa666cb57fd1James Dong mAlbumArt->mSize = dataSize; 334515e855eae78aa495da58356486aaa666cb57fd1James Dong mAlbumArt->mData = new uint8_t[dataSize]; 335515e855eae78aa495da58356486aaa666cb57fd1James Dong memcpy(mAlbumArt->mData, data, dataSize); 336515e855eae78aa495da58356486aaa666cb57fd1James Dong } 337515e855eae78aa495da58356486aaa666cb57fd1James Dong 3384e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber VideoFrame *frame = 3394e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber extractVideoFrameWithCodecFlags( 34016afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs, 34116afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong timeUs, option); 3424e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 3434e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber if (frame == NULL) { 3443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("Software decoder failed to extract thumbnail, " 3454e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber "trying hardware decoder."); 3464e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 34716afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong frame = extractVideoFrameWithCodecFlags(&mClient, trackMeta, source, 0, 34816afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong timeUs, option); 3494e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 3504e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 3514e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber return frame; 3524e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber} 3534e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 3542a4a7d5af053a17586a262a1267ba993e31790f1Andreas HuberMediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() { 3553856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO"); 3562a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 357fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mExtractor == NULL) { 358fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return NULL; 359fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 360fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 361fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!mParsedMetaData) { 362fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber parseMetaData(); 363fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 364fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mParsedMetaData = true; 365fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 366fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 367fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mAlbumArt) { 368fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return new MediaAlbumArt(*mAlbumArt); 369fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 370fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 3712a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber return NULL; 3722a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 3732a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 3742a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huberconst char *StagefrightMetadataRetriever::extractMetadata(int keyCode) { 375fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mExtractor == NULL) { 376fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return NULL; 377fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 378fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 379fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!mParsedMetaData) { 380fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber parseMetaData(); 381fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 382fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mParsedMetaData = true; 383fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 384fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 385fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber ssize_t index = mMetaData.indexOfKey(keyCode); 386fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 387fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (index < 0) { 388fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return NULL; 389fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 390fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 391fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return strdup(mMetaData.valueAt(index).string()); 3922a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 3932a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 394fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid StagefrightMetadataRetriever::parseMetaData() { 395fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber sp<MetaData> meta = mExtractor->getMetaData(); 396fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 397e7484f36061a60aadadb01143d84964d931aa837Andreas Huber if (meta == NULL) { 3983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("extractor doesn't publish metadata, failed to initialize?"); 399e7484f36061a60aadadb01143d84964d931aa837Andreas Huber return; 400e7484f36061a60aadadb01143d84964d931aa837Andreas Huber } 401e7484f36061a60aadadb01143d84964d931aa837Andreas Huber 402fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber struct Map { 403fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber int from; 404fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber int to; 405fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber }; 406fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber static const Map kMap[] = { 4077be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber { kKeyMIMEType, METADATA_KEY_MIMETYPE }, 408bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER }, 4096c8a9a4132337a3419a72a735f0b40df0b82061fMarco Nelissen { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER }, 410fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber { kKeyAlbum, METADATA_KEY_ALBUM }, 411fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber { kKeyArtist, METADATA_KEY_ARTIST }, 41266ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST }, 413bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber { kKeyAuthor, METADATA_KEY_AUTHOR }, 414fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber { kKeyComposer, METADATA_KEY_COMPOSER }, 415bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber { kKeyDate, METADATA_KEY_DATE }, 416fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber { kKeyGenre, METADATA_KEY_GENRE }, 417fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber { kKeyTitle, METADATA_KEY_TITLE }, 418fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber { kKeyYear, METADATA_KEY_YEAR }, 41972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { kKeyWriter, METADATA_KEY_WRITER }, 42011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { kKeyCompilation, METADATA_KEY_COMPILATION }, 4214948818cb91176df74c972ac27b2f392b5d148bcJames Dong { kKeyLocation, METADATA_KEY_LOCATION }, 422fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber }; 423fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]); 424fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 425fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber for (size_t i = 0; i < kNumMapEntries; ++i) { 426fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber const char *value; 427fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (meta->findCString(kMap[i].from, &value)) { 428fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mMetaData.add(kMap[i].to, String8(value)); 429fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 430fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 431fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 432fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber const void *data; 433fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber uint32_t type; 434fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t dataSize; 435515e855eae78aa495da58356486aaa666cb57fd1James Dong if (meta->findData(kKeyAlbumArt, &type, &data, &dataSize) 436515e855eae78aa495da58356486aaa666cb57fd1James Dong && mAlbumArt == NULL) { 437fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mAlbumArt = new MediaAlbumArt; 438fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mAlbumArt->mSize = dataSize; 439fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mAlbumArt->mData = new uint8_t[dataSize]; 440fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber memcpy(mAlbumArt->mData, data, dataSize); 441fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 442fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 443bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber size_t numTracks = mExtractor->countTracks(); 444bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber 445bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber char tmp[32]; 446bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber sprintf(tmp, "%d", numTracks); 447bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber 448bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp)); 449bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber 4502256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber bool hasAudio = false; 4512256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber bool hasVideo = false; 4522256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber int32_t videoWidth = -1; 4532256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber int32_t videoHeight = -1; 4542256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber int32_t audioBitrate = -1; 4552256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 456fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // The overall duration is the duration of the longest track. 457fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber int64_t maxDurationUs = 0; 4587a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang String8 timedTextLang; 459bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber for (size_t i = 0; i < numTracks; ++i) { 460fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i); 461fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 462fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber int64_t durationUs; 463fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (trackMeta->findInt64(kKeyDuration, &durationUs)) { 464fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (durationUs > maxDurationUs) { 465fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber maxDurationUs = durationUs; 466fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 467fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 4682256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 4692256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber const char *mime; 4702256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber if (trackMeta->findCString(kKeyMIMEType, &mime)) { 4712256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber if (!hasAudio && !strncasecmp("audio/", mime, 6)) { 4722256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber hasAudio = true; 4732256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 4742256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) { 4752256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber audioBitrate = -1; 4762256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } 4772256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } else if (!hasVideo && !strncasecmp("video/", mime, 6)) { 4782256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber hasVideo = true; 4792256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 4802256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth)); 4812256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight)); 4827a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) { 4837a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang const char *lang; 4847a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang trackMeta->findCString(kKeyMediaLanguage, &lang); 4857a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang timedTextLang.append(String8(lang)); 4867a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang timedTextLang.append(String8(":")); 4872256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } 4882256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } 489fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 490fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 4917a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // To save the language codes for all timed text tracks 4927a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // If multiple text tracks present, the format will look 4937a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // like "eng:chi" 4947a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang if (!timedTextLang.isEmpty()) { 4957a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang mMetaData.add(METADATA_KEY_TIMED_TEXT_LANGUAGES, timedTextLang); 4967a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 4977a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 498fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // The duration value is a string representing the duration in ms. 499fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000); 500fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mMetaData.add(METADATA_KEY_DURATION, String8(tmp)); 501093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 5022256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber if (hasAudio) { 5032256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber mMetaData.add(METADATA_KEY_HAS_AUDIO, String8("yes")); 5042256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } 5052256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 5062256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber if (hasVideo) { 5072256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber mMetaData.add(METADATA_KEY_HAS_VIDEO, String8("yes")); 5082256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 5092256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber sprintf(tmp, "%d", videoWidth); 5102256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber mMetaData.add(METADATA_KEY_VIDEO_WIDTH, String8(tmp)); 5112256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 5122256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber sprintf(tmp, "%d", videoHeight); 5132256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber mMetaData.add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp)); 5142256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } 5152256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 5162256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber if (numTracks == 1 && hasAudio && audioBitrate >= 0) { 5171d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong sprintf(tmp, "%d", audioBitrate); 5182256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber mMetaData.add(METADATA_KEY_BITRATE, String8(tmp)); 5192256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } else { 5202256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber off64_t sourceSize; 5212256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber if (mSource->getSize(&sourceSize) == OK) { 5222256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs); 5232256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 5242256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber sprintf(tmp, "%lld", avgBitRate); 5252256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber mMetaData.add(METADATA_KEY_BITRATE, String8(tmp)); 5262256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } 5272256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } 5282256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 529093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (numTracks == 1) { 530093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const char *fileMIME; 531093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(meta->findCString(kKeyMIMEType, &fileMIME)); 532093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 533093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcasecmp(fileMIME, "video/x-matroska")) { 534093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MetaData> trackMeta = mExtractor->getTrackMetaData(0); 535093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const char *trackMIME; 536093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(trackMeta->findCString(kKeyMIMEType, &trackMIME)); 537093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 538093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strncasecmp("audio/", trackMIME, 6)) { 539093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber // The matroska file only contains a single audio track, 540093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber // rewrite its mime type. 541093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mMetaData.add( 542093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber METADATA_KEY_MIMETYPE, String8("audio/x-matroska")); 543093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 544093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 545093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 5460d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang 5470d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang // To check whether the media file is drm-protected 5480d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang if (mExtractor->getDrmFlag()) { 5490d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang mMetaData.add(METADATA_KEY_IS_DRM, String8("1")); 5500d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang } 551fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 552fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 5532a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} // namespace android 554