Merge "NuPlayer: Fix decoder error handling" into lmp-dev
diff --git a/media/libmediaplayerservice/VideoFrameScheduler.cpp b/media/libmediaplayerservice/VideoFrameScheduler.cpp
index 4251c4e..1a5f3e0 100644
--- a/media/libmediaplayerservice/VideoFrameScheduler.cpp
+++ b/media/libmediaplayerservice/VideoFrameScheduler.cpp
@@ -152,7 +152,7 @@
#endif
-void VideoFrameScheduler::PLL::fit(
+bool VideoFrameScheduler::PLL::fit(
nsecs_t phase, nsecs_t period, size_t numSamplesToUse,
int64_t *a, int64_t *b, int64_t *err) {
if (numSamplesToUse > mNumSamples) {
@@ -187,6 +187,10 @@
}
int64_t div = numSamplesToUse * sumXX - sumX * sumX;
+ if (div == 0) {
+ return false;
+ }
+
int64_t a_nom = numSamplesToUse * sumXY - sumX * sumY;
int64_t b_nom = sumXX * sumY - sumX * sumXY;
*a = divRound(a_nom, div);
@@ -198,6 +202,7 @@
(long long)*a, (*a / (float)(1 << kPrecision)),
(long long)*b, (*b / (float)(1 << kPrecision)),
(long long)*err, (*err / (float)(1 << (kPrecision * 2))));
+ return true;
}
void VideoFrameScheduler::PLL::prime(size_t numSamplesToUse) {
@@ -226,7 +231,7 @@
deltas.sort(compare<nsecs_t>);
size_t numDeltas = deltas.size();
if (numDeltas > 1) {
- nsecs_t deltaMinLimit = min(deltas[0] / kMultiplesThresholdDiv, kMinPeriod);
+ nsecs_t deltaMinLimit = max(deltas[0] / kMultiplesThresholdDiv, kMinPeriod);
nsecs_t deltaMaxLimit = deltas[numDeltas / 2] * kMultiplesThresholdDiv;
for (size_t i = numDeltas / 2 + 1; i < numDeltas; ++i) {
if (deltas[i] > deltaMaxLimit) {
@@ -314,8 +319,15 @@
if (doFit) {
int64_t a, b, err;
+ if (!fit(mPhase, mPeriod, kMaxSamplesToEstimatePeriod, &a, &b, &err)) {
+ // samples are not suitable for fitting. this means they are
+ // also not suitable for priming.
+ ALOGV("could not fit - keeping old period:%lld", (long long)mPeriod);
+ return mPeriod;
+ }
+
mRefitAt = time + kRefitRefreshPeriod;
- fit(mPhase, mPeriod, kMaxSamplesToEstimatePeriod, &a, &b, &err);
+
mPhase += (mPeriod * b) >> kPrecision;
mPeriod = (mPeriod * a) >> kPrecision;
ALOGV("new phase:%lld period:%lld", (long long)mPhase, (long long)mPeriod);
diff --git a/media/libmediaplayerservice/VideoFrameScheduler.h b/media/libmediaplayerservice/VideoFrameScheduler.h
index 19f0787..84b27b4 100644
--- a/media/libmediaplayerservice/VideoFrameScheduler.h
+++ b/media/libmediaplayerservice/VideoFrameScheduler.h
@@ -71,7 +71,8 @@
nsecs_t mTimes[kHistorySize];
void test();
- void fit(nsecs_t phase, nsecs_t period, size_t numSamples,
+ // returns whether fit was successful
+ bool fit(nsecs_t phase, nsecs_t period, size_t numSamples,
int64_t *a, int64_t *b, int64_t *err);
void prime(size_t numSamples);
};
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index bd75034..f84decd 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -1198,10 +1198,17 @@
switch (trackType) {
case MEDIA_TRACK_TYPE_VIDEO:
track = &mVideoTrack;
+ if (mIsWidevine) {
+ maxBuffers = 2;
+ }
break;
case MEDIA_TRACK_TYPE_AUDIO:
track = &mAudioTrack;
- maxBuffers = 64;
+ if (mIsWidevine) {
+ maxBuffers = 8;
+ } else {
+ maxBuffers = 64;
+ }
break;
case MEDIA_TRACK_TYPE_SUBTITLE:
track = &mSubtitleTrack;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index ed6f674..1a066b7 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -53,6 +53,10 @@
}
NuPlayer::Decoder::~Decoder() {
+ mDecoderLooper->unregisterHandler(id());
+ mDecoderLooper->stop();
+
+ releaseAndResetMediaBuffers();
}
static
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 3c04859..4589ed1 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -2933,13 +2933,6 @@
image.mNumPlanes = 0;
const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
- // we need stride and slice-height to be non-zero
- if (params.nStride == 0 || params.nSliceHeight == 0) {
- ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
- fmt, fmt, params.nStride, params.nSliceHeight);
- return false;
- }
-
image.mWidth = params.nFrameWidth;
image.mHeight = params.nFrameHeight;
@@ -2952,6 +2945,20 @@
return false;
}
+ // TEMPORARY FIX for some vendors that advertise sliceHeight as 0
+ if (params.nStride != 0 && params.nSliceHeight == 0) {
+ ALOGW("using sliceHeight=%u instead of what codec advertised (=0)",
+ params.nFrameHeight);
+ params.nSliceHeight = params.nFrameHeight;
+ }
+
+ // we need stride and slice-height to be non-zero
+ if (params.nStride == 0 || params.nSliceHeight == 0) {
+ ALOGW("cannot describe color format 0x%x = %d with stride=%u and sliceHeight=%u",
+ fmt, fmt, params.nStride, params.nSliceHeight);
+ return false;
+ }
+
// set-up YUV format
image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
image.mNumPlanes = 3;
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 6c98c52..b56819c 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -589,7 +589,12 @@
if (index < buffers->size()) {
const BufferInfo &info = buffers->itemAt(index);
if (info.mOwnedByClient) {
- *buffer = info.mData;
+ // by the time buffers array is initialized, crypto is set
+ if (portIndex == kPortIndexInput && mCrypto != NULL) {
+ *buffer = info.mEncryptedData;
+ } else {
+ *buffer = info.mData;
+ }
*format = info.mFormat;
}
}
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index be2a873..f469d4d 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -254,6 +254,10 @@
// set mDisconnecting to true, if a fetch returns after
// this, the source will be marked as EOS.
mDisconnecting = true;
+
+ // explicitly signal mCondition so that the pending readAt()
+ // will immediately return
+ mCondition.signal();
}
// explicitly disconnect from the source, to allow any
@@ -325,7 +329,11 @@
Mutex::Autolock autoLock(mLock);
- if (err == ERROR_UNSUPPORTED || err == -EPIPE) {
+ if (mDisconnecting) {
+ mNumRetriesLeft = 0;
+ mFinalStatus = ERROR_END_OF_STREAM;
+ return;
+ } else if (err == ERROR_UNSUPPORTED || err == -EPIPE) {
// These are errors that are not likely to go away even if we
// retry, i.e. the server doesn't support range requests or similar.
mNumRetriesLeft = 0;
@@ -515,10 +523,14 @@
CHECK(mAsyncResult == NULL);
msg->post();
- while (mAsyncResult == NULL) {
+ while (mAsyncResult == NULL && !mDisconnecting) {
mCondition.wait(mLock);
}
+ if (mDisconnecting) {
+ return ERROR_END_OF_STREAM;
+ }
+
int32_t result;
CHECK(mAsyncResult->findInt32("result", &result));
diff --git a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
index 5b2ab84..d98fa80 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/SoftMPEG4.cpp
@@ -295,19 +295,23 @@
ALOGV("disp_width = %d, disp_height = %d, buf_width = %d, buf_height = %d",
disp_width, disp_height, buf_width, buf_height);
- bool cropChanged = false;
- if (mCropWidth != disp_width || mCropHeight != disp_height) {
- mCropLeft = 0;
- mCropTop = 0;
- mCropWidth = disp_width;
- mCropHeight = disp_height;
- cropChanged = true;
+ CropSettingsMode cropSettingsMode = kCropUnSet;
+ if (disp_width != buf_width || disp_height != buf_height) {
+ cropSettingsMode = kCropSet;
+
+ if (mCropWidth != disp_width || mCropHeight != disp_height) {
+ mCropLeft = 0;
+ mCropTop = 0;
+ mCropWidth = disp_width;
+ mCropHeight = disp_height;
+ cropSettingsMode = kCropChanged;
+ }
}
bool portWillReset = false;
const bool fakeStride = true;
SoftVideoDecoderOMXComponent::handlePortSettingsChange(
- &portWillReset, buf_width, buf_height, cropChanged, fakeStride);
+ &portWillReset, buf_width, buf_height, cropSettingsMode, fakeStride);
if (portWillReset) {
if (mMode == MODE_H263) {
PVCleanUpVideoDecoder(mHandle);
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
index cf3c3e3..168208f 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
@@ -160,10 +160,11 @@
H264SwDecInfo decoderInfo;
CHECK(H264SwDecGetInfo(mHandle, &decoderInfo) == H264SWDEC_OK);
- bool cropChanged = handleCropChange(decoderInfo);
+ SoftVideoDecoderOMXComponent::CropSettingsMode cropSettingsMode =
+ handleCropParams(decoderInfo);
handlePortSettingsChange(
&portWillReset, decoderInfo.picWidth, decoderInfo.picHeight,
- cropChanged);
+ cropSettingsMode);
}
} else {
if (portWillReset) {
@@ -209,9 +210,10 @@
}
}
-bool SoftAVC::handleCropChange(const H264SwDecInfo& decInfo) {
+SoftVideoDecoderOMXComponent::CropSettingsMode SoftAVC::handleCropParams(
+ const H264SwDecInfo& decInfo) {
if (!decInfo.croppingFlag) {
- return false;
+ return kCropUnSet;
}
const CropParams& crop = decInfo.cropParams;
@@ -219,14 +221,14 @@
mCropTop == crop.cropTopOffset &&
mCropWidth == crop.cropOutWidth &&
mCropHeight == crop.cropOutHeight) {
- return false;
+ return kCropSet;
}
mCropLeft = crop.cropLeftOffset;
mCropTop = crop.cropTopOffset;
mCropWidth = crop.cropOutWidth;
mCropHeight = crop.cropOutHeight;
- return true;
+ return kCropChanged;
}
void SoftAVC::saveFirstOutputBuffer(int32_t picId, uint8_t *data) {
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
index 253a406..069107d 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
@@ -73,7 +73,7 @@
void drainAllOutputBuffers(bool eos);
void drainOneOutputBuffer(int32_t picId, uint8_t *data);
void saveFirstOutputBuffer(int32_t pidId, uint8_t *data);
- bool handleCropChange(const H264SwDecInfo& decInfo);
+ CropSettingsMode handleCropParams(const H264SwDecInfo& decInfo);
DISALLOW_EVIL_CONSTRUCTORS(SoftAVC);
};
diff --git a/media/libstagefright/data/media_codecs_google_video.xml b/media/libstagefright/data/media_codecs_google_video.xml
index c97be28..1cbef39 100644
--- a/media/libstagefright/data/media_codecs_google_video.xml
+++ b/media/libstagefright/data/media_codecs_google_video.xml
@@ -73,22 +73,22 @@
<Encoders>
<MediaCodec name="OMX.google.h263.encoder" type="video/3gpp">
<!-- profiles and levels: ProfileBaseline : Level45 -->
- <Limit name="size" min="2x2" max="176x144" />
- <Limit name="alignment" value="2x2" />
+ <Limit name="size" min="16x16" max="176x144" />
+ <Limit name="alignment" value="16x16" />
<Limit name="bitrate" range="1-128000" />
</MediaCodec>
<MediaCodec name="OMX.google.h264.encoder" type="video/avc">
<!-- profiles and levels: ProfileBaseline : Level2 -->
- <Limit name="size" min="2x2" max="896x896" />
- <Limit name="alignment" value="2x2" />
+ <Limit name="size" min="16x16" max="896x896" />
+ <Limit name="alignment" value="16x16" />
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="1-11880" />
<Limit name="bitrate" range="1-2000000" />
</MediaCodec>
<MediaCodec name="OMX.google.mpeg4.encoder" type="video/mp4v-es">
<!-- profiles and levels: ProfileCore : Level2 -->
- <Limit name="size" min="2x2" max="176x144" />
- <Limit name="alignment" value="2x2" />
+ <Limit name="size" min="16x16" max="176x144" />
+ <Limit name="alignment" value="16x16" />
<Limit name="block-size" value="16x16" />
<Limit name="blocks-per-second" range="12-1485" />
<Limit name="bitrate" range="1-64000" />
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index a289637..7a9a1a3 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -353,10 +353,6 @@
sp<AMessage> response;
status_t err = msg->postAndAwaitResponse(&response);
- uint32_t replyID;
- CHECK(response == mSeekReply && 0 != mSeekReplyID);
- mSeekReply.clear();
- mSeekReplyID = 0;
return err;
}
@@ -382,12 +378,16 @@
case kWhatSeek:
{
- CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
+ uint32_t seekReplyID;
+ CHECK(msg->senderAwaitsResponse(&seekReplyID));
+ mSeekReplyID = seekReplyID;
+ mSeekReply = new AMessage;
status_t err = onSeek(msg);
- mSeekReply = new AMessage;
- mSeekReply->setInt32("err", err);
+ if (err != OK) {
+ msg->post(50000);
+ }
break;
}
@@ -422,7 +422,10 @@
if (mSeekReplyID != 0) {
CHECK(mSeekReply != NULL);
+ mSeekReply->setInt32("err", OK);
mSeekReply->postReply(mSeekReplyID);
+ mSeekReplyID = 0;
+ mSeekReply.clear();
}
}
}
@@ -1094,10 +1097,11 @@
CHECK(msg->findInt64("timeUs", &timeUs));
if (!mReconfigurationInProgress) {
- changeConfiguration(timeUs, getBandwidthIndex());
+ changeConfiguration(timeUs, mCurBandwidthIndex);
+ return OK;
+ } else {
+ return -EWOULDBLOCK;
}
-
- return OK;
}
status_t LiveSession::getDuration(int64_t *durationUs) const {
@@ -1254,7 +1258,10 @@
if (mSeekReplyID != 0) {
CHECK(mSeekReply != NULL);
+ mSeekReply->setInt32("err", OK);
mSeekReply->postReply(mSeekReplyID);
+ mSeekReplyID = 0;
+ mSeekReply.clear();
}
}
}
diff --git a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
index 37b1fe1..9e97ebd 100644
--- a/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
+++ b/media/libstagefright/include/SoftVideoDecoderOMXComponent.h
@@ -68,9 +68,14 @@
uint32_t outputBufferWidth();
uint32_t outputBufferHeight();
+ enum CropSettingsMode {
+ kCropUnSet = 0,
+ kCropSet,
+ kCropChanged,
+ };
void handlePortSettingsChange(
bool *portWillReset, uint32_t width, uint32_t height,
- bool cropChanged = false, bool fakeStride = false);
+ CropSettingsMode cropSettingsMode = kCropUnSet, bool fakeStride = false);
void copyYV12FrameToOutputBuffer(
uint8_t *dst, const uint8_t *srcY, const uint8_t *srcU, const uint8_t *srcV,
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index 5853469..3d20a79 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -160,15 +160,17 @@
}
void SoftVideoDecoderOMXComponent::handlePortSettingsChange(
- bool *portWillReset, uint32_t width, uint32_t height, bool cropChanged, bool fakeStride) {
+ bool *portWillReset, uint32_t width, uint32_t height,
+ CropSettingsMode cropSettingsMode, bool fakeStride) {
*portWillReset = false;
bool sizeChanged = (width != mWidth || height != mHeight);
+ bool updateCrop = (cropSettingsMode == kCropUnSet);
+ bool cropChanged = (cropSettingsMode == kCropChanged);
if (sizeChanged || cropChanged) {
mWidth = width;
mHeight = height;
- bool updateCrop = !cropChanged;
if ((sizeChanged && !mIsAdaptive)
|| width > mAdaptiveMaxWidth
|| height > mAdaptiveMaxHeight) {
@@ -343,6 +345,40 @@
return OMX_ErrorNone;
}
+ case OMX_IndexParamPortDefinition:
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE *newParams =
+ (OMX_PARAM_PORTDEFINITIONTYPE *)params;
+ OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &newParams->format.video;
+ OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(newParams->nPortIndex)->mDef;
+
+ uint32_t oldWidth = def->format.video.nFrameWidth;
+ uint32_t oldHeight = def->format.video.nFrameHeight;
+ uint32_t newWidth = video_def->nFrameWidth;
+ uint32_t newHeight = video_def->nFrameHeight;
+ if (newWidth != oldWidth || newHeight != oldHeight) {
+ bool outputPort = (newParams->nPortIndex == kOutputPortIndex);
+ def->format.video.nFrameWidth =
+ (mIsAdaptive && outputPort) ? mAdaptiveMaxWidth : newWidth;
+ def->format.video.nFrameHeight =
+ (mIsAdaptive && outputPort) ? mAdaptiveMaxHeight : newHeight;
+ def->format.video.nStride = def->format.video.nFrameWidth;
+ def->format.video.nSliceHeight = def->format.video.nFrameHeight;
+ def->nBufferSize =
+ def->format.video.nFrameWidth * def->format.video.nFrameHeight * 3 / 2;
+ if (outputPort) {
+ mWidth = newWidth;
+ mHeight = newHeight;
+ mCropLeft = 0;
+ mCropTop = 0;
+ mCropWidth = newWidth;
+ mCropHeight = newHeight;
+ }
+ newParams->nBufferSize = def->nBufferSize;
+ }
+ return SimpleSoftOMXComponent::internalSetParameter(index, params);
+ }
+
default:
return SimpleSoftOMXComponent::internalSetParameter(index, params);
}