StagefrightMetadataRetriever.cpp revision 665df6f7c5b3189f9555ebe14cde3d0d24a5a024
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
20#include <inttypes.h>
21
22#include <utils/Log.h>
23#include <gui/Surface.h>
24
25#include "include/StagefrightMetadataRetriever.h"
26
27#include <media/ICrypto.h>
28#include <media/IMediaHTTPService.h>
29
30#include <media/stagefright/foundation/ABuffer.h>
31#include <media/stagefright/foundation/ADebug.h>
32#include <media/stagefright/foundation/AMessage.h>
33#include <media/stagefright/ColorConverter.h>
34#include <media/stagefright/DataSource.h>
35#include <media/stagefright/FileSource.h>
36#include <media/stagefright/MediaBuffer.h>
37#include <media/stagefright/MediaCodec.h>
38#include <media/stagefright/MediaCodecList.h>
39#include <media/stagefright/MediaDefs.h>
40#include <media/stagefright/MediaErrors.h>
41#include <media/stagefright/MediaExtractor.h>
42#include <media/stagefright/MediaSource.h>
43#include <media/stagefright/MetaData.h>
44#include <media/stagefright/Utils.h>
45
46#include <CharacterEncodingDetector.h>
47
48namespace android {
49
50static const int64_t kBufferTimeOutUs = 30000ll; // 30 msec
51static const size_t kRetryCount = 20; // must be >0
52
53StagefrightMetadataRetriever::StagefrightMetadataRetriever()
54    : mParsedMetaData(false),
55      mAlbumArt(NULL) {
56    ALOGV("StagefrightMetadataRetriever()");
57
58    DataSource::RegisterDefaultSniffers();
59}
60
61StagefrightMetadataRetriever::~StagefrightMetadataRetriever() {
62    ALOGV("~StagefrightMetadataRetriever()");
63    clearMetadata();
64    if (mSource != NULL) {
65        mSource->close();
66    }
67}
68
69status_t StagefrightMetadataRetriever::setDataSource(
70        const sp<IMediaHTTPService> &httpService,
71        const char *uri,
72        const KeyedVector<String8, String8> *headers) {
73    ALOGV("setDataSource(%s)", uri);
74
75    clearMetadata();
76    mSource = DataSource::CreateFromURI(httpService, uri, headers);
77
78    if (mSource == NULL) {
79        ALOGE("Unable to create data source for '%s'.", uri);
80        return UNKNOWN_ERROR;
81    }
82
83    mExtractor = MediaExtractor::Create(mSource);
84
85    if (mExtractor == NULL) {
86        ALOGE("Unable to instantiate an extractor for '%s'.", uri);
87
88        mSource.clear();
89
90        return UNKNOWN_ERROR;
91    }
92
93    return OK;
94}
95
96// Warning caller retains ownership of the filedescriptor! Dup it if necessary.
97status_t StagefrightMetadataRetriever::setDataSource(
98        int fd, int64_t offset, int64_t length) {
99    fd = dup(fd);
100
101    ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
102
103    clearMetadata();
104    mSource = new FileSource(fd, offset, length);
105
106    status_t err;
107    if ((err = mSource->initCheck()) != OK) {
108        mSource.clear();
109
110        return err;
111    }
112
113    mExtractor = MediaExtractor::Create(mSource);
114
115    if (mExtractor == NULL) {
116        mSource.clear();
117
118        return UNKNOWN_ERROR;
119    }
120
121    return OK;
122}
123
124status_t StagefrightMetadataRetriever::setDataSource(
125        const sp<DataSource>& source) {
126    ALOGV("setDataSource(DataSource)");
127
128    clearMetadata();
129    mSource = source;
130    mExtractor = MediaExtractor::Create(mSource);
131
132    if (mExtractor == NULL) {
133        ALOGE("Failed to instantiate a MediaExtractor.");
134        mSource.clear();
135        return UNKNOWN_ERROR;
136    }
137
138    return OK;
139}
140
141static VideoFrame *extractVideoFrame(
142        const AString &componentName,
143        const sp<MetaData> &trackMeta,
144        const sp<IMediaSource> &source,
145        int64_t frameTimeUs,
146        int seekMode) {
147
148    sp<MetaData> format = source->getFormat();
149
150    sp<AMessage> videoFormat;
151    if (convertMetaDataToMessage(trackMeta, &videoFormat) != OK) {
152        ALOGE("b/23680780");
153        ALOGW("Failed to convert meta data to message");
154        return NULL;
155    }
156
157    // TODO: Use Flexible color instead
158    videoFormat->setInt32("color-format", OMX_COLOR_FormatYUV420Planar);
159
160    status_t err;
161    sp<ALooper> looper = new ALooper;
162    looper->start();
163    sp<MediaCodec> decoder = MediaCodec::CreateByComponentName(
164            looper, componentName, &err);
165
166    if (decoder.get() == NULL || err != OK) {
167        ALOGW("Failed to instantiate decoder [%s]", componentName.c_str());
168        return NULL;
169    }
170
171    err = decoder->configure(videoFormat, NULL /* surface */, NULL /* crypto */, 0 /* flags */);
172    if (err != OK) {
173        ALOGW("configure returned error %d (%s)", err, asString(err));
174        decoder->release();
175        return NULL;
176    }
177
178    err = decoder->start();
179    if (err != OK) {
180        ALOGW("start returned error %d (%s)", err, asString(err));
181        decoder->release();
182        return NULL;
183    }
184
185    MediaSource::ReadOptions options;
186    if (seekMode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC ||
187        seekMode > MediaSource::ReadOptions::SEEK_CLOSEST) {
188
189        ALOGE("Unknown seek mode: %d", seekMode);
190        decoder->release();
191        return NULL;
192    }
193
194    MediaSource::ReadOptions::SeekMode mode =
195            static_cast<MediaSource::ReadOptions::SeekMode>(seekMode);
196
197    int64_t thumbNailTime;
198    if (frameTimeUs < 0) {
199        if (!trackMeta->findInt64(kKeyThumbnailTime, &thumbNailTime)
200                || thumbNailTime < 0) {
201            thumbNailTime = 0;
202        }
203        options.setSeekTo(thumbNailTime, mode);
204    } else {
205        thumbNailTime = -1;
206        options.setSeekTo(frameTimeUs, mode);
207    }
208
209    err = source->start();
210    if (err != OK) {
211        ALOGW("source failed to start: %d (%s)", err, asString(err));
212        decoder->release();
213        return NULL;
214    }
215
216    Vector<sp<ABuffer> > inputBuffers;
217    err = decoder->getInputBuffers(&inputBuffers);
218    if (err != OK) {
219        ALOGW("failed to get input buffers: %d (%s)", err, asString(err));
220        decoder->release();
221        source->stop();
222        return NULL;
223    }
224
225    Vector<sp<ABuffer> > outputBuffers;
226    err = decoder->getOutputBuffers(&outputBuffers);
227    if (err != OK) {
228        ALOGW("failed to get output buffers: %d (%s)", err, asString(err));
229        decoder->release();
230        source->stop();
231        return NULL;
232    }
233
234    sp<AMessage> outputFormat = NULL;
235    bool haveMoreInputs = true;
236    size_t index, offset, size;
237    int64_t timeUs;
238    size_t retriesLeft = kRetryCount;
239    bool done = false;
240
241    do {
242        size_t inputIndex = -1;
243        int64_t ptsUs = 0ll;
244        uint32_t flags = 0;
245        sp<ABuffer> codecBuffer = NULL;
246
247        while (haveMoreInputs) {
248            err = decoder->dequeueInputBuffer(&inputIndex, kBufferTimeOutUs);
249            if (err != OK) {
250                ALOGW("Timed out waiting for input");
251                if (retriesLeft) {
252                    err = OK;
253                }
254                break;
255            }
256            codecBuffer = inputBuffers[inputIndex];
257
258            MediaBuffer *mediaBuffer = NULL;
259
260            err = source->read(&mediaBuffer, &options);
261            options.clearSeekTo();
262            if (err != OK) {
263                ALOGW("Input Error or EOS");
264                haveMoreInputs = false;
265                break;
266            }
267
268            if (mediaBuffer->range_length() > codecBuffer->capacity()) {
269                ALOGE("buffer size (%zu) too large for codec input size (%zu)",
270                        mediaBuffer->range_length(), codecBuffer->capacity());
271                err = BAD_VALUE;
272            } else {
273                codecBuffer->setRange(0, mediaBuffer->range_length());
274
275                CHECK(mediaBuffer->meta_data()->findInt64(kKeyTime, &ptsUs));
276                memcpy(codecBuffer->data(),
277                        (const uint8_t*)mediaBuffer->data() + mediaBuffer->range_offset(),
278                        mediaBuffer->range_length());
279            }
280
281            mediaBuffer->release();
282            break;
283        }
284
285        if (err == OK && inputIndex < inputBuffers.size()) {
286            ALOGV("QueueInput: size=%zu ts=%" PRId64 " us flags=%x",
287                    codecBuffer->size(), ptsUs, flags);
288            err = decoder->queueInputBuffer(
289                    inputIndex,
290                    codecBuffer->offset(),
291                    codecBuffer->size(),
292                    ptsUs,
293                    flags);
294
295            // we don't expect an output from codec config buffer
296            if (flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) {
297                continue;
298            }
299        }
300
301        while (err == OK) {
302            // wait for a decoded buffer
303            err = decoder->dequeueOutputBuffer(
304                    &index,
305                    &offset,
306                    &size,
307                    &timeUs,
308                    &flags,
309                    kBufferTimeOutUs);
310
311            if (err == INFO_FORMAT_CHANGED) {
312                ALOGV("Received format change");
313                err = decoder->getOutputFormat(&outputFormat);
314            } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
315                ALOGV("Output buffers changed");
316                err = decoder->getOutputBuffers(&outputBuffers);
317            } else {
318                if (err == -EAGAIN /* INFO_TRY_AGAIN_LATER */ && --retriesLeft > 0) {
319                    ALOGV("Timed-out waiting for output.. retries left = %zu", retriesLeft);
320                    err = OK;
321                } else if (err == OK) {
322                    ALOGV("Received an output buffer");
323                    done = true;
324                } else {
325                    ALOGW("Received error %d (%s) instead of output", err, asString(err));
326                    done = true;
327                }
328                break;
329            }
330        }
331    } while (err == OK && !done);
332
333    if (err != OK || size <= 0 || outputFormat == NULL) {
334        ALOGE("Failed to decode thumbnail frame");
335        source->stop();
336        decoder->release();
337        return NULL;
338    }
339
340    ALOGV("successfully decoded video frame.");
341    sp<ABuffer> videoFrameBuffer = outputBuffers.itemAt(index);
342
343    if (thumbNailTime >= 0) {
344        if (timeUs != thumbNailTime) {
345            AString mime;
346            CHECK(outputFormat->findString("mime", &mime));
347
348            ALOGV("thumbNailTime = %lld us, timeUs = %lld us, mime = %s",
349                    (long long)thumbNailTime, (long long)timeUs, mime.c_str());
350        }
351    }
352
353    int32_t width, height;
354    CHECK(outputFormat->findInt32("width", &width));
355    CHECK(outputFormat->findInt32("height", &height));
356
357    int32_t crop_left, crop_top, crop_right, crop_bottom;
358    if (!outputFormat->findRect("crop", &crop_left, &crop_top, &crop_right, &crop_bottom)) {
359        crop_left = crop_top = 0;
360        crop_right = width - 1;
361        crop_bottom = height - 1;
362    }
363
364    int32_t rotationAngle;
365    if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) {
366        rotationAngle = 0;  // By default, no rotation
367    }
368
369    VideoFrame *frame = new VideoFrame;
370    frame->mWidth = crop_right - crop_left + 1;
371    frame->mHeight = crop_bottom - crop_top + 1;
372    frame->mDisplayWidth = frame->mWidth;
373    frame->mDisplayHeight = frame->mHeight;
374    frame->mSize = frame->mWidth * frame->mHeight * 2;
375    frame->mData = new uint8_t[frame->mSize];
376    frame->mRotationAngle = rotationAngle;
377
378    int32_t sarWidth, sarHeight;
379    if (trackMeta->findInt32(kKeySARWidth, &sarWidth)
380            && trackMeta->findInt32(kKeySARHeight, &sarHeight)
381            && sarHeight != 0) {
382        frame->mDisplayWidth = (frame->mDisplayWidth * sarWidth) / sarHeight;
383    }
384
385    int32_t srcFormat;
386    CHECK(outputFormat->findInt32("color-format", &srcFormat));
387
388    ColorConverter converter((OMX_COLOR_FORMATTYPE)srcFormat, OMX_COLOR_Format16bitRGB565);
389
390    if (converter.isValid()) {
391        err = converter.convert(
392                (const uint8_t *)videoFrameBuffer->data(),
393                width, height,
394                crop_left, crop_top, crop_right, crop_bottom,
395                frame->mData,
396                frame->mWidth,
397                frame->mHeight,
398                0, 0, frame->mWidth - 1, frame->mHeight - 1);
399    } else {
400        ALOGE("Unable to convert from format 0x%08x to RGB565", srcFormat);
401
402        err = ERROR_UNSUPPORTED;
403    }
404
405    videoFrameBuffer.clear();
406    source->stop();
407    decoder->releaseOutputBuffer(index);
408    decoder->release();
409
410    if (err != OK) {
411        ALOGE("Colorconverter failed to convert frame.");
412
413        delete frame;
414        frame = NULL;
415    }
416
417    return frame;
418}
419
420VideoFrame *StagefrightMetadataRetriever::getFrameAtTime(
421        int64_t timeUs, int option) {
422
423    ALOGV("getFrameAtTime: %" PRId64 " us option: %d", timeUs, option);
424
425    if (mExtractor.get() == NULL) {
426        ALOGV("no extractor.");
427        return NULL;
428    }
429
430    sp<MetaData> fileMeta = mExtractor->getMetaData();
431
432    if (fileMeta == NULL) {
433        ALOGV("extractor doesn't publish metadata, failed to initialize?");
434        return NULL;
435    }
436
437    int32_t drm = 0;
438    if (fileMeta->findInt32(kKeyIsDRM, &drm) && drm != 0) {
439        ALOGE("frame grab not allowed.");
440        return NULL;
441    }
442
443    size_t n = mExtractor->countTracks();
444    size_t i;
445    for (i = 0; i < n; ++i) {
446        sp<MetaData> meta = mExtractor->getTrackMetaData(i);
447
448        const char *mime;
449        CHECK(meta->findCString(kKeyMIMEType, &mime));
450
451        if (!strncasecmp(mime, "video/", 6)) {
452            break;
453        }
454    }
455
456    if (i == n) {
457        ALOGV("no video track found.");
458        return NULL;
459    }
460
461    sp<MetaData> trackMeta = mExtractor->getTrackMetaData(
462            i, MediaExtractor::kIncludeExtensiveMetaData);
463
464    sp<IMediaSource> source = mExtractor->getTrack(i);
465
466    if (source.get() == NULL) {
467        ALOGV("unable to instantiate video track.");
468        return NULL;
469    }
470
471    const void *data;
472    uint32_t type;
473    size_t dataSize;
474    if (fileMeta->findData(kKeyAlbumArt, &type, &data, &dataSize)
475            && mAlbumArt == NULL) {
476        mAlbumArt = MediaAlbumArt::fromData(dataSize, data);
477    }
478
479    const char *mime;
480    CHECK(trackMeta->findCString(kKeyMIMEType, &mime));
481
482    Vector<AString> matchingCodecs;
483    MediaCodecList::findMatchingCodecs(
484            mime,
485            false, /* encoder */
486            MediaCodecList::kPreferSoftwareCodecs,
487            &matchingCodecs);
488
489    for (size_t i = 0; i < matchingCodecs.size(); ++i) {
490        const AString &componentName = matchingCodecs[i];
491        VideoFrame *frame =
492            extractVideoFrame(componentName, trackMeta, source, timeUs, option);
493
494        if (frame != NULL) {
495            return frame;
496        }
497        ALOGV("%s failed to extract thumbnail, trying next decoder.", componentName.c_str());
498    }
499
500    return NULL;
501}
502
503MediaAlbumArt *StagefrightMetadataRetriever::extractAlbumArt() {
504    ALOGV("extractAlbumArt (extractor: %s)", mExtractor.get() != NULL ? "YES" : "NO");
505
506    if (mExtractor == NULL) {
507        return NULL;
508    }
509
510    if (!mParsedMetaData) {
511        parseMetaData();
512
513        mParsedMetaData = true;
514    }
515
516    if (mAlbumArt) {
517        return mAlbumArt->clone();
518    }
519
520    return NULL;
521}
522
523const char *StagefrightMetadataRetriever::extractMetadata(int keyCode) {
524    if (mExtractor == NULL) {
525        return NULL;
526    }
527
528    if (!mParsedMetaData) {
529        parseMetaData();
530
531        mParsedMetaData = true;
532    }
533
534    ssize_t index = mMetaData.indexOfKey(keyCode);
535
536    if (index < 0) {
537        return NULL;
538    }
539
540    return mMetaData.valueAt(index).string();
541}
542
543void StagefrightMetadataRetriever::parseMetaData() {
544    sp<MetaData> meta = mExtractor->getMetaData();
545
546    if (meta == NULL) {
547        ALOGV("extractor doesn't publish metadata, failed to initialize?");
548        return;
549    }
550
551    struct Map {
552        int from;
553        int to;
554        const char *name;
555    };
556    static const Map kMap[] = {
557        { kKeyMIMEType, METADATA_KEY_MIMETYPE, NULL },
558        { kKeyCDTrackNumber, METADATA_KEY_CD_TRACK_NUMBER, "tracknumber" },
559        { kKeyDiscNumber, METADATA_KEY_DISC_NUMBER, "discnumber" },
560        { kKeyAlbum, METADATA_KEY_ALBUM, "album" },
561        { kKeyArtist, METADATA_KEY_ARTIST, "artist" },
562        { kKeyAlbumArtist, METADATA_KEY_ALBUMARTIST, "albumartist" },
563        { kKeyAuthor, METADATA_KEY_AUTHOR, NULL },
564        { kKeyComposer, METADATA_KEY_COMPOSER, "composer" },
565        { kKeyDate, METADATA_KEY_DATE, NULL },
566        { kKeyGenre, METADATA_KEY_GENRE, "genre" },
567        { kKeyTitle, METADATA_KEY_TITLE, "title" },
568        { kKeyYear, METADATA_KEY_YEAR, "year" },
569        { kKeyWriter, METADATA_KEY_WRITER, "writer" },
570        { kKeyCompilation, METADATA_KEY_COMPILATION, "compilation" },
571        { kKeyLocation, METADATA_KEY_LOCATION, NULL },
572    };
573
574    static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
575
576    CharacterEncodingDetector *detector = new CharacterEncodingDetector();
577
578    for (size_t i = 0; i < kNumMapEntries; ++i) {
579        const char *value;
580        if (meta->findCString(kMap[i].from, &value)) {
581            if (kMap[i].name) {
582                // add to charset detector
583                detector->addTag(kMap[i].name, value);
584            } else {
585                // directly add to output list
586                mMetaData.add(kMap[i].to, String8(value));
587            }
588        }
589    }
590
591    detector->detectAndConvert();
592    int size = detector->size();
593    if (size) {
594        for (int i = 0; i < size; i++) {
595            const char *name;
596            const char *value;
597            detector->getTag(i, &name, &value);
598            for (size_t j = 0; j < kNumMapEntries; ++j) {
599                if (kMap[j].name && !strcmp(kMap[j].name, name)) {
600                    mMetaData.add(kMap[j].to, String8(value));
601                }
602            }
603        }
604    }
605    delete detector;
606
607    const void *data;
608    uint32_t type;
609    size_t dataSize;
610    if (meta->findData(kKeyAlbumArt, &type, &data, &dataSize)
611            && mAlbumArt == NULL) {
612        mAlbumArt = MediaAlbumArt::fromData(dataSize, data);
613    }
614
615    size_t numTracks = mExtractor->countTracks();
616
617    char tmp[32];
618    sprintf(tmp, "%zu", numTracks);
619
620    mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp));
621
622    float captureFps;
623    if (meta->findFloat(kKeyCaptureFramerate, &captureFps)) {
624        sprintf(tmp, "%f", captureFps);
625        mMetaData.add(METADATA_KEY_CAPTURE_FRAMERATE, String8(tmp));
626    }
627
628    bool hasAudio = false;
629    bool hasVideo = false;
630    int32_t videoWidth = -1;
631    int32_t videoHeight = -1;
632    int32_t audioBitrate = -1;
633    int32_t rotationAngle = -1;
634
635    // The overall duration is the duration of the longest track.
636    int64_t maxDurationUs = 0;
637    String8 timedTextLang;
638    for (size_t i = 0; i < numTracks; ++i) {
639        sp<MetaData> trackMeta = mExtractor->getTrackMetaData(i);
640
641        int64_t durationUs;
642        if (trackMeta->findInt64(kKeyDuration, &durationUs)) {
643            if (durationUs > maxDurationUs) {
644                maxDurationUs = durationUs;
645            }
646        }
647
648        const char *mime;
649        if (trackMeta->findCString(kKeyMIMEType, &mime)) {
650            if (!hasAudio && !strncasecmp("audio/", mime, 6)) {
651                hasAudio = true;
652
653                if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) {
654                    audioBitrate = -1;
655                }
656            } else if (!hasVideo && !strncasecmp("video/", mime, 6)) {
657                hasVideo = true;
658
659                CHECK(trackMeta->findInt32(kKeyWidth, &videoWidth));
660                CHECK(trackMeta->findInt32(kKeyHeight, &videoHeight));
661                if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) {
662                    rotationAngle = 0;
663                }
664            } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
665                const char *lang;
666                if (trackMeta->findCString(kKeyMediaLanguage, &lang)) {
667                    timedTextLang.append(String8(lang));
668                    timedTextLang.append(String8(":"));
669                } else {
670                    ALOGE("No language found for timed text");
671                }
672            }
673        }
674    }
675
676    // To save the language codes for all timed text tracks
677    // If multiple text tracks present, the format will look
678    // like "eng:chi"
679    if (!timedTextLang.isEmpty()) {
680        mMetaData.add(METADATA_KEY_TIMED_TEXT_LANGUAGES, timedTextLang);
681    }
682
683    // The duration value is a string representing the duration in ms.
684    sprintf(tmp, "%" PRId64, (maxDurationUs + 500) / 1000);
685    mMetaData.add(METADATA_KEY_DURATION, String8(tmp));
686
687    if (hasAudio) {
688        mMetaData.add(METADATA_KEY_HAS_AUDIO, String8("yes"));
689    }
690
691    if (hasVideo) {
692        mMetaData.add(METADATA_KEY_HAS_VIDEO, String8("yes"));
693
694        sprintf(tmp, "%d", videoWidth);
695        mMetaData.add(METADATA_KEY_VIDEO_WIDTH, String8(tmp));
696
697        sprintf(tmp, "%d", videoHeight);
698        mMetaData.add(METADATA_KEY_VIDEO_HEIGHT, String8(tmp));
699
700        sprintf(tmp, "%d", rotationAngle);
701        mMetaData.add(METADATA_KEY_VIDEO_ROTATION, String8(tmp));
702    }
703
704    if (numTracks == 1 && hasAudio && audioBitrate >= 0) {
705        sprintf(tmp, "%d", audioBitrate);
706        mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
707    } else {
708        off64_t sourceSize;
709        if (mSource != NULL && mSource->getSize(&sourceSize) == OK) {
710            int64_t avgBitRate = (int64_t)(sourceSize * 8E6 / maxDurationUs);
711
712            sprintf(tmp, "%" PRId64, avgBitRate);
713            mMetaData.add(METADATA_KEY_BITRATE, String8(tmp));
714        }
715    }
716
717    if (numTracks == 1) {
718        const char *fileMIME;
719        CHECK(meta->findCString(kKeyMIMEType, &fileMIME));
720
721        if (!strcasecmp(fileMIME, "video/x-matroska")) {
722            sp<MetaData> trackMeta = mExtractor->getTrackMetaData(0);
723            const char *trackMIME;
724            CHECK(trackMeta->findCString(kKeyMIMEType, &trackMIME));
725
726            if (!strncasecmp("audio/", trackMIME, 6)) {
727                // The matroska file only contains a single audio track,
728                // rewrite its mime type.
729                mMetaData.add(
730                        METADATA_KEY_MIMETYPE, String8("audio/x-matroska"));
731            }
732        }
733    }
734
735    // To check whether the media file is drm-protected
736    if (mExtractor->getDrmFlag()) {
737        mMetaData.add(METADATA_KEY_IS_DRM, String8("1"));
738    }
739}
740
741void StagefrightMetadataRetriever::clearMetadata() {
742    mParsedMetaData = false;
743    mMetaData.clear();
744    delete mAlbumArt;
745    mAlbumArt = NULL;
746}
747
748}  // namespace android
749