am 86d2c088: Merge "Don\'t return a decoder error if the encoded stream does not start with SPS/PPS." into gingerbread

Merge commit '86d2c088f15e0df33d5f81bece1c2f088632cc2c' into gingerbread-plus-aosp

* commit '86d2c088f15e0df33d5f81bece1c2f088632cc2c':
  Don't return a decoder error if the encoded stream does not start with SPS/PPS.
This commit is contained in:
Andreas Huber
2010-08-04 14:18:58 -07:00
committed by Android Git Automerger
2 changed files with 175 additions and 156 deletions

View File

@@ -53,7 +53,9 @@ AVCDecoder::AVCDecoder(const sp<MediaSource> &source)
mNumSamplesOutput(0), mNumSamplesOutput(0),
mPendingSeekTimeUs(-1), mPendingSeekTimeUs(-1),
mPendingSeekMode(MediaSource::ReadOptions::SEEK_CLOSEST_SYNC), mPendingSeekMode(MediaSource::ReadOptions::SEEK_CLOSEST_SYNC),
mTargetTimeUs(-1) { mTargetTimeUs(-1),
mSPSSeen(false),
mPPSSeen(false) {
memset(mHandle, 0, sizeof(tagAVCHandle)); memset(mHandle, 0, sizeof(tagAVCHandle));
mHandle->AVCObject = NULL; mHandle->AVCObject = NULL;
mHandle->userData = this; mHandle->userData = this;
@@ -165,6 +167,8 @@ status_t AVCDecoder::start(MetaData *) {
mPendingSeekTimeUs = -1; mPendingSeekTimeUs = -1;
mPendingSeekMode = ReadOptions::SEEK_CLOSEST_SYNC; mPendingSeekMode = ReadOptions::SEEK_CLOSEST_SYNC;
mTargetTimeUs = -1; mTargetTimeUs = -1;
mSPSSeen = false;
mPPSSeen = false;
mStarted = true; mStarted = true;
return OK; return OK;
@@ -314,184 +318,196 @@ status_t AVCDecoder::read(
if (res != AVCDEC_SUCCESS) { if (res != AVCDEC_SUCCESS) {
LOGE("cannot determine nal type"); LOGE("cannot determine nal type");
} else switch (nalType) { } else if (nalType == AVC_NALTYPE_SPS || nalType == AVC_NALTYPE_PPS
case AVC_NALTYPE_SPS: || (mSPSSeen && mPPSSeen)) {
{ switch (nalType) {
res = PVAVCDecSeqParamSet( case AVC_NALTYPE_SPS:
mHandle, const_cast<uint8_t *>(fragPtr),
fragSize);
if (res != AVCDEC_SUCCESS) {
break;
}
AVCDecObject *pDecVid = (AVCDecObject *)mHandle->AVCObject;
int32_t width =
(pDecVid->seqParams[0]->pic_width_in_mbs_minus1 + 1) * 16;
int32_t height =
(pDecVid->seqParams[0]->pic_height_in_map_units_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; mSPSSeen = true;
crop_right =
width - (2 * pDecVid->seqParams[0]->frame_crop_right_offset + 1);
if (pDecVid->seqParams[0]->frame_mbs_only_flag) res = PVAVCDecSeqParamSet(
{ mHandle, const_cast<uint8_t *>(fragPtr),
crop_top = 2 * pDecVid->seqParams[0]->frame_crop_top_offset; fragSize);
crop_bottom =
height - if (res != AVCDEC_SUCCESS) {
(2 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1); break;
} }
else
AVCDecObject *pDecVid = (AVCDecObject *)mHandle->AVCObject;
int32_t width =
(pDecVid->seqParams[0]->pic_width_in_mbs_minus1 + 1) * 16;
int32_t height =
(pDecVid->seqParams[0]->pic_height_in_map_units_minus1 + 1) * 16;
int32_t crop_left, crop_right, crop_top, crop_bottom;
if (pDecVid->seqParams[0]->frame_cropping_flag)
{ {
crop_top = 4 * pDecVid->seqParams[0]->frame_crop_top_offset; crop_left = 2 * pDecVid->seqParams[0]->frame_crop_left_offset;
crop_bottom = crop_right =
height - width - (2 * pDecVid->seqParams[0]->frame_crop_right_offset + 1);
(4 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
}
} else {
crop_bottom = height - 1;
crop_right = width - 1;
crop_top = crop_left = 0;
}
int32_t aligned_width = (crop_right - crop_left + 1 + 15) & ~15; if (pDecVid->seqParams[0]->frame_mbs_only_flag)
int32_t aligned_height = (crop_bottom - crop_top + 1 + 15) & ~15; {
crop_top = 2 * pDecVid->seqParams[0]->frame_crop_top_offset;
int32_t oldWidth, oldHeight; crop_bottom =
CHECK(mFormat->findInt32(kKeyWidth, &oldWidth)); height -
CHECK(mFormat->findInt32(kKeyHeight, &oldHeight)); (2 * pDecVid->seqParams[0]->frame_crop_bottom_offset + 1);
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;
}
break;
}
case AVC_NALTYPE_PPS:
{
res = PVAVCDecPicParamSet(
mHandle, const_cast<uint8_t *>(fragPtr),
fragSize);
if (res != AVCDEC_SUCCESS) {
break;
}
*out = new MediaBuffer(0);
err = OK;
break;
}
case AVC_NALTYPE_SLICE:
case AVC_NALTYPE_IDR:
{
res = PVAVCDecodeSlice(
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),
AVCDEC_SUCCESS);
CHECK(index >= 0);
CHECK(index < (int32_t)mFrames.size());
MediaBuffer *mbuf = mFrames.editItemAt(index);
bool skipFrame = false;
if (mTargetTimeUs >= 0) {
int64_t timeUs;
CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
CHECK(timeUs <= mTargetTimeUs);
if (timeUs < mTargetTimeUs) {
// We're still waiting for the frame with the matching
// timestamp and we won't return the current one.
skipFrame = true;
LOGV("skipping frame at %lld us", timeUs);
} else {
LOGV("found target frame at %lld us", timeUs);
mTargetTimeUs = -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;
} }
if (!skipFrame) { int32_t aligned_width = (crop_right - crop_left + 1 + 15) & ~15;
*out = mbuf; int32_t aligned_height = (crop_bottom - crop_top + 1 + 15) & ~15;
(*out)->set_range(0, (*out)->size());
(*out)->add_ref(); 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 { } else {
*out = new MediaBuffer(0); *out = new MediaBuffer(0);
err = OK;
} }
// Do _not_ release input buffer yet.
releaseFragment = false;
err = OK;
break; break;
} }
if (res == AVCDEC_PICTURE_READY || res == AVCDEC_SUCCESS) { case AVC_NALTYPE_PPS:
{
mPPSSeen = true;
res = PVAVCDecPicParamSet(
mHandle, const_cast<uint8_t *>(fragPtr),
fragSize);
if (res != AVCDEC_SUCCESS) {
break;
}
*out = new MediaBuffer(0); *out = new MediaBuffer(0);
err = OK; err = OK;
} else {
LOGV("failed to decode frame (res = %d)", res);
}
break;
}
case AVC_NALTYPE_SEI:
{
res = PVAVCDecSEI(
mHandle, const_cast<uint8_t *>(fragPtr),
fragSize);
if (res != AVCDEC_SUCCESS) {
break; break;
} }
*out = new MediaBuffer(0); case AVC_NALTYPE_SLICE:
case AVC_NALTYPE_IDR:
{
res = PVAVCDecodeSlice(
mHandle, const_cast<uint8_t *>(fragPtr),
fragSize);
err = OK; if (res == AVCDEC_PICTURE_OUTPUT_READY) {
break; 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),
AVCDEC_SUCCESS);
CHECK(index >= 0);
CHECK(index < (int32_t)mFrames.size());
MediaBuffer *mbuf = mFrames.editItemAt(index);
bool skipFrame = false;
if (mTargetTimeUs >= 0) {
int64_t timeUs;
CHECK(mbuf->meta_data()->findInt64(kKeyTime, &timeUs));
CHECK(timeUs <= mTargetTimeUs);
if (timeUs < mTargetTimeUs) {
// We're still waiting for the frame with the matching
// timestamp and we won't return the current one.
skipFrame = true;
LOGV("skipping frame at %lld us", timeUs);
} else {
LOGV("found target frame at %lld us", timeUs);
mTargetTimeUs = -1;
}
}
if (!skipFrame) {
*out = mbuf;
(*out)->set_range(0, (*out)->size());
(*out)->add_ref();
} else {
*out = new MediaBuffer(0);
}
// Do _not_ release input buffer yet.
releaseFragment = false;
err = OK;
break;
}
if (res == AVCDEC_PICTURE_READY || res == AVCDEC_SUCCESS) {
*out = new MediaBuffer(0);
err = OK;
} else {
LOGV("failed to decode frame (res = %d)", res);
}
break;
}
case AVC_NALTYPE_SEI:
{
res = PVAVCDecSEI(
mHandle, const_cast<uint8_t *>(fragPtr),
fragSize);
if (res != AVCDEC_SUCCESS) {
break;
}
*out = new MediaBuffer(0);
err = OK;
break;
}
case AVC_NALTYPE_AUD:
case AVC_NALTYPE_FILL:
{
*out = new MediaBuffer(0);
err = OK;
break;
}
default:
{
LOGE("Should not be here, unknown nalType %d", nalType);
CHECK(!"Should not be here");
break;
}
} }
} else {
// We haven't seen SPS or PPS yet.
case AVC_NALTYPE_AUD: *out = new MediaBuffer(0);
case AVC_NALTYPE_FILL: err = OK;
{
*out = new MediaBuffer(0);
err = OK;
break;
}
default:
{
LOGE("Should not be here, unknown nalType %d", nalType);
CHECK(!"Should not be here");
break;
}
} }
if (releaseFragment) { if (releaseFragment) {

View File

@@ -62,6 +62,9 @@ private:
int64_t mTargetTimeUs; int64_t mTargetTimeUs;
bool mSPSSeen;
bool mPPSSeen;
void addCodecSpecificData(const uint8_t *data, size_t size); void addCodecSpecificData(const uint8_t *data, size_t size);
static int32_t ActivateSPSWrapper( static int32_t ActivateSPSWrapper(