Merge "media: Notify main thread error if encounter failure in track worker thread." into nyc-mr1-dev
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 15d691f..1c39b9c 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -192,6 +192,7 @@
INTERNAL_OPTION_START_TIME, // data is an int64_t
INTERNAL_OPTION_TIME_LAPSE, // data is an int64_t[2]
INTERNAL_OPTION_COLOR_ASPECTS, // data is ColorAspects
+ INTERNAL_OPTION_TIME_OFFSET, // data is an int64_t
};
virtual status_t setInternalOption(
node_id node,
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index 00b2c71..18b1955 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -49,7 +49,7 @@
bool isVideo() const { return mIsVideo; }
sp<IGraphicBufferProducer> getGraphicBufferProducer();
- void setInputBufferTimeOffset(int64_t timeOffsetUs);
+ status_t setInputBufferTimeOffset(int64_t timeOffsetUs);
int64_t getFirstSampleSystemTimeUs();
// MediaSource
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index 8a305de..c4e5df7 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -58,6 +58,7 @@
mDisconnectReplyID(0),
mBuffering(false),
mInPreparationPhase(true),
+ mEOSPending(false),
mSeekGeneration(0),
mEOSTimeoutAudio(0),
mEOSTimeoutVideo(0) {
@@ -200,34 +201,28 @@
status_t finalResult;
if (!source->hasBufferAvailable(&finalResult)) {
if (finalResult == OK) {
- int64_t mediaDurationUs = 0;
- getDuration(&mediaDurationUs);
- sp<AnotherPacketSource> otherSource = getSource(!audio);
- status_t otherFinalResult;
- // If other source already signaled EOS, this source should also signal EOS
- if (otherSource != NULL &&
- !otherSource->hasBufferAvailable(&otherFinalResult) &&
- otherFinalResult == ERROR_END_OF_STREAM) {
- source->signalEOS(ERROR_END_OF_STREAM);
+ // If other source already signaled EOS, this source should also return EOS
+ if (sourceReachedEOS(!audio)) {
return ERROR_END_OF_STREAM;
}
// If this source has detected near end, give it some time to retrieve more
- // data before signaling EOS
+ // data before returning EOS
+ int64_t mediaDurationUs = 0;
+ getDuration(&mediaDurationUs);
if (source->isFinished(mediaDurationUs)) {
int64_t eosTimeout = audio ? mEOSTimeoutAudio : mEOSTimeoutVideo;
if (eosTimeout == 0) {
setEOSTimeout(audio, ALooper::GetNowUs());
} else if ((ALooper::GetNowUs() - eosTimeout) > kNearEOSTimeoutUs) {
setEOSTimeout(audio, 0);
- source->signalEOS(ERROR_END_OF_STREAM);
return ERROR_END_OF_STREAM;
}
return -EWOULDBLOCK;
}
- if (!(otherSource != NULL && otherSource->isFinished(mediaDurationUs))) {
+ if (!sourceNearEOS(!audio)) {
// We should not enter buffering mode
// if any of the sources already have detected EOS.
startBufferingIfNecessary();
@@ -306,6 +301,7 @@
mState = SEEKING;
mHandler->seek(seekTimeUs);
+ mEOSPending = false;
}
void NuPlayer::RTSPSource::schedulePollBuffering() {
@@ -314,10 +310,10 @@
}
void NuPlayer::RTSPSource::checkBuffering(
- bool *prepared, bool *underflow, bool *overflow, bool *startServer) {
+ bool *prepared, bool *underflow, bool *overflow, bool *startServer, bool *finished) {
size_t numTracks = mTracks.size();
- size_t preparedCount, underflowCount, overflowCount, startCount;
- preparedCount = underflowCount = overflowCount = startCount = 0;
+ size_t preparedCount, underflowCount, overflowCount, startCount, finishedCount;
+ preparedCount = underflowCount = overflowCount = startCount = finishedCount = 0;
size_t count = numTracks;
for (size_t i = 0; i < count; ++i) {
@@ -337,6 +333,7 @@
if (src->isFinished(/* duration */ 0)) {
++overflowCount;
+ ++finishedCount;
} else {
if (bufferedDurationUs < kUnderflowMarkUs) {
++underflowCount;
@@ -354,11 +351,12 @@
*underflow = (underflowCount > 0);
*overflow = (overflowCount == numTracks);
*startServer = (startCount > 0);
+ *finished = (finishedCount > 0);
}
void NuPlayer::RTSPSource::onPollBuffering() {
- bool prepared, underflow, overflow, startServer;
- checkBuffering(&prepared, &underflow, &overflow, &startServer);
+ bool prepared, underflow, overflow, startServer, finished;
+ checkBuffering(&prepared, &underflow, &overflow, &startServer, &finished);
if (prepared && mInPreparationPhase) {
mInPreparationPhase = false;
@@ -369,8 +367,11 @@
startBufferingIfNecessary();
}
- if (overflow && mHandler != NULL) {
+ if (haveSufficientDataOnAllTracks()) {
stopBufferingIfNecessary();
+ }
+
+ if (overflow && mHandler != NULL) {
mHandler->pause();
}
@@ -378,9 +379,72 @@
mHandler->resume();
}
+ if (finished && mHandler != NULL) {
+ mHandler->cancelAccessUnitTimeoutCheck();
+ }
+
schedulePollBuffering();
}
+void NuPlayer::RTSPSource::signalSourceEOS(status_t result) {
+ const bool audio = true;
+ const bool video = false;
+
+ sp<AnotherPacketSource> source = getSource(audio);
+ if (source != NULL) {
+ source->signalEOS(result);
+ }
+
+ source = getSource(video);
+ if (source != NULL) {
+ source->signalEOS(result);
+ }
+}
+
+bool NuPlayer::RTSPSource::sourceReachedEOS(bool audio) {
+ sp<AnotherPacketSource> source = getSource(audio);
+ status_t finalResult;
+ return (source != NULL &&
+ !source->hasBufferAvailable(&finalResult) &&
+ finalResult == ERROR_END_OF_STREAM);
+}
+
+bool NuPlayer::RTSPSource::sourceNearEOS(bool audio) {
+ sp<AnotherPacketSource> source = getSource(audio);
+ int64_t mediaDurationUs = 0;
+ getDuration(&mediaDurationUs);
+ return (source != NULL && source->isFinished(mediaDurationUs));
+}
+
+void NuPlayer::RTSPSource::onSignalEOS(const sp<AMessage> &msg) {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+
+ if (generation != mSeekGeneration) {
+ return;
+ }
+
+ if (mEOSPending) {
+ signalSourceEOS(ERROR_END_OF_STREAM);
+ mEOSPending = false;
+ }
+}
+
+void NuPlayer::RTSPSource::postSourceEOSIfNecessary() {
+ const bool audio = true;
+ const bool video = false;
+ // If a source has detected near end, give it some time to retrieve more
+ // data before signaling EOS
+ if (sourceNearEOS(audio) || sourceNearEOS(video)) {
+ if (!mEOSPending) {
+ sp<AMessage> msg = new AMessage(kWhatSignalEOS, this);
+ msg->setInt32("generation", mSeekGeneration);
+ msg->post(kNearEOSTimeoutUs);
+ mEOSPending = true;
+ }
+ }
+}
+
void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
if (msg->what() == kWhatDisconnect) {
sp<AReplyToken> replyID;
@@ -408,6 +472,9 @@
} else if (msg->what() == kWhatPollBuffering) {
onPollBuffering();
return;
+ } else if (msg->what() == kWhatSignalEOS) {
+ onSignalEOS(msg);
+ return;
}
CHECK_EQ(msg->what(), (int)kWhatNotify);
@@ -517,16 +584,10 @@
}
if (err != OK) {
- sp<AnotherPacketSource> source = getSource(false /* audio */);
- if (source != NULL) {
- source->signalEOS(err);
- }
-
- source = getSource(true /* audio */);
- if (source != NULL) {
- source->signalEOS(err);
- }
+ signalSourceEOS(err);
}
+
+ postSourceEOSIfNecessary();
break;
}
@@ -554,6 +615,7 @@
source->queueAccessUnit(accessUnit);
}
+ postSourceEOSIfNecessary();
break;
}
@@ -564,17 +626,7 @@
CHECK_NE(finalResult, (status_t)OK);
if (mTSParser != NULL) {
- sp<AnotherPacketSource> source = getSource(false /* audio */);
- if (source != NULL) {
- source->signalEOS(finalResult);
- }
-
- source = getSource(true /* audio */);
- if (source != NULL) {
- source->signalEOS(finalResult);
- }
-
- return;
+ signalSourceEOS(finalResult);
}
size_t trackIndex;
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index a6a7644..c7834ef 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -64,6 +64,7 @@
kWhatDisconnect = 'disc',
kWhatPerformSeek = 'seek',
kWhatPollBuffering = 'poll',
+ kWhatSignalEOS = 'eos ',
};
enum State {
@@ -106,6 +107,7 @@
Mutex mBufferingLock;
bool mBuffering;
bool mInPreparationPhase;
+ bool mEOSPending;
sp<ALooper> mLooper;
sp<MyHandler> mHandler;
@@ -133,7 +135,12 @@
void performSeek(int64_t seekTimeUs);
void schedulePollBuffering();
- void checkBuffering(bool *prepared, bool *underflow, bool *overflow, bool *startServer);
+ void checkBuffering(
+ bool *prepared,
+ bool *underflow,
+ bool *overflow,
+ bool *startServer,
+ bool *finished);
void onPollBuffering();
bool haveSufficientDataOnAllTracks();
@@ -144,6 +151,13 @@
bool stopBufferingIfNecessary();
void finishSeek(status_t err);
+ void postSourceEOSIfNecessary();
+ void signalSourceEOS(status_t result);
+ void onSignalEOS(const sp<AMessage> &msg);
+
+ bool sourceNearEOS(bool audio);
+ bool sourceReachedEOS(bool audio);
+
DISALLOW_EVIL_CONSTRUCTORS(RTSPSource);
};
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index cfdc341..37fd5a5 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -7473,6 +7473,23 @@
}
}
+ int64_t timeOffsetUs;
+ if (params->findInt64("time-offset-us", &timeOffsetUs)) {
+ status_t err = mOMX->setInternalOption(
+ mNode,
+ kPortIndexInput,
+ IOMX::INTERNAL_OPTION_TIME_OFFSET,
+ &timeOffsetUs,
+ sizeof(timeOffsetUs));
+
+ if (err != OK) {
+ ALOGE("[%s] Unable to set input buffer time offset (err %d)",
+ mComponentName.c_str(),
+ err);
+ return err;
+ }
+ }
+
int64_t skipFramesBeforeUs;
if (params->findInt64("skip-frames-before", &skipFramesBeforeUs)) {
status_t err =
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 311c745..33d624e 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -336,10 +336,10 @@
return NULL;
}
-void MediaCodecSource::setInputBufferTimeOffset(int64_t timeOffsetUs) {
+status_t MediaCodecSource::setInputBufferTimeOffset(int64_t timeOffsetUs) {
sp<AMessage> msg = new AMessage(kWhatSetInputBufferTimeOffset, mReflector);
msg->setInt64("time-offset-us", timeOffsetUs);
- postSynchronouslyAndReturnError(msg);
+ return postSynchronouslyAndReturnError(msg);
}
int64_t MediaCodecSource::getFirstSampleSystemTimeUs() {
@@ -874,9 +874,7 @@
break;
}
}
- // Time offset is not applied at
- // feedEncoderInputBuffer() in surface input case.
- timeUs += mInputBufferTimeOffsetUs;
+ // Timestamp offset is already adjusted in GraphicBufferSource.
// GraphicBufferSource is supposed to discard samples
// queued before start, and offset timeUs by start time
CHECK_GE(timeUs, 0ll);
@@ -1015,10 +1013,18 @@
{
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
-
+ status_t err = OK;
CHECK(msg->findInt64("time-offset-us", &mInputBufferTimeOffsetUs));
+ // Propagate the timestamp offset to GraphicBufferSource.
+ if (mIsVideo) {
+ sp<AMessage> params = new AMessage;
+ params->setInt64("time-offset-us", mInputBufferTimeOffsetUs);
+ err = mEncoder->setParameters(params);
+ }
+
sp<AMessage> response = new AMessage;
+ response->setInt32("err", err);
response->postReply(replyID);
break;
}
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index b111c28..be5067d 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -158,11 +158,14 @@
// TODO: Use Flexible color instead
videoFormat->setInt32("color-format", OMX_COLOR_FormatYUV420Planar);
- // For the thumbnail extraction case, try to allocate single buffer
- // in both input and output ports. NOTE: This request may fail if
- // component requires more than that for decoding.
- videoFormat->setInt32("android._num-input-buffers", 1);
- videoFormat->setInt32("android._num-output-buffers", 1);
+ // For the thumbnail extraction case, try to allocate single buffer in both
+ // input and output ports, if seeking to a sync frame. NOTE: This request may
+ // fail if component requires more than that for decoding.
+ bool isSeekingClosest = (seekMode == MediaSource::ReadOptions::SEEK_CLOSEST);
+ if (!isSeekingClosest) {
+ videoFormat->setInt32("android._num-input-buffers", 1);
+ videoFormat->setInt32("android._num-output-buffers", 1);
+ }
status_t err;
sp<ALooper> looper = new ALooper;
@@ -254,7 +257,6 @@
bool isAvcOrHevc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
|| !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
- bool isSeekingClosest = (seekMode == MediaSource::ReadOptions::SEEK_CLOSEST);
bool firstSample = true;
int64_t targetTimeUs = -1ll;
diff --git a/media/libstagefright/omx/GraphicBufferSource.cpp b/media/libstagefright/omx/GraphicBufferSource.cpp
index 0c8fd67..e025653 100644
--- a/media/libstagefright/omx/GraphicBufferSource.cpp
+++ b/media/libstagefright/omx/GraphicBufferSource.cpp
@@ -145,7 +145,8 @@
mTimePerCaptureUs(-1ll),
mTimePerFrameUs(-1ll),
mPrevCaptureUs(-1ll),
- mPrevFrameUs(-1ll) {
+ mPrevFrameUs(-1ll),
+ mInputBufferTimeOffsetUs(0ll) {
ALOGV("GraphicBufferSource w=%u h=%u c=%u",
bufferWidth, bufferHeight, bufferCount);
@@ -774,6 +775,7 @@
int64_t GraphicBufferSource::getTimestamp(const BufferItem &item) {
int64_t timeUs = item.mTimestamp / 1000;
+ timeUs += mInputBufferTimeOffsetUs;
if (mTimePerCaptureUs > 0ll
&& (mTimePerCaptureUs > 2 * mTimePerFrameUs
@@ -802,35 +804,38 @@
static_cast<long long>(mPrevFrameUs));
return mPrevFrameUs;
- } else if (mMaxTimestampGapUs > 0ll) {
- //TODO: Fix the case when mMaxTimestampGapUs and mTimePerCaptureUs are both set.
-
- /* Cap timestamp gap between adjacent frames to specified max
- *
- * In the scenario of cast mirroring, encoding could be suspended for
- * prolonged periods. Limiting the pts gap to workaround the problem
- * where encoder's rate control logic produces huge frames after a
- * long period of suspension.
- */
-
+ } else {
int64_t originalTimeUs = timeUs;
- if (mPrevOriginalTimeUs >= 0ll) {
- if (originalTimeUs < mPrevOriginalTimeUs) {
+ if (originalTimeUs <= mPrevOriginalTimeUs) {
// Drop the frame if it's going backward in time. Bad timestamp
// could disrupt encoder's rate control completely.
- ALOGW("Dropping frame that's going backward in time");
- return -1;
- }
- int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs;
- timeUs = (timestampGapUs < mMaxTimestampGapUs ?
- timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs;
+ ALOGW("Dropping frame that's going backward in time");
+ return -1;
}
+
+ if (mMaxTimestampGapUs > 0ll) {
+ //TODO: Fix the case when mMaxTimestampGapUs and mTimePerCaptureUs are both set.
+
+ /* Cap timestamp gap between adjacent frames to specified max
+ *
+ * In the scenario of cast mirroring, encoding could be suspended for
+ * prolonged periods. Limiting the pts gap to workaround the problem
+ * where encoder's rate control logic produces huge frames after a
+ * long period of suspension.
+ */
+ if (mPrevOriginalTimeUs >= 0ll) {
+ int64_t timestampGapUs = originalTimeUs - mPrevOriginalTimeUs;
+ timeUs = (timestampGapUs < mMaxTimestampGapUs ?
+ timestampGapUs : mMaxTimestampGapUs) + mPrevModifiedTimeUs;
+ mOriginalTimeUs.add(timeUs, originalTimeUs);
+ ALOGV("IN timestamp: %lld -> %lld",
+ static_cast<long long>(originalTimeUs),
+ static_cast<long long>(timeUs));
+ }
+ }
+
mPrevOriginalTimeUs = originalTimeUs;
mPrevModifiedTimeUs = timeUs;
- mOriginalTimeUs.add(timeUs, originalTimeUs);
- ALOGV("IN timestamp: %lld -> %lld",
- static_cast<long long>(originalTimeUs),
- static_cast<long long>(timeUs));
}
return timeUs;
@@ -1048,6 +1053,18 @@
return OK;
}
+status_t GraphicBufferSource::setInputBufferTimeOffset(int64_t timeOffsetUs) {
+ Mutex::Autolock autoLock(mMutex);
+
+ // timeOffsetUs must be negative for adjustment.
+ if (timeOffsetUs >= 0ll) {
+ return INVALID_OPERATION;
+ }
+
+ mInputBufferTimeOffsetUs = timeOffsetUs;
+ return OK;
+}
+
status_t GraphicBufferSource::setMaxFps(float maxFps) {
Mutex::Autolock autoLock(mMutex);
diff --git a/media/libstagefright/omx/GraphicBufferSource.h b/media/libstagefright/omx/GraphicBufferSource.h
index c8b0e62..30bfddb 100644
--- a/media/libstagefright/omx/GraphicBufferSource.h
+++ b/media/libstagefright/omx/GraphicBufferSource.h
@@ -131,6 +131,10 @@
// of suspension on input.
status_t setMaxTimestampGapUs(int64_t maxGapUs);
+ // Sets the input buffer timestamp offset.
+ // When set, the sample's timestamp will be adjusted with the timeOffsetUs.
+ status_t setInputBufferTimeOffset(int64_t timeOffsetUs);
+
// When set, the max frame rate fed to the encoder will be capped at maxFps.
status_t setMaxFps(float maxFps);
@@ -336,6 +340,8 @@
int64_t mPrevCaptureUs;
int64_t mPrevFrameUs;
+ int64_t mInputBufferTimeOffsetUs;
+
MetadataBufferType mMetadataBufferType;
ColorAspects mColorAspects;
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 4f1a952..4908062 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -1445,6 +1445,7 @@
case IOMX::INTERNAL_OPTION_MAX_FPS: return "MAX_FPS";
case IOMX::INTERNAL_OPTION_START_TIME: return "START_TIME";
case IOMX::INTERNAL_OPTION_TIME_LAPSE: return "TIME_LAPSE";
+ case IOMX::INTERNAL_OPTION_TIME_OFFSET: return "TIME_OFFSET";
default: return def;
}
}
@@ -1473,6 +1474,7 @@
case IOMX::INTERNAL_OPTION_MAX_FPS:
case IOMX::INTERNAL_OPTION_START_TIME:
case IOMX::INTERNAL_OPTION_TIME_LAPSE:
+ case IOMX::INTERNAL_OPTION_TIME_OFFSET:
case IOMX::INTERNAL_OPTION_COLOR_ASPECTS:
{
const sp<GraphicBufferSource> &bufferSource =
@@ -1499,6 +1501,13 @@
CLOG_CONFIG(setInternalOption, "delayUs=%lld", (long long)delayUs);
return bufferSource->setRepeatPreviousFrameDelayUs(delayUs);
+ } else if (type == IOMX::INTERNAL_OPTION_TIME_OFFSET) {
+ int64_t timeOffsetUs;
+ if (!getInternalOption(data, size, &timeOffsetUs)) {
+ return INVALID_OPERATION;
+ }
+ CLOG_CONFIG(setInternalOption, "bufferOffsetUs=%lld", (long long)timeOffsetUs);
+ return bufferSource->setInputBufferTimeOffset(timeOffsetUs);
} else if (type == IOMX::INTERNAL_OPTION_MAX_TIMESTAMP_GAP) {
int64_t maxGapUs;
if (!getInternalOption(data, size, &maxGapUs)) {
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 42a1182..845131a 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -1408,6 +1408,11 @@
msg->post((mKeepAliveTimeoutUs * 9) / 10);
}
+ void cancelAccessUnitTimeoutCheck() {
+ ALOGV("cancelAccessUnitTimeoutCheck");
+ ++mCheckGeneration;
+ }
+
void postAccessUnitTimeoutCheck() {
if (mCheckPending) {
return;
@@ -1792,14 +1797,8 @@
// Time is now established, lets start timestamping immediately
for (size_t i = 0; i < mTracks.size(); ++i) {
- TrackInfo *trackInfo = &mTracks.editItemAt(i);
- while (!trackInfo->mPackets.empty()) {
- sp<ABuffer> accessUnit = *trackInfo->mPackets.begin();
- trackInfo->mPackets.erase(trackInfo->mPackets.begin());
-
- if (addMediaTimestamp(i, trackInfo, accessUnit)) {
- postQueueAccessUnit(i, accessUnit);
- }
+ if (OK != processAccessUnitQueue(i)) {
+ return;
}
}
for (size_t i = 0; i < mTracks.size(); ++i) {
@@ -1812,26 +1811,8 @@
}
}
- void onAccessUnitComplete(
- int32_t trackIndex, const sp<ABuffer> &accessUnit) {
- ALOGV("onAccessUnitComplete track %d", trackIndex);
-
+ status_t processAccessUnitQueue(int32_t trackIndex) {
TrackInfo *track = &mTracks.editItemAt(trackIndex);
- if(!mPlayResponseParsed){
- uint32_t seqNum = (uint32_t)accessUnit->int32Data();
- ALOGI("play response is not parsed, storing accessunit %u", seqNum);
- track->mPackets.push_back(accessUnit);
- return;
- }
-
- handleFirstAccessUnit();
-
- if (!mAllTracksHaveTime) {
- ALOGV("storing accessUnit, no time established yet");
- track->mPackets.push_back(accessUnit);
- return;
- }
-
while (!track->mPackets.empty()) {
sp<ABuffer> accessUnit = *track->mPackets.begin();
track->mPackets.erase(track->mPackets.begin());
@@ -1862,7 +1843,7 @@
"Still no first rtp packet after %d stale ones",
kMaxAllowedStaleAccessUnits);
track->mAllowedStaleAccessUnits = -1;
- return;
+ return UNKNOWN_ERROR;
}
// Now found the first rtp packet of the stream after seeking.
@@ -1876,14 +1857,35 @@
continue;
}
-
if (addMediaTimestamp(trackIndex, track, accessUnit)) {
postQueueAccessUnit(trackIndex, accessUnit);
}
}
+ return OK;
+ }
- if (addMediaTimestamp(trackIndex, track, accessUnit)) {
- postQueueAccessUnit(trackIndex, accessUnit);
+ void onAccessUnitComplete(
+ int32_t trackIndex, const sp<ABuffer> &accessUnit) {
+ TrackInfo *track = &mTracks.editItemAt(trackIndex);
+ track->mPackets.push_back(accessUnit);
+
+ uint32_t seqNum = (uint32_t)accessUnit->int32Data();
+ ALOGV("onAccessUnitComplete track %d storing accessunit %u", trackIndex, seqNum);
+
+ if(!mPlayResponseParsed){
+ ALOGV("play response is not parsed");
+ return;
+ }
+
+ handleFirstAccessUnit();
+
+ if (!mAllTracksHaveTime) {
+ ALOGV("storing accessUnit, no time established yet");
+ return;
+ }
+
+ if (OK != processAccessUnitQueue(trackIndex)) {
+ return;
}
if (track->mEOSReceived) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index b752541..1ddfb4d 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1321,9 +1321,11 @@
desc->isActive() &&
outputDesc->sharesHwModuleWith(desc) &&
(newDevice != desc->device())) {
+ audio_devices_t newDevice2 = getNewOutputDevice(desc, false /*fromCache*/);
+ bool force = desc->device() != newDevice2;
setOutputDevice(desc,
- getNewOutputDevice(desc, false /*fromCache*/),
- true,
+ newDevice2,
+ force,
outputDesc->latency()*2);
}
}