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

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

Merge "Update software AVC decoder to no longer require the kWantsNALFragments hack." into kraken

parents 85bc1192 94020380
Loading
Loading
Loading
Loading
+88 −59
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@

namespace android {

static const char kStartCode[4] = { 0x00, 0x00, 0x00, 0x01 };

static int32_t Malloc(void *userData, int32_t size, int32_t attrs) {
    return reinterpret_cast<int32_t>(malloc(size));
}
@@ -154,9 +156,7 @@ status_t AVCDecoder::start(MetaData *) {
        }
    }

    sp<MetaData> params = new MetaData;
    params->setInt32(kKeyWantsNALFragments, true);
    mSource->start(params.get());
    mSource->start();

    mAnchorTimeUs = 0;
    mNumSamplesOutput = 0;
@@ -167,9 +167,10 @@ status_t AVCDecoder::start(MetaData *) {
}

void AVCDecoder::addCodecSpecificData(const uint8_t *data, size_t size) {
    MediaBuffer *buffer = new MediaBuffer(size);
    memcpy(buffer->data(), data, size);
    buffer->set_range(0, size);
    MediaBuffer *buffer = new MediaBuffer(size + 4);
    memcpy(buffer->data(), kStartCode, 4);
    memcpy((uint8_t *)buffer->data() + 4, data, size);
    buffer->set_range(0, size + 4);

    mCodecSpecificData.push(buffer);
}
@@ -200,6 +201,29 @@ sp<MetaData> AVCDecoder::getFormat() {
    return mFormat;
}

static void findNALFragment(
        const MediaBuffer *buffer, const uint8_t **fragPtr, size_t *fragSize) {
    const uint8_t *data =
        (const uint8_t *)buffer->data() + buffer->range_offset();

    size_t size = buffer->range_length();

    CHECK(size >= 4);
    CHECK(!memcmp(kStartCode, data, 4));

    size_t offset = 4;
    while (offset + 3 < size && memcmp(kStartCode, &data[offset], 4)) {
        ++offset;
    }

    *fragPtr = &data[4];
    if (offset + 3 >= size) {
        *fragSize = size - 4;
    } else {
        *fragSize = offset - 4;
    }
}

