StagefrightMetadataRetriever.cpp revision 67e5a4f6f6879d512a859e5dba92e9beec7a2f91
1/*
2**
3** Copyright 2009, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "StagefrightMetadataRetriever"
20#include <utils/Log.h>
21
22#include "include/StagefrightMetadataRetriever.h"
23
24#include <media/stagefright/CachingDataSource.h>
25#include <media/stagefright/ColorConverter.h>
26#include <media/stagefright/DataSource.h>
27#include <media/stagefright/FileSource.h>
28#include <media/stagefright/HTTPDataSource.h>
29#include <media/stagefright/MediaDebug.h>
30#include <media/stagefright/MediaExtractor.h>
31#include <media/stagefright/MetaData.h>
32#include <media/stagefright/OMXCodec.h>
33
34namespace android {
35
36StagefrightMetadataRetriever::StagefrightMetadataRetriever() {
37    LOGV("StagefrightMetadataRetriever()");
38
39    DataSource::RegisterDefaultSniffers();
40    CHECK_EQ(mClient.connect(), OK);
41}
42
43StagefrightMetadataRetriever::~StagefrightMetadataRetriever() {
44    LOGV("~StagefrightMetadataRetriever()");
45    mClient.disconnect();
46}
47
48status_t StagefrightMetadataRetriever::setDataSource(const char *uri) {
49    LOGV("setDataSource(%s)", uri);
50
51    mExtractor = MediaExtractor::CreateFromURI(uri);
52
53    return mExtractor.get() != NULL ? OK : UNKNOWN_ERROR;
54}
55
56status_t StagefrightMetadataRetriever::setDataSource(
57        int fd, int64_t offset, int64_t length) {
58    LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length);
59
60    mExtractor = MediaExtractor::Create(
61            new FileSource(fd, offset, length));
62
63    return OK;
64}
65
66VideoFrame *StagefrightMetadataRetriever::captureFrame() {
67    LOGV("captureFrame");
68
69    if (mExtractor.get() == NULL) {
70        LOGV("no extractor.");
71        return NULL;
72    }
73
74    size_t n = mExtractor->countTracks();
75    size_t i;
76    for (i = 0; i < n; ++i) {
77        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
78
79        const char *mime;
80        CHECK(meta->findCString(kKeyMIMEType, &mime));
81
82        if (!strncasecmp(mime, "video/", 6)) {
83            break;
84        }
85    }
86
87    if (i == n) {
88        LOGV("no video track found.");
89        return NULL;
90    }
91
92    sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
93            i, MediaExtractor::kIncludeExtensiveMetaData);
94
95    sp<MediaSource> source = mExtractor->getTrack(i);
96
97    if (source.get() == NULL) {
98        LOGV("unable to instantiate video track.");
99        return NULL;
100    }
101
102    sp<MetaData> meta = source->getFormat();
103
104    sp<MediaSource> decoder =
105        OMXCodec::Create(
106                mClient.interface(), meta, false, source,
107                NULL, OMXCodec::kPreferSoftwareCodecs);
108
109    if (decoder.get() == NULL) {
110        LOGV("unable to instantiate video decoder.");
111
112        return NULL;
113    }
114
115    decoder->start();
116
117    // Read one output buffer, ignore format change notifications
118    // and spurious empty buffers.
119
120    MediaSource::ReadOptions options;
121    int64_t thumbNailTime;
122    if (trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
123        options.setSeekTo(thumbNailTime);
124    }
125
126    MediaBuffer *buffer = NULL;
127    status_t err;
128    do {
129        if (buffer != NULL) {
130            buffer->release();
131            buffer = NULL;
132        }
133        err = decoder->read(&buffer, &options);
134        options.clearSeekTo();
135    } while (err == INFO_FORMAT_CHANGED
136             || (buffer != NULL && buffer->range_length() == 0));
137
138    if (err != OK) {
139        CHECK_EQ(buffer, NULL);
140
141        LOGV("decoding frame failed.");
142        decoder->stop();
143
144        return NULL;
145    }
146
147    LOGV("successfully decoded video frame.");
148
149    meta = decoder->getFormat();
150
151    int32_t width, height;
152    CHECK(meta->findInt32(kKeyWidth, &width));
153    CHECK(meta->findInt32(kKeyHeight, &height));
154
155    VideoFrame *frame = new VideoFrame;
156    frame->mWidth = width;
157    frame->mHeight = height;
158    frame->mDisplayWidth = width;
159    frame->mDisplayHeight = height;
160    frame->mSize = width * height * 2;
161    frame->mData = new uint8_t[frame->mSize];
162
163    int32_t srcFormat;
164    CHECK(meta->findInt32(kKeyColorFormat, &srcFormat));
165
166    ColorConverter converter(
167            (OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565);
168    CHECK(converter.isValid());
169
170    converter.convert(
171            width, height,
172            (const uint8_t *)buffer->data() + buffer->range_offset(),
173            0,
174            frame->mData, width * 2);
175
176    buffer->release();
177    buffer = NULL;
178
179    decoder->stop();
180
181    return frame;
182}
183
184MediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() {
185    LOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO");
186
187    return NULL;
188}
189
190const char *StagefrightMetadataRetriever::extractMetadata(int keyCode) {
191    LOGV("extractMetadata %d (extractor: %s)",
192         keyCode, mExtractor.get() != NULL ? "YES" : "NO");
193
194    return NULL;
195}
196
197}  // namespace android
198