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

Commit f3b7859f authored by James Dong's avatar James Dong
Browse files

Only check the codec specific data when the output buffer contains kKeyIsCodecConfig in MP4 writer

o Assume there is only a single output buffer containing such information.
  This simplifies the logic in MP4 file writer

o Output SPS and PPS in the very first buffer for software AVC encoder
  This is to make AVC encoder work with the MP4 file writer

o Add timestamp value for codec config data

Change-Id: Iad27a04579e6028332429cd0bebd30976041e997
parent 259b4c86
Loading
Loading
Loading
Loading
+6 −85
Original line number Diff line number Diff line
@@ -1377,91 +1377,6 @@ void MPEG4Writer::Track::threadEntry() {

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

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

            const size_t size = buffer->range_length();

            size_t offset = 0;
            while (offset + 3 < size) {
                if (data[offset] == 0x00 && data[offset + 1] == 0x00
                    && data[offset + 2] == 0x01 && data[offset + 3] == 0xb6) {
                    break;
                }

                ++offset;
            }

            // CHECK(offset + 3 < size);
            if (offset + 3 >= size) {
                // XXX assume the entire first chunk of data is the codec specific
                // data.
                offset = size;
            }

            mCodecSpecificDataSize = offset;
            mCodecSpecificData = malloc(offset);
            memcpy(mCodecSpecificData, data, offset);

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

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

                continue;
            }

            mGotAllCodecSpecificData = true;
        } else if (!mGotAllCodecSpecificData && mIsAvc && 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;
                CHECK_EQ(OK, err);

                mGotAllCodecSpecificData = true;
            }

            continue;
        }

        if (!mGotAllCodecSpecificData) {
            mGotAllCodecSpecificData = true;
        }

        // Make a deep copy of the MediaBuffer and Metadata and release
@@ -1962,6 +1877,8 @@ void MPEG4Writer::Track::writeTrackHeader(
                  mOwner->writeInt32(samplerate << 16);
                  if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
                    mOwner->beginBox("esds");
                        CHECK(mCodecSpecificData);
                        CHECK(mCodecSpecificDataSize > 0);

                        mOwner->writeInt32(0);     // version=0, flags=0
                        mOwner->writeInt8(0x03);   // ES_DescrTag
@@ -2039,6 +1956,8 @@ void MPEG4Writer::Track::writeTrackHeader(
                  mOwner->writeInt16(0x18);        // depth
                  mOwner->writeInt16(-1);          // predefined

                  CHECK(mCodecSpecificData);
                  CHECK(mCodecSpecificDataSize > 0);
                  CHECK(23 + mCodecSpecificDataSize < 128);

                  if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_MPEG4, mime)) {
@@ -2086,6 +2005,8 @@ void MPEG4Writer::Track::writeTrackHeader(

                      mOwner->endBox();  // d263
                  } else if (!strcasecmp(MEDIA_MIMETYPE_VIDEO_AVC, mime)) {
                      CHECK(mCodecSpecificData);
                      CHECK(mCodecSpecificDataSize > 0);
                      mOwner->beginBox("avcC");
                        mOwner->write(mCodecSpecificData, mCodecSpecificDataSize);
                      mOwner->endBox();  // avcC
+22 −7
Original line number Diff line number Diff line
@@ -337,14 +337,18 @@ status_t AVCEncoder::read(

    MediaBuffer *outputBuffer;
    CHECK_EQ(OK, mGroup->acquire_buffer(&outputBuffer));
    uint8_t *outPtr = (uint8_t *) outputBuffer->data();
    uint32_t dataLength = outputBuffer->size();

    // Add 4 bytes for the start code 0x00000001
    uint8_t *outPtr = (uint8_t *) outputBuffer->data() + 4;
    uint32_t dataLength = outputBuffer->size() - 4;

    int32_t type;
    AVCEnc_Status encoderStatus = AVCENC_SUCCESS;

    // Return SPS and PPS for the first two buffers
    if (!mSpsPpsHeaderReceived) {
    // Combine SPS and PPS and place them in the very first output buffer
    // SPS and PPS are separated by start code 0x00000001
    // Assume that we have exactly one SPS and exactly one PPS.
    while (!mSpsPpsHeaderReceived && mNumInputFrames <= 0) {
        encoderStatus = PVAVCEncodeNAL(mHandle, outPtr, &dataLength, &type);
        if (encoderStatus == AVCENC_WRONG_STATE) {
            mSpsPpsHeaderReceived = true;
@@ -352,11 +356,22 @@ status_t AVCEncoder::read(
        } else {
            switch (type) {
                case AVC_NALTYPE_SPS:
                    ++mNumInputFrames;
                    memcpy(outputBuffer->data(), "\x00\x00\x00\x01", 4);
                    outputBuffer->set_range(0, dataLength + 4);
                    outPtr += (dataLength + 4);  // 4 bytes for next start code
                    dataLength = outputBuffer->size() -
                            (outputBuffer->range_length() + 4);
                    break;
                case AVC_NALTYPE_PPS:
                    LOGV("%s received",
                            (type == AVC_NALTYPE_SPS)? "SPS": "PPS");
                    ++mNumInputFrames;
                    outputBuffer->set_range(0, dataLength);
                    memcpy(((uint8_t *) outputBuffer->data()) +
                            outputBuffer->range_length(),
                            "\x00\x00\x00\x01", 4);
                    outputBuffer->set_range(0,
                            dataLength + outputBuffer->range_length() + 4);
                    outputBuffer->meta_data()->setInt32(kKeyIsCodecConfig, 1);
                    outputBuffer->meta_data()->setInt64(kKeyTime, 0);
                    *out = outputBuffer;
                    return OK;
                default: