diff options
Diffstat (limited to 'media')
-rw-r--r-- | media/libstagefright/codecs/avc/dec/AVCDecoder.cpp | 276 | ||||
-rw-r--r-- | media/libstagefright/include/AVCDecoder.h | 3 |
2 files changed, 149 insertions, 130 deletions
diff --git a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp index 050e3da..7154ba5 100644 --- a/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp +++ b/media/libstagefright/codecs/avc/dec/AVCDecoder.cpp @@ -53,7 +53,9 @@ AVCDecoder::AVCDecoder(const sp<MediaSource> &source) mNumSamplesOutput(0), mPendingSeekTimeUs(-1), mPendingSeekMode(MediaSource::ReadOptions::SEEK_CLOSEST_SYNC), - mTargetTimeUs(-1) { + mTargetTimeUs(-1), + mSPSSeen(false), + mPPSSeen(false) { memset(mHandle, 0, sizeof(tagAVCHandle)); mHandle->AVCObject = NULL; mHandle->userData = this; @@ -165,6 +167,8 @@ status_t AVCDecoder::start(MetaData *) { mPendingSeekTimeUs = -1; mPendingSeekMode = ReadOptions::SEEK_CLOSEST_SYNC; mTargetTimeUs = -1; + mSPSSeen = false; + mPPSSeen = false; mStarted = true; return OK; @@ -314,184 +318,196 @@ status_t AVCDecoder::read( if (res != AVCDEC_SUCCESS) { LOGE("cannot determine nal type"); - } else switch (nalType) { - case AVC_NALTYPE_SPS: - { - res = PVAVCDecSeqParamSet( - mHandle, const_cast<uint8_t *>(fragPtr), - fragSize); - - if (res != AVCDEC_SUCCESS) { - break; - } + } else if (nalType == AVC_NALTYPE_SPS || nalType == AVC_NALTYPE_PPS + || (mSPSSeen && mPPSSeen)) { + switch (nalType) { + case AVC_NALTYPE_SPS: + { + mSPSSeen = true; + + res = PVAVCDecSeqParamSet( + mHandle, const_cast<uint8_t *>(fragPtr), + fragSize); - AVCDecObject *pDecVid = (AVCDecObject *)mHandle->AVCObject; + if (res != AVCDEC_SUCCESS) { + break; + } - int32_t width = - (pDecVid->seqParams[0]->pic_width_in_mbs_minus1 + 1) * 16; + AVCDecObject *pDecVid = (AVCDecObject *)mHandle->AVCObject; - int32_t height = - (pDecVid->seqParams[0]->pic_height_in_map_units_minus1 + 1) * 16; + int32_t width = + (pDecVid->seqParams[0]->pic_width_in_mbs_minus1 + 1) * 16; - int32_t crop_left, crop_right, crop_top, crop_bottom; - if (pDecVid->seqParams[0]->frame_cropping_flag) - { - crop_left = 2 * pDecVid->seqParams[0]->frame_crop_left_offset; - crop_right = - width - (2 * pDecVid->seqParams[0]->frame_crop_right_offset + 1); + int32_t height = + (pDecVid->seqParams[0]->pic_height_in_map_units_minus1 + 1) * 16; - if (pDecVid->seqParams[0]->frame_mbs_only_flag) + int32_t crop_left, crop_right, crop_top, crop_bottom; + if (pDecVid->seqParams[0]->frame_cropping_flag) { - crop_top = 2 * pDecVid->seqParams[0]->frame_crop_top_offset; - crop_bottom = - height - - (2 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1); + crop_left = 2 * pDecVid->seqParams[0]->frame_crop_left_offset; + crop_right = + width - (2 * pDecVid->seqParams[0]->frame_crop_right_offset + 1); + + if (pDecVid->seqParams[0]->frame_mbs_only_flag) + { + crop_top = 2 * pDecVid->seqParams[0]->frame_crop_top_offset; + crop_bottom = + height - + (2 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1); + } + else + { + crop_top = 4 * pDecVid->seqParams[0]->frame_crop_top_offset; + crop_bottom = + height - + (4 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1); + } + } else { + crop_bottom = height - 1; + crop_right = width - 1; + crop_top = crop_left = 0; } - else - { - crop_top = 4 * pDecVid->seqParams[0]->frame_crop_top_offset; - crop_bottom = - height - - (4 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1); + + 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); + + err = INFO_FORMAT_CHANGED; + } else { + *out = new MediaBuffer(0); + err = OK; } - } else { - crop_bottom = height - 1; - crop_right = width - 1; - crop_top = crop_left = 0; + break; } - int32_t aligned_width = (crop_right - crop_left + 1 + 15) & ~15; - int32_t aligned_height = (crop_bottom - crop_top + 1 + 15) & ~15; + case AVC_NALTYPE_PPS: + { + mPPSSeen = true; - int32_t oldWidth, oldHeight; - CHECK(mFormat->findInt32(kKeyWidth, &oldWidth)); - CHECK(mFormat->findInt32(kKeyHeight, &oldHeight)); + res = PVAVCDecPicParamSet( + mHandle, const_cast<uint8_t *>(fragPtr), + fragSize); - if (oldWidth != aligned_width || oldHeight != aligned_height) { - mFormat->setInt32(kKeyWidth, aligned_width); - mFormat->setInt32(kKeyHeight, aligned_height); + if (res != AVCDEC_SUCCESS) { + break; + } - err = INFO_FORMAT_CHANGED; - } else { *out = new MediaBuffer(0); - err = OK; - } - break; - } - - case AVC_NALTYPE_PPS: - { - res = PVAVCDecPicParamSet( - mHandle, const_cast<uint8_t *>(fragPtr), - fragSize); - if (res != AVCDEC_SUCCESS) { + err = OK; break; } - *out = new MediaBuffer(0); + case AVC_NALTYPE_SLICE: + case AVC_NALTYPE_IDR: + { + res = PVAVCDecodeSlice( + mHandle, const_cast<uint8_t *>(fragPtr), + fragSize); - err = OK; - break; - } + if (res == AVCDEC_PICTURE_OUTPUT_READY) { + int32_t index; + int32_t Release; + AVCFrameIO Output; + Output.YCbCr[0] = Output.YCbCr[1] = Output.YCbCr[2] = NULL; - case AVC_NALTYPE_SLICE: - case AVC_NALTYPE_IDR: - { - res = PVAVCDecodeSlice( - mHandle, const_cast<uint8_t *>(fragPtr), - fragSize); + CHECK_EQ(PVAVCDecGetOutput(mHandle, &index, &Release, &Output), + AVCDEC_SUCCESS); - 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(index >= 0); + CHECK(index < (int32_t)mFrames.size()); - CHECK_EQ(PVAVCDecGetOutput(mHandle, &index, &Release, &Output), - AVCDEC_SUCCESS); + MediaBuffer *mbuf = mFrames.editItemAt(index); - CHECK(index >= 0); - CHECK(index < (int32_t)mFrames.size()); + bool skipFrame = false; - MediaBuffer *mbuf = mFrames.editItemAt(index); + if (mTargetTimeUs >= 0) { + int64_t timeUs; + CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs)); + CHECK(timeUs <= mTargetTimeUs); - bool skipFrame = false; + if (timeUs < mTargetTimeUs) { + // We're still waiting for the frame with the matching + // timestamp and we won't return the current one. + skipFrame = true; - if (mTargetTimeUs >= 0) { - int64_t timeUs; - CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs)); - CHECK(timeUs <= mTargetTimeUs); + LOGV("skipping frame at %lld us", timeUs); + } else { + LOGV("found target frame at %lld us", timeUs); - if (timeUs < mTargetTimeUs) { - // We're still waiting for the frame with the matching - // timestamp and we won't return the current one. - skipFrame = true; + mTargetTimeUs = -1; + } + } - LOGV("skipping frame at %lld us", timeUs); + if (!skipFrame) { + *out = mbuf; + (*out)->set_range(0, (*out)->size()); + (*out)->add_ref(); } else { - LOGV("found target frame at %lld us", timeUs); - - mTargetTimeUs = -1; + *out = new MediaBuffer(0); } + + // Do _not_ release input buffer yet. + + releaseFragment = false; + err = OK; + break; } - if (!skipFrame) { - *out = mbuf; - (*out)->set_range(0, (*out)->size()); - (*out)->add_ref(); - } else { + if (res == AVCDEC_PICTURE_READY || res == AVCDEC_SUCCESS) { *out = new MediaBuffer(0); + + err = OK; + } else { + LOGV("failed to decode frame (res = %d)", res); } + break; + } - // Do _not_ release input buffer yet. + case AVC_NALTYPE_SEI: + { + res = PVAVCDecSEI( + mHandle, const_cast<uint8_t *>(fragPtr), + fragSize); + + if (res != AVCDEC_SUCCESS) { + break; + } + + *out = new MediaBuffer(0); - releaseFragment = false; err = OK; break; } - if (res == AVCDEC_PICTURE_READY || res == AVCDEC_SUCCESS) { + case AVC_NALTYPE_AUD: + case AVC_NALTYPE_FILL: + { *out = new MediaBuffer(0); err = OK; - } else { - LOGV("failed to decode frame (res = %d)", res); + break; } - break; - } - - case AVC_NALTYPE_SEI: - { - res = PVAVCDecSEI( - mHandle, const_cast<uint8_t *>(fragPtr), - fragSize); - if (res != AVCDEC_SUCCESS) { + default: + { + LOGE("Should not be here, unknown nalType %d", nalType); + CHECK(!"Should not be here"); break; } - - *out = new MediaBuffer(0); - - err = OK; - break; - } - - case AVC_NALTYPE_AUD: - case AVC_NALTYPE_FILL: - { - *out = new MediaBuffer(0); - - err = OK; - break; } + } else { + // We haven't seen SPS or PPS yet. - default: - { - LOGE("Should not be here, unknown nalType %d", nalType); - CHECK(!"Should not be here"); - break; - } + *out = new MediaBuffer(0); + err = OK; } if (releaseFragment) { diff --git a/media/libstagefright/include/AVCDecoder.h b/media/libstagefright/include/AVCDecoder.h index 7810171..898c90a 100644 --- a/media/libstagefright/include/AVCDecoder.h +++ b/media/libstagefright/include/AVCDecoder.h @@ -62,6 +62,9 @@ private: int64_t mTargetTimeUs; + bool mSPSSeen; + bool mPPSSeen; + void addCodecSpecificData(const uint8_t *data, size_t size); static int32_t ActivateSPSWrapper( |