Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 10b3b860 authored by Andreas Huber's avatar Andreas Huber Committed by Android (Google) Code Review
Browse files

Merge "Support some .avi files containing H.264 video, log warnings if audio/video unsupported"

parents dc7747d7 c639aad6
Loading
Loading
Loading
Loading
+92 −11
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#define LOG_TAG "AVIExtractor"
#include <utils/Log.h>

#include "include/avc_utils.h"
#include "include/AVIExtractor.h"

#include <binder/ProcessState.h>
@@ -362,6 +363,13 @@ static const char *GetMIMETypeForHandler(uint32_t handler) {
        case FOURCC('X', 'V', 'I', 'X'):
            return MEDIA_MIMETYPE_VIDEO_MPEG4;

        // from http://wiki.multimedia.cx/index.php?title=H264
        case FOURCC('a', 'v', 'c', '1'):
        case FOURCC('d', 'a', 'v', 'c'):
        case FOURCC('x', '2', '6', '4'):
        case FOURCC('v', 's', 's', 'h'):
            return MEDIA_MIMETYPE_VIDEO_AVC;

        default:
            return NULL;
    }
@@ -406,6 +414,14 @@ status_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) {
            return ERROR_MALFORMED;
        }

        if (mime == NULL) {
            LOGW("Unsupported video format '%c%c%c%c'",
                 (char)(handler >> 24),
                 (char)((handler >> 16) & 0xff),
                 (char)((handler >> 8) & 0xff),
                 (char)(handler & 0xff));
        }

        kind = Track::VIDEO;
    } else if (type == FOURCC('a', 'u', 'd', 's')) {
        if (mime && strncasecmp(mime, "audio/", 6)) {
@@ -473,8 +489,11 @@ status_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) {
        track->mMeta->setInt32(kKeyHeight, height);
    } else {
        uint32_t format = U16LE_AT(data);

        if (format == 0x55) {
            track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
        } else {
            LOGW("Unsupported audio format = 0x%04x", format);
        }

        uint32_t numChannels = U16LE_AT(&data[2]);
@@ -646,23 +665,28 @@ status_t AVIExtractor::parseIndex(off64_t offset, size_t size) {

        AString mime = tmp;

        if (!strncasecmp("video/", mime.c_str(), 6)
                && track->mThumbnailSampleIndex >= 0) {
        if (!strncasecmp("video/", mime.c_str(), 6)) {
            if (track->mThumbnailSampleIndex >= 0) {
                int64_t thumbnailTimeUs;
                CHECK_EQ((status_t)OK,
                         getSampleTime(i, track->mThumbnailSampleIndex,
                                       &thumbnailTimeUs));

                track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
            }

            status_t err = OK;

            if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
                status_t err = addMPEG4CodecSpecificData(i);
                err = addMPEG4CodecSpecificData(i);
            } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
                err = addH264CodecSpecificData(i);
            }

            if (err != OK) {
                return err;
            }
        }
        }

        if (track->mBytesPerSample != 0) {
            // Assume all chunks are the same size for now.
@@ -781,6 +805,63 @@ status_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) {
    return OK;
}

status_t AVIExtractor::addH264CodecSpecificData(size_t trackIndex) {
    Track *track = &mTracks.editItemAt(trackIndex);

    off64_t offset;
    size_t size;
    bool isKey;
    int64_t timeUs;

    // Extract codec specific data from the first non-empty sample.

    size_t sampleIndex = 0;
    for (;;) {
        status_t err =
            getSampleInfo(
                    trackIndex, sampleIndex, &offset, &size, &isKey, &timeUs);

        if (err != OK) {
            return err;
        }

        if (size > 0) {
            break;
        }

        ++sampleIndex;
    }

    sp<ABuffer> buffer = new ABuffer(size);
    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());

    if (n < (ssize_t)size) {
        return n < 0 ? (status_t)n : ERROR_MALFORMED;
    }

    sp<MetaData> meta = MakeAVCCodecSpecificData(buffer);

    if (meta == NULL) {
        LOGE("Unable to extract AVC codec specific data");
        return ERROR_MALFORMED;
    }

    int32_t width, height;
    CHECK(meta->findInt32(kKeyWidth, &width));
    CHECK(meta->findInt32(kKeyHeight, &height));

    uint32_t type;
    const void *csd;
    size_t csdSize;
    CHECK(meta->findData(kKeyAVCC, &type, &csd, &csdSize));

    track->mMeta->setInt32(kKeyWidth, width);
    track->mMeta->setInt32(kKeyHeight, width);
    track->mMeta->setData(kKeyAVCC, type, csd, csdSize);

    return OK;
}

status_t AVIExtractor::getSampleInfo(
        size_t trackIndex, size_t sampleIndex,
        off64_t *offset, size_t *size, bool *isKey,
+1 −1
Original line number Diff line number Diff line
@@ -297,7 +297,7 @@ sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit) {
    sp<MetaData> meta = new MetaData;
    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);

    meta->setData(kKeyAVCC, 0, csd->data(), csd->size());
    meta->setData(kKeyAVCC, kTypeAVCC, csd->data(), csd->size());
    meta->setInt32(kKeyWidth, width);
    meta->setInt32(kKeyHeight, height);

+1 −0
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ private:
            size_t *sampleIndex) const;

    status_t addMPEG4CodecSpecificData(size_t trackIndex);
    status_t addH264CodecSpecificData(size_t trackIndex);

    static bool IsCorrectChunkType(
        ssize_t trackIndex, Track::Kind kind, uint32_t chunkType);