StagefrightMetadataRetriever.cpp revision 72b8c5ae6a5f97a4fcfc6d23d33159d6ae50179c
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "StagefrightMetadataRetriever" 19#include <utils/Log.h> 20 21#include "include/StagefrightMetadataRetriever.h" 22 23#include <media/stagefright/CachingDataSource.h> 24#include <media/stagefright/ColorConverter.h> 25#include <media/stagefright/DataSource.h> 26#include <media/stagefright/FileSource.h> 27#include <media/stagefright/HTTPDataSource.h> 28#include <media/stagefright/MediaDebug.h> 29#include <media/stagefright/MediaExtractor.h> 30#include <media/stagefright/MetaData.h> 31#include <media/stagefright/OMXCodec.h> 32 33namespace android { 34 35StagefrightMetadataRetriever::StagefrightMetadataRetriever() 36 : mParsedMetaData(false), 37 mAlbumArt(NULL) { 38 LOGV("StagefrightMetadataRetriever()"); 39 40 DataSource::RegisterDefaultSniffers(); 41 CHECK_EQ(mClient.connect(), OK); 42} 43 44StagefrightMetadataRetriever::~StagefrightMetadataRetriever() { 45 LOGV("~StagefrightMetadataRetriever()"); 46 47 delete mAlbumArt; 48 mAlbumArt = NULL; 49 50 mClient.disconnect(); 51} 52 53status_t StagefrightMetadataRetriever::setDataSource(const char *uri) { 54 LOGV("setDataSource(%s)", uri); 55 56 mParsedMetaData = false; 57 mMetaData.clear(); 58 delete mAlbumArt; 59 mAlbumArt = NULL; 60 61 mSource = DataSource::CreateFromURI(uri); 62 63 if (mSource == NULL) { 64 return UNKNOWN_ERROR; 65 } 66 67 mExtractor = MediaExtractor::Create(mSource); 68 69 if (mExtractor == NULL) { 70 mSource.clear(); 71 72 return UNKNOWN_ERROR; 73 } 74 75 return OK; 76} 77 78// Warning caller retains ownership of the filedescriptor! Dup it if necessary. 79status_t StagefrightMetadataRetriever::setDataSource( 80 int fd, int64_t offset, int64_t length) { 81 fd = dup(fd); 82 83 LOGV("setDataSource(%d, %lld, %lld)", fd, offset, length); 84 85 mParsedMetaData = false; 86 mMetaData.clear(); 87 delete mAlbumArt; 88 mAlbumArt = NULL; 89 90 mSource = new FileSource(fd, offset, length); 91 92 status_t err; 93 if ((err = mSource->initCheck()) != OK) { 94 mSource.clear(); 95 96 return err; 97 } 98 99 mExtractor = MediaExtractor::Create(mSource); 100 101 if (mExtractor == NULL) { 102 mSource.clear(); 103 104 return UNKNOWN_ERROR; 105 } 106 107 return OK; 108} 109 110static VideoFrame *extractVideoFrameWithCodecFlags( 111 OMXClient *client, 112 const sp<MetaData> &trackMeta, 113 const sp<MediaSource> &source, uint32_t flags) { 114 sp<MediaSource> decoder = 115 OMXCodec::Create( 116 client->interface(), source->getFormat(), false, source, 117 NULL, flags); 118 119 if (decoder.get() == NULL) { 120 LOGV("unable to instantiate video decoder."); 121 122 return NULL; 123 } 124 125 decoder->start(); 126 127 // Read one output buffer, ignore format change notifications 128 // and spurious empty buffers. 129 130 MediaSource::ReadOptions options; 131 int64_t thumbNailTime; 132 if (trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)) { 133 options.setSeekTo(thumbNailTime); 134 } else { 135 thumbNailTime = -1; 136 } 137 138 MediaBuffer *buffer = NULL; 139 status_t err; 140 do { 141 if (buffer != NULL) { 142 buffer->release(); 143 buffer = NULL; 144 } 145 err = decoder->read(&buffer, &options); 146 options.clearSeekTo(); 147 } while (err == INFO_FORMAT_CHANGED 148 || (buffer != NULL && buffer->range_length() == 0)); 149 150 if (err != OK) { 151 CHECK_EQ(buffer, NULL); 152 153 LOGV("decoding frame failed."); 154 decoder->stop(); 155 156 return NULL; 157 } 158 159 LOGV("successfully decoded video frame."); 160 161 int64_t timeUs; 162 CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs)); 163 if (thumbNailTime >= 0) { 164 if (timeUs != thumbNailTime) { 165 const char *mime; 166 CHECK(trackMeta->findCString(kKeyMIMEType, &mime)); 167 168 LOGV("thumbNailTime = %lld us, timeUs = %lld us, mime = %s", 169 thumbNailTime, timeUs, mime); 170 } 171 } 172 173 sp<MetaData> meta = decoder->getFormat(); 174 175 int32_t width, height; 176 CHECK(meta->findInt32(kKeyWidth, &width)); 177 CHECK(meta->findInt32(kKeyHeight, &height)); 178 179 VideoFrame *frame = new VideoFrame; 180 frame->mWidth = width; 181 frame->mHeight = height; 182 frame->mDisplayWidth = width; 183 frame->mDisplayHeight = height; 184 frame->mSize = width * height * 2; 185 frame->mData = new uint8_t[frame->mSize]; 186 187 int32_t srcFormat; 188 CHECK(meta->findInt32(kKeyColorFormat, &srcFormat)); 189 190 ColorConverter converter( 191 (OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565); 192 CHECK(converter.isValid()); 193 194 converter.convert( 195 width, height, 196 (const uint8_t *)buffer->data() + buffer->range_offset(), 197 0, 198 frame->mData, width * 2); 199 200 buffer->release(); 201 buffer = NULL; 202 203 decoder->stop(); 204 205 return frame; 206} 207 208VideoFrame *StagefrightMetadataRetriever::captureFrame() { 209 LOGV("captureFrame"); 210 211 if (mExtractor.get() == NULL) { 212 LOGV("no extractor."); 213 return NULL; 214 } 215 216 size_t n = mExtractor->countTracks(); 217 size_t i; 218 for (i = 0; i < n; ++i) { 219 sp<MetaData> meta = mExtractor->getTrackMetaData(i); 220 221 const char *mime; 222 CHECK(meta->findCString(kKeyMIMEType, &mime)); 223 224 if (!strncasecmp(mime, "video/", 6)) { 225 break; 226 } 227 } 228 229 if (i == n) { 230 LOGV("no video track found."); 231 return NULL; 232 } 233 234 sp<MetaData> trackMeta = mExtractor->getTrackMetaData( 235 i, MediaExtractor::kIncludeExtensiveMetaData); 236 237 sp<MediaSource> source = mExtractor->getTrack(i); 238 239 if (source.get() == NULL) { 240 LOGV("unable to instantiate video track."); 241 return NULL; 242 } 243 244 VideoFrame *frame = 245 extractVideoFrameWithCodecFlags( 246 &mClient, trackMeta, source, OMXCodec::kPreferSoftwareCodecs); 247 248 if (frame == NULL) { 249 LOGV("Software decoder failed to extract thumbnail, " 250 "trying hardware decoder."); 251 252 frame = extractVideoFrameWithCodecFlags(&mClient, trackMeta, source, 0); 253 } 254 255 return frame; 256} 257 258MediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() { 259 LOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO"); 260 261 if (mExtractor == NULL) { 262 return NULL; 263 } 264 265 if (!mParsedMetaData) { 266 parseMetaData(); 267 268 mParsedMetaData = true; 269 } 270 271 if (mAlbumArt) { 272 return new MediaAlbumArt(*mAlbumArt); 273 } 274 275 return NULL; 276} 277 278const char *StagefrightMetadataRetriever::extractMetadata(int keyCode) { 279 LOGV("extractMetadata %d", keyCode); 280 281 if (mExtractor == NULL) { 282 return NULL; 283 } 284 285 if (!mParsedMetaData) { 286 parseMetaData(); 287 288 mParsedMetaData = true; 289 } 290 291 ssize_t index = mMetaData.indexOfKey(keyCode); 292 293 if (index < 0) { 294 return NULL; 295 } 296 297 return strdup(mMetaData.valueAt(index).string()); 298} 299 300void StagefrightMetadataRetriever::parseMetaData() { 301 sp<MetaData> meta = mExtractor->getMetaData(); 302 303 struct Map { 304 int from; 305 int to; 306 }; 307 static const Map kMap[] = { 308 { kKeyMIMEType, METADATA_KEY_MIMETYPE }, 309 { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER }, 310 { kKeyAlbum, METADATA_KEY_ALBUM }, 311 { kKeyArtist, METADATA_KEY_ARTIST }, 312 { kKeyAuthor, METADATA_KEY_AUTHOR }, 313 { kKeyComposer, METADATA_KEY_COMPOSER }, 314 { kKeyDate, METADATA_KEY_DATE }, 315 { kKeyGenre, METADATA_KEY_GENRE }, 316 { kKeyTitle, METADATA_KEY_TITLE }, 317 { kKeyYear, METADATA_KEY_YEAR }, 318 { kKeyWriter, METADATA_KEY_WRITER }, 319 }; 320 static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]); 321 322 for (size_t i = 0; i < kNumMapEntries; ++i) { 323 const char *value; 324 if (meta->findCString(kMap[i].from, &value)) { 325 mMetaData.add(kMap[i].to, String8(value)); 326 } 327 } 328 329 const void *data; 330 uint32_t type; 331 size_t dataSize; 332 if (meta->findData(kKeyAlbumArt, &type, &data, &dataSize)) { 333 mAlbumArt = new MediaAlbumArt; 334 mAlbumArt->mSize = dataSize; 335 mAlbumArt->mData = new uint8_t[dataSize]; 336 memcpy(mAlbumArt->mData, data, dataSize); 337 } 338 339 size_t numTracks = mExtractor->countTracks(); 340 341 char tmp[32]; 342 sprintf(tmp, "%d", numTracks); 343 344 mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp)); 345 346 // The overall duration is the duration of the longest track. 347 int64_t maxDurationUs = 0; 348 for (size_t i = 0; i < numTracks; ++i) { 349 sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i); 350 351 int64_t durationUs; 352 if (trackMeta->findInt64(kKeyDuration, &durationUs)) { 353 if (durationUs > maxDurationUs) { 354 maxDurationUs = durationUs; 355 } 356 } 357 } 358 359 // The duration value is a string representing the duration in ms. 360 sprintf(tmp, "%lld", (maxDurationUs + 500) / 1000); 361 mMetaData.add(METADATA_KEY_DURATION, String8(tmp)); 362} 363 364 365} // namespace android 366