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