Loading media/libstagefright/codecs/avc/dec/AVCDecoder.cpp +88 −59 Original line number Diff line number Diff line Loading @@ -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)); } Loading Loading @@ -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; Loading @@ -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); } Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading @@ -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: Loading @@ -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 Loading Loading
media/libstagefright/codecs/avc/dec/AVCDecoder.cpp +88 −59 Original line number Diff line number Diff line Loading @@ -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)); } Loading Loading @@ -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; Loading @@ -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); } Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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); Loading @@ -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: Loading @@ -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 Loading