blob: 42c18770c9f82fb1e8fc3194b782b90a9771dc7f [file] [log] [blame]
Andreas Huber53a76bd2009-10-06 16:20:44 -07001/*
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 "StagefrightMetadataRetriever.h"
23
24#include <media/stagefright/CachingDataSource.h>
25#include <media/stagefright/ColorConverter.h>
26#include <media/stagefright/DataSource.h>
Andreas Huber27366fc2009-11-20 09:32:46 -080027#include <media/stagefright/FileSource.h>
Andreas Huber53a76bd2009-10-06 16:20:44 -070028#include <media/stagefright/HTTPDataSource.h>
29#include <media/stagefright/MediaDebug.h>
30#include <media/stagefright/MediaExtractor.h>
31#include <media/stagefright/MetaData.h>
Andreas Huber53a76bd2009-10-06 16:20:44 -070032#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
Andreas Huber9a12baf2009-10-23 10:22:30 -070051 mExtractor = MediaExtractor::CreateFromURI(uri);
Andreas Huber53a76bd2009-10-06 16:20:44 -070052
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(
Andreas Huber27366fc2009-11-20 09:32:46 -080061 new FileSource(fd, offset, length));
Andreas Huber53a76bd2009-10-06 16:20:44 -070062
63 return OK;
64}
65
66VideoFrame *StagefrightMetadataRetriever::captureFrame() {
67 LOGV("captureFrame");
68
69 if (mExtractor.get() == NULL) {
Andreas Huberad285432009-10-22 09:44:00 -070070 LOGV("no extractor.");
Andreas Huber53a76bd2009-10-06 16:20:44 -070071 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) {
Andreas Huberad285432009-10-22 09:44:00 -070088 LOGV("no video track found.");
Andreas Huber53a76bd2009-10-06 16:20:44 -070089 return NULL;
90 }
91
Andreas Hubere981c332009-10-22 13:49:30 -070092 sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
93 i, MediaExtractor::kIncludeExtensiveMetaData);
94
Andreas Huber53a76bd2009-10-06 16:20:44 -070095 sp<MediaSource> source = mExtractor->getTrack(i);
96
97 if (source.get() == NULL) {
Andreas Huberad285432009-10-22 09:44:00 -070098 LOGV("unable to instantiate video track.");
Andreas Huber53a76bd2009-10-06 16:20:44 -070099 return NULL;
100 }
101
102 sp<MetaData> meta = source->getFormat();
103
104 sp<MediaSource> decoder =
105 OMXCodec::Create(
Andreas Hubere13526a2009-10-22 10:43:34 -0700106 mClient.interface(), meta, false, source,
107 NULL, OMXCodec::kPreferSoftwareCodecs);
Andreas Huber53a76bd2009-10-06 16:20:44 -0700108
109 if (decoder.get() == NULL) {
Andreas Huberad285432009-10-22 09:44:00 -0700110 LOGV("unable to instantiate video decoder.");
Andreas Huber53a76bd2009-10-06 16:20:44 -0700111
112 return NULL;
113 }
114
115 decoder->start();
116
Andreas Huberf68c1682009-10-21 14:01:30 -0700117 // Read one output buffer, ignore format change notifications
118 // and spurious empty buffers.
119
Andreas Hubere981c332009-10-22 13:49:30 -0700120 MediaSource::ReadOptions options;
121 int64_t thumbNailTime;
122 if (trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) {
123 options.setSeekTo(thumbNailTime);
124 }
125
Andreas Huberf68c1682009-10-21 14:01:30 -0700126 MediaBuffer *buffer = NULL;
Andreas Hubercfd55572009-10-09 14:11:28 -0700127 status_t err;
128 do {
Andreas Huberf68c1682009-10-21 14:01:30 -0700129 if (buffer != NULL) {
130 buffer->release();
131 buffer = NULL;
132 }
Andreas Hubere981c332009-10-22 13:49:30 -0700133 err = decoder->read(&buffer, &options);
134 options.clearSeekTo();
Andreas Huberf68c1682009-10-21 14:01:30 -0700135 } while (err == INFO_FORMAT_CHANGED
136 || (buffer != NULL && buffer->range_length() == 0));
Andreas Huber53a76bd2009-10-06 16:20:44 -0700137
138 if (err != OK) {
139 CHECK_EQ(buffer, NULL);
140
Andreas Huberad285432009-10-22 09:44:00 -0700141 LOGV("decoding frame failed.");
Andreas Huber53a76bd2009-10-06 16:20:44 -0700142 decoder->stop();
143
144 return NULL;
145 }
146
Andreas Huberad285432009-10-22 09:44:00 -0700147 LOGV("successfully decoded video frame.");
Andreas Huber53a76bd2009-10-06 16:20:44 -0700148
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