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" 19a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn 20377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT#include <inttypes.h> 21a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn 222a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <utils/Log.h> 2336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan#include <gui/Surface.h> 242a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2545edc1f7009a31b21bed7b25314778336f56bfbeHangyu Kuang#include "include/avc_utils.h" 2667e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber#include "include/StagefrightMetadataRetriever.h" 272a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 2836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan#include <media/ICrypto.h> 291b86fe063badb5f28c467ade39be0f4008688947Andreas Huber#include <media/IMediaHTTPService.h> 3036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan 3136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan#include <media/stagefright/foundation/ABuffer.h> 32f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h> 3336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan#include <media/stagefright/foundation/AMessage.h> 342a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/ColorConverter.h> 352a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/DataSource.h> 36bfa6b2d7a1be1832ac40ed90aece1834f720b5c6Andreas Huber#include <media/stagefright/FileSource.h> 3736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan#include <media/stagefright/MediaBuffer.h> 3836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan#include <media/stagefright/MediaCodec.h> 396b0795009b8f53ab771e0074b76381977d016f4bLajos Molnar#include <media/stagefright/MediaCodecList.h> 4036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan#include <media/stagefright/MediaDefs.h> 4136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan#include <media/stagefright/MediaErrors.h> 422a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/MediaExtractor.h> 436b0795009b8f53ab771e0074b76381977d016f4bLajos Molnar#include <media/stagefright/MediaSource.h> 442a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber#include <media/stagefright/MetaData.h> 4536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan#include <media/stagefright/Utils.h> 4636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan 4734581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen#include <CharacterEncodingDetector.h> 482a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 492a4a7d5af053a17586a262a1267ba993e31790f1Andreas Hubernamespace android { 502a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 5136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavanstatic const int64_t kBufferTimeOutUs = 30000ll; // 30 msec 5236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavanstatic const size_t kRetryCount = 20; // must be >0 5336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan 54fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas HuberStagefrightMetadataRetriever::StagefrightMetadataRetriever() 55fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber : mParsedMetaData(false), 56fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mAlbumArt(NULL) { 573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("StagefrightMetadataRetriever()"); 582a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 592a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber DataSource::RegisterDefaultSniffers(); 602a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 612a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 622a4a7d5af053a17586a262a1267ba993e31790f1Andreas HuberStagefrightMetadataRetriever::~StagefrightMetadataRetriever() { 633856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("~StagefrightMetadataRetriever()"); 6499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins clearMetadata(); 65665df6f7c5b3189f9555ebe14cde3d0d24a5a024Lajos Molnar if (mSource != NULL) { 66665df6f7c5b3189f9555ebe14cde3d0d24a5a024Lajos Molnar mSource->close(); 67665df6f7c5b3189f9555ebe14cde3d0d24a5a024Lajos Molnar } 682a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 692a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 70af8791e112c8072452bd14ef3c43a47511d19542Andreas Huberstatus_t StagefrightMetadataRetriever::setDataSource( 711b86fe063badb5f28c467ade39be0f4008688947Andreas Huber const sp<IMediaHTTPService> &httpService, 721b86fe063badb5f28c467ade39be0f4008688947Andreas Huber const char *uri, 731b86fe063badb5f28c467ade39be0f4008688947Andreas Huber const KeyedVector<String8, String8> *headers) { 743856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("setDataSource(%s)", uri); 752a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 7699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins clearMetadata(); 771b86fe063badb5f28c467ade39be0f4008688947Andreas Huber mSource = DataSource::CreateFromURI(httpService, uri, headers); 78fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 79fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mSource == NULL) { 80f4b7d94062c896dca565d849c6188cd3489be257Andreas Huber ALOGE("Unable to create data source for '%s'.", uri); 81fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return UNKNOWN_ERROR; 82fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 83fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 84fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mExtractor = MediaExtractor::Create(mSource); 85fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 86fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mExtractor == NULL) { 87f4b7d94062c896dca565d849c6188cd3489be257Andreas Huber ALOGE("Unable to instantiate an extractor for '%s'.", uri); 88f4b7d94062c896dca565d849c6188cd3489be257Andreas Huber 89fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mSource.clear(); 902a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 91fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return UNKNOWN_ERROR; 92fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 93fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 94fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return OK; 952a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 962a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 97fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber// Warning caller retains ownership of the filedescriptor! Dup it if necessary. 982a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huberstatus_t StagefrightMetadataRetriever::setDataSource( 992a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber int fd, int64_t offset, int64_t length) { 100fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber fd = dup(fd); 101fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 102a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length); 1032a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 10499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins clearMetadata(); 105fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mSource = new FileSource(fd, offset, length); 106fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 107fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber status_t err; 108fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if ((err = mSource->initCheck()) != OK) { 109fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mSource.clear(); 110fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 111fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return err; 112fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 113fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 114fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mExtractor = MediaExtractor::Create(mSource); 115fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 116fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mExtractor == NULL) { 117fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mSource.clear(); 118fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 119fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return UNKNOWN_ERROR; 120fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 1212a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 1222a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber return OK; 1232a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 1242a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 12599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkinsstatus_t StagefrightMetadataRetriever::setDataSource( 12699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins const sp<DataSource>& source) { 12799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins ALOGV("setDataSource(DataSource)"); 12899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 12999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins clearMetadata(); 13099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins mSource = source; 13199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins mExtractor = MediaExtractor::Create(mSource); 13299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 13399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (mExtractor == NULL) { 13499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins ALOGE("Failed to instantiate a MediaExtractor."); 13599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins mSource.clear(); 13699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return UNKNOWN_ERROR; 13799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 13899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 13999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return OK; 14099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 14199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 14236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavanstatic VideoFrame *extractVideoFrame( 1436b0795009b8f53ab771e0074b76381977d016f4bLajos Molnar const AString &componentName, 1444e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber const sp<MetaData> &trackMeta, 145b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen const sp<IMediaSource> &source, 14616afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong int64_t frameTimeUs, 14716afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong int seekMode) { 1488fa80e3be63ffde5ef029afa713877440856b663James Dong 1498fa80e3be63ffde5ef029afa713877440856b663James Dong sp<MetaData> format = source->getFormat(); 1508fa80e3be63ffde5ef029afa713877440856b663James Dong 15136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan sp<AMessage> videoFormat; 152ed78e2fdf53b72be4647be88a02a120869415015Wei Jia if (convertMetaDataToMessage(trackMeta, &videoFormat) != OK) { 153be094287351c59fe06b4c8d3aa73f7f7de0522d0Wei Jia ALOGE("b/23680780"); 154ed78e2fdf53b72be4647be88a02a120869415015Wei Jia ALOGW("Failed to convert meta data to message"); 155ed78e2fdf53b72be4647be88a02a120869415015Wei Jia return NULL; 156ed78e2fdf53b72be4647be88a02a120869415015Wei Jia } 1578fa80e3be63ffde5ef029afa713877440856b663James Dong 15836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan // TODO: Use Flexible color instead 15936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan videoFormat->setInt32("color-format", OMX_COLOR_FormatYUV420Planar); 1602a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 16136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan status_t err; 16236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan sp<ALooper> looper = new ALooper; 16336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan looper->start(); 16436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan sp<MediaCodec> decoder = MediaCodec::CreateByComponentName( 16536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan looper, componentName, &err); 1662a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 16736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (decoder.get() == NULL || err != OK) { 1686b0795009b8f53ab771e0074b76381977d016f4bLajos Molnar ALOGW("Failed to instantiate decoder [%s]", componentName.c_str()); 1692a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber return NULL; 1702a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 1712a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 17236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan err = decoder->configure(videoFormat, NULL /* surface */, NULL /* crypto */, 0 /* flags */); 173139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber if (err != OK) { 17436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGW("configure returned error %d (%s)", err, asString(err)); 17536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan decoder->release(); 176139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber return NULL; 177139a5d5bd33c9fc7708d0a79f11ee928f7796e6bAndreas Huber } 1782a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 17936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan err = decoder->start(); 18036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (err != OK) { 18136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGW("start returned error %d (%s)", err, asString(err)); 18236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan decoder->release(); 18336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan return NULL; 18436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } 185c6323f9d72e0f08dd1e813550a56c8d2f0fd76a2Andreas Huber 1867e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber MediaSource::ReadOptions options; 18716afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong if (seekMode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC || 18816afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong seekMode > MediaSource::ReadOptions::SEEK_CLOSEST) { 18916afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong 19029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Unknown seek mode: %d", seekMode); 19136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan decoder->release(); 19216afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong return NULL; 19316afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong } 19416afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong 19516afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong MediaSource::ReadOptions::SeekMode mode = 19616afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong static_cast<MediaSource::ReadOptions::SeekMode>(seekMode); 19716afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong 1987e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber int64_t thumbNailTime; 199cb0cb25002f1b5fe0d02c997bac487b5b6c5c682Andreas Huber if (frameTimeUs < 0) { 20021af757836167a328ddf1c0381909d53941528c4Andreas Huber if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime) 20121af757836167a328ddf1c0381909d53941528c4Andreas Huber || thumbNailTime < 0) { 202cb0cb25002f1b5fe0d02c997bac487b5b6c5c682Andreas Huber thumbNailTime = 0; 203cb0cb25002f1b5fe0d02c997bac487b5b6c5c682Andreas Huber } 20416afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong options.setSeekTo(thumbNailTime, mode); 2054e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } else { 2064e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber thumbNailTime = -1; 20716afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong options.setSeekTo(frameTimeUs, mode); 2087e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 2097e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 21036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan err = source->start(); 2112a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber if (err != OK) { 21236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGW("source failed to start: %d (%s)", err, asString(err)); 21336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan decoder->release(); 21436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan return NULL; 21536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } 2162a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 21736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan Vector<sp<ABuffer> > inputBuffers; 21836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan err = decoder->getInputBuffers(&inputBuffers); 21936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (err != OK) { 22036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGW("failed to get input buffers: %d (%s)", err, asString(err)); 22136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan decoder->release(); 222e7d8e71e45028cbe51839c23f922ba8c506cba82Marco Nelissen source->stop(); 22336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan return NULL; 22436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } 2252a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 22636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan Vector<sp<ABuffer> > outputBuffers; 22736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan err = decoder->getOutputBuffers(&outputBuffers); 22836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (err != OK) { 22936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGW("failed to get output buffers: %d (%s)", err, asString(err)); 23036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan decoder->release(); 231e7d8e71e45028cbe51839c23f922ba8c506cba82Marco Nelissen source->stop(); 2322a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber return NULL; 2332a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber } 2342a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 23536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan sp<AMessage> outputFormat = NULL; 23636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan bool haveMoreInputs = true; 23736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan size_t index, offset, size; 23836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan int64_t timeUs; 23936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan size_t retriesLeft = kRetryCount; 24036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan bool done = false; 24145edc1f7009a31b21bed7b25314778336f56bfbeHangyu Kuang const char *mime; 24245edc1f7009a31b21bed7b25314778336f56bfbeHangyu Kuang bool success = format->findCString(kKeyMIMEType, &mime); 24345edc1f7009a31b21bed7b25314778336f56bfbeHangyu Kuang if (!success) { 24445edc1f7009a31b21bed7b25314778336f56bfbeHangyu Kuang ALOGE("Could not find mime type"); 24545edc1f7009a31b21bed7b25314778336f56bfbeHangyu Kuang return NULL; 24645edc1f7009a31b21bed7b25314778336f56bfbeHangyu Kuang } 24745edc1f7009a31b21bed7b25314778336f56bfbeHangyu Kuang 24845edc1f7009a31b21bed7b25314778336f56bfbeHangyu Kuang bool isAvcOrHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC) 24945edc1f7009a31b21bed7b25314778336f56bfbeHangyu Kuang || !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC); 25036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan 25136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan do { 25236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan size_t inputIndex = -1; 25336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan int64_t ptsUs = 0ll; 25436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan uint32_t flags = 0; 25536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan sp<ABuffer> codecBuffer = NULL; 25636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan 25736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan while (haveMoreInputs) { 25836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan err = decoder->dequeueInputBuffer(&inputIndex, kBufferTimeOutUs); 25936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (err != OK) { 26036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGW("Timed out waiting for input"); 26136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (retriesLeft) { 26236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan err = OK; 26336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } 26436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan break; 26536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } 26636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan codecBuffer = inputBuffers[inputIndex]; 2672a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 26836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan MediaBuffer *mediaBuffer = NULL; 2692b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber 27036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan err = source->read(&mediaBuffer, &options); 27136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan options.clearSeekTo(); 27236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (err != OK) { 27336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGW("Input Error or EOS"); 27436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan haveMoreInputs = false; 27536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan break; 27636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } 2772b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber 27836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (mediaBuffer->range_length() > codecBuffer->capacity()) { 27936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGE("buffer size (%zu) too large for codec input size (%zu)", 28036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan mediaBuffer->range_length(), codecBuffer->capacity()); 28136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan err = BAD_VALUE; 28236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } else { 28336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan codecBuffer->setRange(0, mediaBuffer->range_length()); 28436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan 28536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan CHECK(mediaBuffer->meta_data()->findInt64(kKeyTime, &ptsUs)); 28636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan memcpy(codecBuffer->data(), 28736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan (const uint8_t*)mediaBuffer->data() + mediaBuffer->range_offset(), 28836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan mediaBuffer->range_length()); 28945edc1f7009a31b21bed7b25314778336f56bfbeHangyu Kuang if (isAvcOrHevc && IsIDR(codecBuffer)) { 29045edc1f7009a31b21bed7b25314778336f56bfbeHangyu Kuang // Only need to decode one IDR frame. 29145edc1f7009a31b21bed7b25314778336f56bfbeHangyu Kuang haveMoreInputs = false; 29245edc1f7009a31b21bed7b25314778336f56bfbeHangyu Kuang flags |= MediaCodec::BUFFER_FLAG_EOS; 29345edc1f7009a31b21bed7b25314778336f56bfbeHangyu Kuang } 29436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } 2952b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber 29636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan mediaBuffer->release(); 29736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan break; 29836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } 29936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan 30036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (err == OK && inputIndex < inputBuffers.size()) { 30136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGV("QueueInput: size=%zu ts=%" PRId64 " us flags=%x", 30236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan codecBuffer->size(), ptsUs, flags); 30336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan err = decoder->queueInputBuffer( 30436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan inputIndex, 30536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan codecBuffer->offset(), 30636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan codecBuffer->size(), 30736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ptsUs, 30836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan flags); 30936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan 31036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan // we don't expect an output from codec config buffer 31136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) { 31236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan continue; 31336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } 31436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } 31536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan 31636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan while (err == OK) { 31736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan // wait for a decoded buffer 31836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan err = decoder->dequeueOutputBuffer( 31936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan &index, 32036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan &offset, 32136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan &size, 32236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan &timeUs, 32336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan &flags, 32436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan kBufferTimeOutUs); 32536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan 32636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (err == INFO_FORMAT_CHANGED) { 32736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGV("Received format change"); 32836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan err = decoder->getOutputFormat(&outputFormat); 32936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { 33036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGV("Output buffers changed"); 33136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan err = decoder->getOutputBuffers(&outputBuffers); 33236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } else { 33336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (err == -EAGAIN /* INFO_TRY_AGAIN_LATER */ && --retriesLeft > 0) { 3345011629ad8212397263702f6b585547767f30726Lajos Molnar ALOGV("Timed-out waiting for output.. retries left = %zu", retriesLeft); 33536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan err = OK; 33636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } else if (err == OK) { 33736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGV("Received an output buffer"); 33836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan done = true; 33936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } else { 34036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGW("Received error %d (%s) instead of output", err, asString(err)); 34136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan done = true; 34236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } 34336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan break; 34436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } 34536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } 34636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } while (err == OK && !done); 34736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan 34836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (err != OK || size <= 0 || outputFormat == NULL) { 34936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGE("Failed to decode thumbnail frame"); 35036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan source->stop(); 35136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan decoder->release(); 3522b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber return NULL; 3532b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber } 3542b82e9652ba049e754c2cc74e381282f231d5fbfAndreas Huber 35536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGV("successfully decoded video frame."); 35636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan sp<ABuffer> videoFrameBuffer = outputBuffers.itemAt(index); 35736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan 3584e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber if (thumbNailTime >= 0) { 3594e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber if (timeUs != thumbNailTime) { 36036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan AString mime; 36136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan CHECK(outputFormat->findString("mime", &mime)); 3624e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 36336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGV("thumbNailTime = %lld us, timeUs = %lld us, mime = %s", 36436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan (long long)thumbNailTime, (long long)timeUs, mime.c_str()); 3654e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 3664e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 3674e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 3682a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber int32_t width, height; 36936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan CHECK(outputFormat->findInt32("width", &width)); 37036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan CHECK(outputFormat->findInt32("height", &height)); 3712a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 372f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber int32_t crop_left, crop_top, crop_right, crop_bottom; 37336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (!outputFormat->findRect("crop", &crop_left, &crop_top, &crop_right, &crop_bottom)) { 374f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber crop_left = crop_top = 0; 375f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber crop_right = width - 1; 376f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber crop_bottom = height - 1; 377f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber } 378f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber 379ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong int32_t rotationAngle; 380ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) { 381ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong rotationAngle = 0; // By default, no rotation 382ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong } 383ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong 3842a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber VideoFrame *frame = new VideoFrame; 385f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber frame->mWidth = crop_right - crop_left + 1; 386f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber frame->mHeight = crop_bottom - crop_top + 1; 387f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber frame->mDisplayWidth = frame->mWidth; 388f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber frame->mDisplayHeight = frame->mHeight; 389f5ab57c2d5e02af7483c94eddb177e4f5c9e9892Andreas Huber frame->mSize = frame->mWidth * frame->mHeight * 2; 3902a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber frame->mData = new uint8_t[frame->mSize]; 391ce0febae177d1816ee7a6750ed9fba52472b9a71James Dong frame->mRotationAngle = rotationAngle; 3922a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 39336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan int32_t sarWidth, sarHeight; 39436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (trackMeta->findInt32(kKeySARWidth, &sarWidth) 39536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan && trackMeta->findInt32(kKeySARHeight, &sarHeight) 39636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan && sarHeight != 0) { 39736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan frame->mDisplayWidth = (frame->mDisplayWidth * sarWidth) / sarHeight; 3981d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong } 3991d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong 4002a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber int32_t srcFormat; 40136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan CHECK(outputFormat->findInt32("color-format", &srcFormat)); 4022a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 40336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ColorConverter converter((OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565); 404de321c324cc4af88a8ea54d08c63546f73677037Andreas Huber 405de321c324cc4af88a8ea54d08c63546f73677037Andreas Huber if (converter.isValid()) { 406de321c324cc4af88a8ea54d08c63546f73677037Andreas Huber err = converter.convert( 40736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan (const uint8_t *)videoFrameBuffer->data(), 408de321c324cc4af88a8ea54d08c63546f73677037Andreas Huber width, height, 409de321c324cc4af88a8ea54d08c63546f73677037Andreas Huber crop_left, crop_top, crop_right, crop_bottom, 410de321c324cc4af88a8ea54d08c63546f73677037Andreas Huber frame->mData, 411de321c324cc4af88a8ea54d08c63546f73677037Andreas Huber frame->mWidth, 412de321c324cc4af88a8ea54d08c63546f73677037Andreas Huber frame->mHeight, 413de321c324cc4af88a8ea54d08c63546f73677037Andreas Huber 0, 0, frame->mWidth - 1, frame->mHeight - 1); 414de321c324cc4af88a8ea54d08c63546f73677037Andreas Huber } else { 41536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan ALOGE("Unable to convert from format 0x%08x to RGB565", srcFormat); 416de321c324cc4af88a8ea54d08c63546f73677037Andreas Huber 417de321c324cc4af88a8ea54d08c63546f73677037Andreas Huber err = ERROR_UNSUPPORTED; 418de321c324cc4af88a8ea54d08c63546f73677037Andreas Huber } 4192a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 42036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan videoFrameBuffer.clear(); 42136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan source->stop(); 42236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan decoder->releaseOutputBuffer(index); 42336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan decoder->release(); 4242a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 425b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber if (err != OK) { 42629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Colorconverter failed to convert frame."); 427b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber 428b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber delete frame; 429b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber frame = NULL; 430b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber } 431b1787e3b95e96cc002377d41518cc183f64b58c4Andreas Huber 4322a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber return frame; 4332a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 4342a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 43516afe2fb439cab6125bb46a07a8078d4ce1c1ea5James DongVideoFrame *StagefrightMetadataRetriever::getFrameAtTime( 43616afe2fb439cab6125bb46a07a8078d4ce1c1ea5James Dong int64_t timeUs, int option) { 4374e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 438a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("getFrameAtTime: %" PRId64 " us option: %d", timeUs, option); 43993e1fb99a0c66784b49b105ce84a23baf054ee9cAndreas Huber 4404e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber if (mExtractor.get() == NULL) { 4413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("no extractor."); 4424e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber return NULL; 4434e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 4444e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 445e7484f36061a60aadadb01143d84964d931aa837Andreas Huber sp<MetaData> fileMeta = mExtractor->getMetaData(); 446e7484f36061a60aadadb01143d84964d931aa837Andreas Huber 447e7484f36061a60aadadb01143d84964d931aa837Andreas Huber if (fileMeta == NULL) { 4483856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("extractor doesn't publish metadata, failed to initialize?"); 449e7484f36061a60aadadb01143d84964d931aa837Andreas Huber return NULL; 450e7484f36061a60aadadb01143d84964d931aa837Andreas Huber } 451e7484f36061a60aadadb01143d84964d931aa837Andreas Huber 4528ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten int32_t drm = 0; 453e7484f36061a60aadadb01143d84964d931aa837Andreas Huber if (fileMeta->findInt32(kKeyIsDRM, &drm) && drm != 0) { 45429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("frame grab not allowed."); 4558ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten return NULL; 4568ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten } 4578ddeebb93cb41e7a8e9fe763afb6c6016b21fa61Glenn Kasten 4584e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber size_t n = mExtractor->countTracks(); 4594e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber size_t i; 4604e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber for (i = 0; i < n; ++i) { 4614e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber sp<MetaData> meta = mExtractor->getTrackMetaData(i); 4624e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 4634e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber const char *mime; 4644e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber CHECK(meta->findCString(kKeyMIMEType, &mime)); 4654e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 4664e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber if (!strncasecmp(mime, "video/", 6)) { 4674e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber break; 4684e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 4694e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 4704e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 4714e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber if (i == n) { 4723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("no video track found."); 4734e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber return NULL; 4744e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 4754e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 4764e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber sp<MetaData> trackMeta = mExtractor->getTrackMetaData( 4774e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber i, MediaExtractor::kIncludeExtensiveMetaData); 4784e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 479b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissen sp<IMediaSource> source = mExtractor->getTrack(i); 4804e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 4814e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber if (source.get() == NULL) { 4823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("unable to instantiate video track."); 4834e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber return NULL; 4844e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 4854e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 486515e855eae78aa495da58356486aaa666cb57fd1James Dong const void *data; 487515e855eae78aa495da58356486aaa666cb57fd1James Dong uint32_t type; 488515e855eae78aa495da58356486aaa666cb57fd1James Dong size_t dataSize; 489e7484f36061a60aadadb01143d84964d931aa837Andreas Huber if (fileMeta->findData(kKeyAlbumArt, &type, &data, &dataSize) 490515e855eae78aa495da58356486aaa666cb57fd1James Dong && mAlbumArt == NULL) { 491f3e80dddd7376aa9deeb27de25e1d50030a2ad98Elliott Hughes mAlbumArt = MediaAlbumArt::fromData(dataSize, data); 492515e855eae78aa495da58356486aaa666cb57fd1James Dong } 493515e855eae78aa495da58356486aaa666cb57fd1James Dong 49436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan const char *mime; 49536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan CHECK(trackMeta->findCString(kKeyMIMEType, &mime)); 4964e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 4976b0795009b8f53ab771e0074b76381977d016f4bLajos Molnar Vector<AString> matchingCodecs; 4986b0795009b8f53ab771e0074b76381977d016f4bLajos Molnar MediaCodecList::findMatchingCodecs( 49936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan mime, 50036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan false, /* encoder */ 5016b0795009b8f53ab771e0074b76381977d016f4bLajos Molnar MediaCodecList::kPreferSoftwareCodecs, 50236dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan &matchingCodecs); 50336dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan 50436dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan for (size_t i = 0; i < matchingCodecs.size(); ++i) { 5056b0795009b8f53ab771e0074b76381977d016f4bLajos Molnar const AString &componentName = matchingCodecs[i]; 50636dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan VideoFrame *frame = 50736dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan extractVideoFrame(componentName, trackMeta, source, timeUs, option); 50836dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan 50936dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan if (frame != NULL) { 51036dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan return frame; 51136dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan } 5126b0795009b8f53ab771e0074b76381977d016f4bLajos Molnar ALOGV("%s failed to extract thumbnail, trying next decoder.", componentName.c_str()); 5134e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber } 5144e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 51536dee23baca299f38c134b18f4deb36862bdd89dPraveen Chavan return NULL; 5164e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber} 5174e202e779a8495091ab189fd88fc295a3e619c61Andreas Huber 5182a4a7d5af053a17586a262a1267ba993e31790f1Andreas HuberMediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() { 5193856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO"); 5202a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 521fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mExtractor == NULL) { 522fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return NULL; 523fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 524fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 525fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!mParsedMetaData) { 526fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber parseMetaData(); 527fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 528fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mParsedMetaData = true; 529fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 530fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 531fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mAlbumArt) { 532f3e80dddd7376aa9deeb27de25e1d50030a2ad98Elliott Hughes return mAlbumArt->clone(); 533fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 534fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 5352a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber return NULL; 5362a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 5372a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 5382a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huberconst char *StagefrightMetadataRetriever::extractMetadata(int keyCode) { 539fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mExtractor == NULL) { 540fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return NULL; 541fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 542fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 543fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!mParsedMetaData) { 544fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber parseMetaData(); 545fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 546fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mParsedMetaData = true; 547fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 548fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 549fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber ssize_t index = mMetaData.indexOfKey(keyCode); 550fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 551fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (index < 0) { 552fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return NULL; 553fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 554fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 555d863eff90f2820e78da763ca5be9f942dc49675eDavid Williams return mMetaData.valueAt(index).string(); 5562a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} 5572a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber 558fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Hubervoid StagefrightMetadataRetriever::parseMetaData() { 559fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber sp<MetaData> meta = mExtractor->getMetaData(); 560fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 561e7484f36061a60aadadb01143d84964d931aa837Andreas Huber if (meta == NULL) { 5623856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("extractor doesn't publish metadata, failed to initialize?"); 563e7484f36061a60aadadb01143d84964d931aa837Andreas Huber return; 564e7484f36061a60aadadb01143d84964d931aa837Andreas Huber } 565e7484f36061a60aadadb01143d84964d931aa837Andreas Huber 566fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber struct Map { 567fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber int from; 568fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber int to; 56934581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen const char *name; 570fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber }; 571fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber static const Map kMap[] = { 57234581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen { kKeyMIMEType, METADATA_KEY_MIMETYPE, NULL }, 57334581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER, "tracknumber" }, 57434581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER, "discnumber" }, 57534581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen { kKeyAlbum, METADATA_KEY_ALBUM, "album" }, 57634581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen { kKeyArtist, METADATA_KEY_ARTIST, "artist" }, 57734581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST, "albumartist" }, 57834581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen { kKeyAuthor, METADATA_KEY_AUTHOR, NULL }, 57934581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen { kKeyComposer, METADATA_KEY_COMPOSER, "composer" }, 58034581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen { kKeyDate, METADATA_KEY_DATE, NULL }, 58134581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen { kKeyGenre, METADATA_KEY_GENRE, "genre" }, 58234581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen { kKeyTitle, METADATA_KEY_TITLE, "title" }, 58334581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen { kKeyYear, METADATA_KEY_YEAR, "year" }, 58434581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen { kKeyWriter, METADATA_KEY_WRITER, "writer" }, 58534581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen { kKeyCompilation, METADATA_KEY_COMPILATION, "compilation" }, 58634581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen { kKeyLocation, METADATA_KEY_LOCATION, NULL }, 587fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber }; 58834581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen 589fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]); 590fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 59134581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen CharacterEncodingDetector *detector = new CharacterEncodingDetector(); 59234581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen 593fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber for (size_t i = 0; i < kNumMapEntries; ++i) { 594fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber const char *value; 595fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (meta->findCString(kMap[i].from, &value)) { 59634581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen if (kMap[i].name) { 59734581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen // add to charset detector 59834581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen detector->addTag(kMap[i].name, value); 59934581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen } else { 60034581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen // directly add to output list 60134581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen mMetaData.add(kMap[i].to, String8(value)); 60234581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen } 60334581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen } 60434581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen } 60534581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen 60634581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen detector->detectAndConvert(); 60734581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen int size = detector->size(); 60834581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen if (size) { 60934581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen for (int i = 0; i < size; i++) { 61034581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen const char *name; 61134581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen const char *value; 61234581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen detector->getTag(i, &name, &value); 61334581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen for (size_t j = 0; j < kNumMapEntries; ++j) { 61434581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen if (kMap[j].name && !strcmp(kMap[j].name, name)) { 61534581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen mMetaData.add(kMap[j].to, String8(value)); 61634581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen } 61734581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen } 618fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 619fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 62034581f44cde67960fbac3ba1f191a2c063ea5145Marco Nelissen delete detector; 621fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 622fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber const void *data; 623fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber uint32_t type; 624fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber size_t dataSize; 625515e855eae78aa495da58356486aaa666cb57fd1James Dong if (meta->findData(kKeyAlbumArt, &type, &data, &dataSize) 626515e855eae78aa495da58356486aaa666cb57fd1James Dong && mAlbumArt == NULL) { 627f3e80dddd7376aa9deeb27de25e1d50030a2ad98Elliott Hughes mAlbumArt = MediaAlbumArt::fromData(dataSize, data); 628fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 629fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 630bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber size_t numTracks = mExtractor->countTracks(); 631bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber 632bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber char tmp[32]; 633377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT sprintf(tmp, "%zu", numTracks); 634bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber 635bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp)); 636bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber 6378cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang float captureFps; 6388cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang if (meta->findFloat(kKeyCaptureFramerate, &captureFps)) { 6398cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang sprintf(tmp, "%f", captureFps); 6408cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang mMetaData.add(METADATA_KEY_CAPTURE_FRAMERATE, String8(tmp)); 6418cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang } 6428cfad968d5ec429b033caff9743f1ef15090be61Chong Zhang 6432256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber bool hasAudio = false; 6442256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber bool hasVideo = false; 6452256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber int32_t videoWidth = -1; 6462256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber int32_t videoHeight = -1; 6472256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber int32_t audioBitrate = -1; 6485a81ad893eada20c32596be53dabe203b99bec3cJames Dong int32_t rotationAngle = -1; 6492256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 650fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // The overall duration is the duration of the longest track. 651fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber int64_t maxDurationUs = 0; 6527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang String8 timedTextLang; 653bd4bc59262df90dc85752684a1d4a92833a535a3Andreas Huber for (size_t i = 0; i < numTracks; ++i) { 654fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i); 655fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 656fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber int64_t durationUs; 657fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (trackMeta->findInt64(kKeyDuration, &durationUs)) { 658fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (durationUs > maxDurationUs) { 659fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber maxDurationUs = durationUs; 660fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 661fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 6622256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 6632256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber const char *mime; 6642256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber if (trackMeta->findCString(kKeyMIMEType, &mime)) { 6652256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber if (!hasAudio && !strncasecmp("audio/", mime, 6)) { 6662256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber hasAudio = true; 6672256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 6682256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) { 6692256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber audioBitrate = -1; 6702256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } 6712256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } else if (!hasVideo && !strncasecmp("video/", mime, 6)) { 6722256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber hasVideo = true; 6732256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 6742256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth)); 6752256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight)); 6765a81ad893eada20c32596be53dabe203b99bec3cJames Dong if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) { 6775a81ad893eada20c32596be53dabe203b99bec3cJames Dong rotationAngle = 0; 6785a81ad893eada20c32596be53dabe203b99bec3cJames Dong } 6797a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) { 6807a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang const char *lang; 68143dcf600b7d6f1fdf0e8db4b9c68dfa11da5878cApurupa Pattapu if (trackMeta->findCString(kKeyMediaLanguage, &lang)) { 68243dcf600b7d6f1fdf0e8db4b9c68dfa11da5878cApurupa Pattapu timedTextLang.append(String8(lang)); 68343dcf600b7d6f1fdf0e8db4b9c68dfa11da5878cApurupa Pattapu timedTextLang.append(String8(":")); 68443dcf600b7d6f1fdf0e8db4b9c68dfa11da5878cApurupa Pattapu } else { 68543dcf600b7d6f1fdf0e8db4b9c68dfa11da5878cApurupa Pattapu ALOGE("No language found for timed text"); 68643dcf600b7d6f1fdf0e8db4b9c68dfa11da5878cApurupa Pattapu } 6872256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } 6882256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } 689fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 690fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 6917a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // To save the language codes for all timed text tracks 6927a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // If multiple text tracks present, the format will look 6937a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // like "eng:chi" 6947a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang if (!timedTextLang.isEmpty()) { 6957a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang mMetaData.add(METADATA_KEY_TIMED_TEXT_LANGUAGES, timedTextLang); 6967a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 6977a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 698fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // The duration value is a string representing the duration in ms. 699377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT sprintf(tmp, "%" PRId64, (maxDurationUs + 500) / 1000); 700fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber mMetaData.add(METADATA_KEY_DURATION, String8(tmp)); 701093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 7022256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber if (hasAudio) { 7032256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber mMetaData.add(METADATA_KEY_HAS_AUDIO, String8("yes")); 7042256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } 7052256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 7062256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber if (hasVideo) { 7072256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber mMetaData.add(METADATA_KEY_HAS_VIDEO, String8("yes")); 7082256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 7092256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber sprintf(tmp, "%d", videoWidth); 7102256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber mMetaData.add(METADATA_KEY_VIDEO_WIDTH, String8(tmp)); 7112256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 7122256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber sprintf(tmp, "%d", videoHeight); 7132256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber mMetaData.add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp)); 7145a81ad893eada20c32596be53dabe203b99bec3cJames Dong 7155a81ad893eada20c32596be53dabe203b99bec3cJames Dong sprintf(tmp, "%d", rotationAngle); 7165a81ad893eada20c32596be53dabe203b99bec3cJames Dong mMetaData.add(METADATA_KEY_VIDEO_ROTATION, String8(tmp)); 7172256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } 7182256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 7192256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber if (numTracks == 1 && hasAudio && audioBitrate >= 0) { 7201d54b3e0ec3d1ef17e75fec6f97be59f29721fffJames Dong sprintf(tmp, "%d", audioBitrate); 7212256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber mMetaData.add(METADATA_KEY_BITRATE, String8(tmp)); 7222256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } else { 7232256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber off64_t sourceSize; 724665df6f7c5b3189f9555ebe14cde3d0d24a5a024Lajos Molnar if (mSource != NULL && mSource->getSize(&sourceSize) == OK) { 7252256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs); 7262256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 727377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT sprintf(tmp, "%" PRId64, avgBitRate); 7282256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber mMetaData.add(METADATA_KEY_BITRATE, String8(tmp)); 7292256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } 7302256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber } 7312256d515e6fa1dd95b8fd0de05b56d8c83af8327Andreas Huber 732093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (numTracks == 1) { 733093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const char *fileMIME; 734093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(meta->findCString(kKeyMIMEType, &fileMIME)); 735093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 736093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strcasecmp(fileMIME, "video/x-matroska")) { 737093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber sp<MetaData> trackMeta = mExtractor->getTrackMetaData(0); 738093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber const char *trackMIME; 739093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber CHECK(trackMeta->findCString(kKeyMIMEType, &trackMIME)); 740093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber 741093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber if (!strncasecmp("audio/", trackMIME, 6)) { 742093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber // The matroska file only contains a single audio track, 743093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber // rewrite its mime type. 744093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber mMetaData.add( 745093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber METADATA_KEY_MIMETYPE, String8("audio/x-matroska")); 746093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 747093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 748093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber } 7490d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang 7500d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang // To check whether the media file is drm-protected 7510d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang if (mExtractor->getDrmFlag()) { 7520d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang mMetaData.add(METADATA_KEY_IS_DRM, String8("1")); 7530d0edfb024f65f7e1097bf1814ae229ce9cb367dGloria Wang } 754fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 755fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 75699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkinsvoid StagefrightMetadataRetriever::clearMetadata() { 75799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins mParsedMetaData = false; 75899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins mMetaData.clear(); 75999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins delete mAlbumArt; 76099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins mAlbumArt = NULL; 76199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 76299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 7632a4a7d5af053a17586a262a1267ba993e31790f1Andreas Huber} // namespace android 764