status_t AVCDecoder::read(
        MediaBuffer **out, const ReadOptions *options) {
    *out = NULL;
@@ -254,37 +278,31 @@ status_t AVCDecoder::read(
        }
    }

    const uint8_t *inPtr =
        (const uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset();
    const uint8_t *fragPtr;
    size_t fragSize;
    findNALFragment(mInputBuffer, &fragPtr, &fragSize);

    bool releaseFragment = true;
    status_t err = UNKNOWN_ERROR;

    int nalType;
    int nalRefIdc;
    AVCDec_Status res =
        PVAVCDecGetNALType(
                const_cast<uint8_t *>(inPtr), mInputBuffer->range_length(),
                const_cast<uint8_t *>(fragPtr), fragSize,
                &nalType, &nalRefIdc);

    if (res != AVCDEC_SUCCESS) {
        LOGE("cannot determine nal type");

        mInputBuffer->release();
        mInputBuffer = NULL;

        return UNKNOWN_ERROR;
    }

    switch (nalType) {
    } else switch (nalType) {
        case AVC_NALTYPE_SPS:
        {
            res = PVAVCDecSeqParamSet(
                    mHandle, const_cast<uint8_t *>(inPtr),
                    mInputBuffer->range_length());
                    mHandle, const_cast<uint8_t *>(fragPtr),
                    fragSize);

            if (res != AVCDEC_SUCCESS) {
                mInputBuffer->release();
                mInputBuffer = NULL;

                return UNKNOWN_ERROR;
                break;
            }

            AVCDecObject *pDecVid = (AVCDecObject *)mHandle->AVCObject;
@@ -324,47 +342,53 @@ status_t AVCDecoder::read(

            int32_t aligned_width = (crop_right - crop_left + 1 + 15) & ~15;
            int32_t aligned_height = (crop_bottom - crop_top + 1 + 15) & ~15;

            int32_t oldWidth, oldHeight;
            CHECK(mFormat->findInt32(kKeyWidth, &oldWidth));
            CHECK(mFormat->findInt32(kKeyHeight, &oldHeight));

            if (oldWidth != aligned_width || oldHeight != aligned_height) {
                mFormat->setInt32(kKeyWidth, aligned_width);
                mFormat->setInt32(kKeyHeight, aligned_height);

            mInputBuffer->release();
            mInputBuffer = NULL;

            return INFO_FORMAT_CHANGED;
                err = INFO_FORMAT_CHANGED;
            } else {
                *out = new MediaBuffer(0);
                err = OK;
            }
            break;
        }

        case AVC_NALTYPE_PPS:
        {
            res = PVAVCDecPicParamSet(
                    mHandle, const_cast<uint8_t *>(inPtr),
                    mInputBuffer->range_length());

            mInputBuffer->release();
            mInputBuffer = NULL;
                    mHandle, const_cast<uint8_t *>(fragPtr),
                    fragSize);

            if (res != AVCDEC_SUCCESS) {
                return UNKNOWN_ERROR;
                break;
            }

            *out = new MediaBuffer(0);

            return OK;
            err = OK;
            break;
        }

        case AVC_NALTYPE_SLICE:
        case AVC_NALTYPE_IDR:
        {
            res = PVAVCDecodeSlice(
                    mHandle, const_cast<uint8_t *>(inPtr),
                    mInputBuffer->range_length());
                    mHandle, const_cast<uint8_t *>(fragPtr),
                    fragSize);

            if (res == AVCDEC_PICTURE_OUTPUT_READY) {
                int32_t index;
                int32_t Release;
                AVCFrameIO Output;
                Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL;
                CHECK_EQ(PVAVCDecGetOutput(
                            mHandle, &index, &Release, &Output),

                CHECK_EQ(PVAVCDecGetOutput(mHandle, &index, &Release, &Output),
                         AVCDEC_SUCCESS);

                CHECK(index >= 0);
@@ -376,48 +400,44 @@ status_t AVCDecoder::read(

                // Do _not_ release input buffer yet.

                return OK;
                releaseFragment = false;
                err = OK;
                break;
            }

            mInputBuffer->release();
            mInputBuffer = NULL;

            if (res == AVCDEC_PICTURE_READY || res == AVCDEC_SUCCESS) {
                *out = new MediaBuffer(0);

                return OK;
                err = OK;
            } else {
                LOGV("failed to decode frame (res = %d)", res);
                return UNKNOWN_ERROR;
            }
            break;
        }

        case AVC_NALTYPE_SEI:
        {
            res = PVAVCDecSEI(
                    mHandle, const_cast<uint8_t *>(inPtr),
                    mInputBuffer->range_length());

            mInputBuffer->release();
            mInputBuffer = NULL;
                    mHandle, const_cast<uint8_t *>(fragPtr),
                    fragSize);

            if (res != AVCDEC_SUCCESS) {
                return UNKNOWN_ERROR;
                break;
            }

            *out = new MediaBuffer(0);

            return OK;
            err = OK;
            break;
        }

        case AVC_NALTYPE_AUD:
        case AVC_NALTYPE_FILL:
        {
            mInputBuffer->release();
            mInputBuffer = NULL;

            *out = new MediaBuffer(0);

            return OK;
            err = OK;
            break;
        }

        default:
@@ -428,10 +448,19 @@ status_t AVCDecoder::read(
        }
    }

    if (releaseFragment) {
        size_t offset = mInputBuffer->range_offset();
        if (fragSize + 4 == mInputBuffer->range_length()) {
            mInputBuffer->release();
            mInputBuffer = NULL;
        } else {
            mInputBuffer->set_range(
                    offset + fragSize + 4,
                    mInputBuffer->range_length() - fragSize - 4);
        }
    }

    return UNKNOWN_ERROR;
    return err;
}

// static