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

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

Merge "Various fixes to enable recording on passion and nexus1." into kraken

parents 4b2bc736 71c27d99
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -147,7 +147,7 @@ int main(int argc, char **argv) {
    OMXClient client;
    CHECK_EQ(client.connect(), OK);

#if 1
#if 0
    sp<MediaSource> source = createSource(argv[1]);

    if (source == NULL) {
@@ -165,14 +165,15 @@ int main(int argc, char **argv) {
    success = success && meta->findInt32(kKeyHeight, &height);
    CHECK(success);
#else
    int width = 800;
    int width = 720;
    int height = 480;
    sp<MediaSource> decoder = new DummySource(width, height);
#endif

    sp<MetaData> enc_meta = new MetaData;
    // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
    enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
    // enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
    enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
    enc_meta->setInt32(kKeyWidth, width);
    enc_meta->setInt32(kKeyHeight, height);

@@ -213,6 +214,8 @@ int main(int argc, char **argv) {

#if 0
    CameraSource *source = CameraSource::Create();
    source->start();

    printf("source = %p\n", source);

    for (int i = 0; i < 100; ++i) {
@@ -227,6 +230,8 @@ int main(int argc, char **argv) {
        buffer = NULL;
    }

    source->stop();

    delete source;
    source = NULL;
#endif
+0 −7
Original line number Diff line number Diff line
@@ -142,13 +142,6 @@ CameraSource::CameraSource(const sp<Camera> &camera)
      mFirstFrameTimeUs(0),
      mNumFrames(0),
      mStarted(false) {
    char value[PROPERTY_VALUE_MAX];
    if (property_get("ro.hardware", value, NULL) && !strcmp(value, "sholes")) {
        // The hardware encoder(s) do not support yuv420, but only YCbYCr,
        // fortunately the camera also supports this, so we needn't transcode.
        mCamera->setParameters(String8("preview-format=yuv422i-yuyv"));
    }

    String8 s = mCamera->getParameters();
    printf("params: \"%s\"\n", s.string());

+185 −40
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/Utils.h>

@@ -65,10 +66,15 @@ private:
    static void *ThreadWrapper(void *me);
    void threadEntry();

    status_t makeAVCCodecSpecificData(
            const uint8_t *data, size_t size);

    Track(const Track &);
    Track &operator=(const Track &);
};

#define USE_NALLEN_FOUR         1

MPEG4Writer::MPEG4Writer(const char *filename)
    : mFile(fopen(filename, "wb")),
      mOffset(0),
@@ -213,23 +219,55 @@ off_t MPEG4Writer::addSample(MediaBuffer *buffer) {
    return old_offset;
}

static void StripStartcode(MediaBuffer *buffer) {
    if (buffer->range_length() < 4) {
        return;
    }

    const uint8_t *ptr =
        (const uint8_t *)buffer->data() + buffer->range_offset();

    if (!memcmp(ptr, "\x00\x00\x00\x01", 4)) {
        buffer->set_range(
                buffer->range_offset() + 4, buffer->range_length() - 4);
    }
}

off_t MPEG4Writer::addLengthPrefixedSample(MediaBuffer *buffer) {
    Mutex::Autolock autoLock(mLock);

    StripStartcode(buffer);

    off_t old_offset = mOffset;

    size_t length = buffer->range_length();

#if USE_NALLEN_FOUR
    uint8_t x = length >> 24;
    fwrite(&x, 1, 1, mFile);
    x = (length >> 16) & 0xff;
    fwrite(&x, 1, 1, mFile);
    x = (length >> 8) & 0xff;
    fwrite(&x, 1, 1, mFile);
    x = length & 0xff;
    fwrite(&x, 1, 1, mFile);
#else
    CHECK(length < 65536);

    uint8_t x = length >> 8;
    fwrite(&x, 1, 1, mFile);
    x = length & 0xff;
    fwrite(&x, 1, 1, mFile);
#endif

    fwrite((const uint8_t *)buffer->data() + buffer->range_offset(),
           1, length, mFile);

#if USE_NALLEN_FOUR
    mOffset += length + 4;
#else
    mOffset += length + 2;
#endif

    return old_offset;
}
@@ -380,6 +418,60 @@ void *MPEG4Writer::Track::ThreadWrapper(void *me) {
    return NULL;
}

status_t MPEG4Writer::Track::makeAVCCodecSpecificData(
        const uint8_t *data, size_t size) {
    if (mCodecSpecificData != NULL) {
        return ERROR_MALFORMED;
    }

    if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) {
        // Must start with a start-code.
        return ERROR_MALFORMED;
    }

    size_t picParamOffset = 4;
    while (picParamOffset + 3 < size
            && memcmp("\x00\x00\x00\x01", &data[picParamOffset], 4)) {
        ++picParamOffset;
    }

    if (picParamOffset + 3 >= size) {
        // Could not find start-code for pictureParameterSet.
        return ERROR_MALFORMED;
    }

    size_t seqParamSetLength = picParamOffset - 4;
    size_t picParamSetLength = size - picParamOffset - 4;

    mCodecSpecificDataSize =
        6 + 1 + seqParamSetLength + 2 + picParamSetLength + 2;

    mCodecSpecificData = malloc(mCodecSpecificDataSize);
    uint8_t *header = (uint8_t *)mCodecSpecificData;
    header[0] = 1;
    header[1] = 0x42;  // profile
    header[2] = 0x80;
    header[3] = 0x1e;  // level

#if USE_NALLEN_FOUR
    header[4] = 0xfc | 3;  // length size == 4 bytes
#else
    header[4] = 0xfc | 1;  // length size == 2 bytes
#endif

    header[5] = 0xe0 | 1;
    header[6] = seqParamSetLength >> 8;
    header[7] = seqParamSetLength & 0xff;
    memcpy(&header[8], &data[4], seqParamSetLength);
    header += 8 + seqParamSetLength;
    header[0] = 1;
    header[1] = picParamSetLength >> 8;
    header[2] = picParamSetLength & 0xff;
    memcpy(&header[3], &data[picParamOffset + 4], picParamSetLength);

    return OK;
}

void MPEG4Writer::Track::threadEntry() {
    sp<MetaData> meta = mSource->getFormat();
    const char *mime;
@@ -399,54 +491,40 @@ void MPEG4Writer::Track::threadEntry() {

        ++count;

        if (is_avc && count < 3) {
            size_t size = buffer->range_length();

            switch (count) {
                case 1:
                {
                    CHECK_EQ(mCodecSpecificData, NULL);
                    mCodecSpecificData = malloc(size + 8);
                    uint8_t *header = (uint8_t *)mCodecSpecificData;
                    header[0] = 1;
                    header[1] = 0x42;  // profile
                    header[2] = 0x80;
                    header[3] = 0x1e;  // level
                    header[4] = 0xfc | 3;
                    header[5] = 0xe0 | 1;
                    header[6] = size >> 8;
                    header[7] = size & 0xff;
                    memcpy(&header[8],
                            (const uint8_t *)buffer->data() + buffer->range_offset(),
                            size);
        int32_t isCodecConfig;
        if (buffer->meta_data()->findInt32(kKeyIsCodecConfig, &isCodecConfig)
                && isCodecConfig) {
            if (is_avc) {
                status_t err = makeAVCCodecSpecificData(
                        (const uint8_t *)buffer->data()
                            + buffer->range_offset(),
                        buffer->range_length());

                    mCodecSpecificDataSize = size + 8;
                if (err != OK) {
                    LOGE("failed to parse avc codec specific data.");
                    break;
                }

                case 2:
                {
                    size_t offset = mCodecSpecificDataSize;
                    mCodecSpecificDataSize += size + 3;
                    mCodecSpecificData = realloc(mCodecSpecificData, mCodecSpecificDataSize);
                    uint8_t *header = (uint8_t *)mCodecSpecificData;
                    header[offset] = 1;
                    header[offset + 1] = size >> 8;
                    header[offset + 2] = size & 0xff;
                    memcpy(&header[offset + 3],
                            (const uint8_t *)buffer->data() + buffer->range_offset(),
                            size);
            } else if (is_mpeg4) {
                if (mCodecSpecificData != NULL) {
                    break;
                }

                mCodecSpecificDataSize = buffer->range_length();
                mCodecSpecificData = malloc(mCodecSpecificDataSize);
                memcpy(mCodecSpecificData,
                        (const uint8_t *)buffer->data()
                            + buffer->range_offset(),
                       buffer->range_length());
            }

            buffer->release();
            buffer = NULL;

            continue;
        }
        } else if (count == 1 && is_mpeg4 && mCodecSpecificData == NULL) {
            // The TI mpeg4 encoder does not properly set the
            // codec-specific-data flag.

        if (mCodecSpecificData == NULL && is_mpeg4) {
            const uint8_t *data =
                (const uint8_t *)buffer->data() + buffer->range_offset();

@@ -474,13 +552,70 @@ void MPEG4Writer::Track::threadEntry() {
            memcpy(mCodecSpecificData, data, offset);

            buffer->set_range(buffer->range_offset() + offset, size - offset);

            if (size == offset) {
                buffer->release();
                buffer = NULL;

                continue;
            }
        } else if (is_avc && count < 3) {
            // The TI video encoder does not flag codec specific data
            // as such and also splits up SPS and PPS across two buffers.

            const uint8_t *data =
                (const uint8_t *)buffer->data() + buffer->range_offset();

            size_t size = buffer->range_length();

            CHECK(count == 2 || mCodecSpecificData == NULL);

            size_t offset = mCodecSpecificDataSize;
            mCodecSpecificDataSize += size + 4;
            mCodecSpecificData =
                realloc(mCodecSpecificData, mCodecSpecificDataSize);

            memcpy((uint8_t *)mCodecSpecificData + offset,
                   "\x00\x00\x00\x01", 4);

            memcpy((uint8_t *)mCodecSpecificData + offset + 4, data, size);

            buffer->release();
            buffer = NULL;

            if (count == 2) {
                void *tmp = mCodecSpecificData;
                size = mCodecSpecificDataSize;
                mCodecSpecificData = NULL;
                mCodecSpecificDataSize = 0;

                status_t err = makeAVCCodecSpecificData(
                        (const uint8_t *)tmp, size);

                free(tmp);
                tmp = NULL;

                if (err != OK) {
                    LOGE("failed to parse avc codec specific data.");
                    break;
                }
            }

            continue;
        }

        off_t offset = is_avc ? mOwner->addLengthPrefixedSample(buffer)
                              : mOwner->addSample(buffer);

        SampleInfo info;
        info.size = is_avc ? buffer->range_length() + 2 : buffer->range_length();
        info.size = is_avc
#if USE_NALLEN_FOUR
            ? buffer->range_length() + 4
#else
            ? buffer->range_length() + 2
#endif
            : buffer->range_length();

        info.offset = offset;

        int64_t timestampUs;
@@ -733,19 +868,29 @@ void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) {

          mOwner->beginBox("stts");
            mOwner->writeInt32(0);  // version=0, flags=0
            mOwner->writeInt32(mSampleInfos.size() - 1);
            mOwner->writeInt32(mSampleInfos.size());

            List<SampleInfo>::iterator it = mSampleInfos.begin();
            int64_t last = (*it).timestamp;
            int64_t lastDuration = 1;

            ++it;
            while (it != mSampleInfos.end()) {
                mOwner->writeInt32(1);
                mOwner->writeInt32((*it).timestamp - last);
                lastDuration = (*it).timestamp - last;
                mOwner->writeInt32(lastDuration);

                last = (*it).timestamp;

                ++it;
            }

            // We don't really know how long the last frame lasts, since
            // there is no frame time after it, just repeat the previous
            // frame's duration.
            mOwner->writeInt32(1);
            mOwner->writeInt32(lastDuration);

          mOwner->endBox();  // stts

          mOwner->beginBox("stsz");
+12 −2
Original line number Diff line number Diff line
@@ -137,6 +137,7 @@ static const CodecInfo kEncoderInfo[] = {
    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.qcom.video.encoder.h263" },
    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.TI.Video.encoder" },
    { MEDIA_MIMETYPE_VIDEO_H263, "OMX.PV.h263enc" },
    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.qcom.video.encoder.avc" },
    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.TI.Video.encoder" },
    { MEDIA_MIMETYPE_VIDEO_AVC, "OMX.PV.avcenc" },
};
@@ -679,6 +680,7 @@ static size_t getFrameSize(
        case OMX_COLOR_FormatCbYCrY:
            return width * height * 2;

        case OMX_COLOR_FormatYUV420Planar:
        case OMX_COLOR_FormatYUV420SemiPlanar:
            return (width * height * 3) / 2;

@@ -706,7 +708,7 @@ void OMXCodec::setVideoInputFormat(

    OMX_COLOR_FORMATTYPE colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
    if (!strcasecmp("OMX.TI.Video.encoder", mComponentName)) {
        colorFormat = OMX_COLOR_FormatYCbYCr;
        colorFormat = OMX_COLOR_FormatYUV420Planar;
    }

    CHECK_EQ(setVideoPortFormatType(
@@ -764,6 +766,14 @@ void OMXCodec::setVideoInputFormat(
            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
    CHECK_EQ(err, OK);

    err = mOMX->getParameter(
            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
    CHECK_EQ(err, OK);

    err = mOMX->setParameter(
            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
    CHECK_EQ(err, OK);

    switch (compressionFormat) {
        case OMX_VIDEO_CodingMPEG4:
        {
@@ -911,7 +921,7 @@ status_t OMXCodec::setupAVCEncoderParameters() {
    CHECK_EQ(err, OK);

    bitrateType.eControlRate = OMX_Video_ControlRateVariable;
    bitrateType.nTargetBitrate = 1000000;
    bitrateType.nTargetBitrate = 3000000;

    err = mOMX->setParameter(
            mNode, OMX_IndexParamVideoBitrate,
+6 −0
Original line number Diff line number Diff line
@@ -264,6 +264,8 @@ status_t OMXNodeInstance::useBuffer(
        return UNKNOWN_ERROR;
    }

    CHECK_EQ(header->pAppPrivate, buffer_meta);

    *buffer = header;

    addActiveBuffer(portIndex, *buffer);
@@ -294,6 +296,8 @@ status_t OMXNodeInstance::allocateBuffer(
        return UNKNOWN_ERROR;
    }

    CHECK_EQ(header->pAppPrivate, buffer_meta);

    *buffer = header;
    *buffer_data = header->pBuffer;

@@ -325,6 +329,8 @@ status_t OMXNodeInstance::allocateBufferWithBackup(
        return UNKNOWN_ERROR;
    }

    CHECK_EQ(header->pAppPrivate, buffer_meta);

    *buffer = header;

    addActiveBuffer(portIndex, *buffer);