Merge "audioflinger: fix audio skipping over A2DP" into ics-mr1
diff --git a/include/media/IStreamSource.h b/include/media/IStreamSource.h
index cc63356..19646b0 100644
--- a/include/media/IStreamSource.h
+++ b/include/media/IStreamSource.h
@@ -52,15 +52,20 @@
static const char *const kKeyResumeAtPTS;
// When signalling a discontinuity you can optionally
- // signal that this is a "hard" discontinuity, i.e. the format
- // or configuration of subsequent stream data differs from that
- // currently active. To do so, include a non-zero int32_t value
- // under the key "kKeyFormatChange" when issuing the DISCONTINUITY
+ // specify the type(s) of discontinuity, i.e. if the
+ // audio format has changed, the video format has changed,
+ // time has jumped or any combination thereof.
+ // To do so, include a non-zero int32_t value
+ // under the key "kKeyDiscontinuityMask" when issuing the DISCONTINUITY
// command.
- // The new logical stream must start with proper codec initialization
+ // If there is a change in audio/video format, The new logical stream
+ // must start with proper codec initialization
// information for playback to continue, i.e. SPS and PPS in the case
// of AVC video etc.
- static const char *const kKeyFormatChange;
+ // If this key is not present, only a time discontinuity is assumed.
+ // The value should be a bitmask of values from
+ // ATSParser::DiscontinuityType.
+ static const char *const kKeyDiscontinuityMask;
virtual void issueCommand(
Command cmd, bool synchronous, const sp<AMessage> &msg = NULL) = 0;
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 5822877..3963d9c 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -166,6 +166,8 @@
bool allYourBuffersAreBelongToUs();
+ size_t countBuffersOwnedByComponent(OMX_U32 portIndex) const;
+
void deferMessage(const sp<AMessage> &msg);
void processDeferredMessages();
diff --git a/media/libmedia/IStreamSource.cpp b/media/libmedia/IStreamSource.cpp
index b311f35..078be94 100644
--- a/media/libmedia/IStreamSource.cpp
+++ b/media/libmedia/IStreamSource.cpp
@@ -30,7 +30,7 @@
const char *const IStreamListener::kKeyResumeAtPTS = "resume-at-PTS";
// static
-const char *const IStreamListener::kKeyFormatChange = "format-change";
+const char *const IStreamListener::kKeyDiscontinuityMask = "discontinuity-mask";
enum {
// IStreamSource
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 2a5c0a6..93ab704 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -54,6 +54,7 @@
mVideoEOS(false),
mScanSourcesPending(false),
mScanSourcesGeneration(0),
+ mTimeDiscontinuityPending(false),
mFlushingAudio(NONE),
mFlushingVideo(NONE),
mResetInProgress(false),
@@ -462,11 +463,24 @@
{
LOGV("kWhatReset");
+ if (mRenderer != NULL) {
+ // There's an edge case where the renderer owns all output
+ // buffers and is paused, therefore the decoder will not read
+ // more input data and will never encounter the matching
+ // discontinuity. To avoid this, we resume the renderer.
+
+ if (mFlushingAudio == AWAITING_DISCONTINUITY
+ || mFlushingVideo == AWAITING_DISCONTINUITY) {
+ mRenderer->resume();
+ }
+ }
+
if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
// We're currently flushing, postpone the reset until that's
// completed.
- LOGV("postponing reset");
+ LOGV("postponing reset mFlushingAudio=%d, mFlushingVideo=%d",
+ mFlushingAudio, mFlushingVideo);
mResetPostponed = true;
break;
@@ -477,6 +491,8 @@
break;
}
+ mTimeDiscontinuityPending = true;
+
if (mAudioDecoder != NULL) {
flushDecoder(true /* audio */, true /* needShutdown */);
}
@@ -540,7 +556,10 @@
LOGV("both audio and video are flushed now.");
- mRenderer->signalTimeDiscontinuity();
+ if (mTimeDiscontinuityPending) {
+ mRenderer->signalTimeDiscontinuity();
+ mTimeDiscontinuityPending = false;
+ }
if (mAudioDecoder != NULL) {
mAudioDecoder->signalResume();
@@ -663,10 +682,15 @@
CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
bool formatChange =
- type == ATSParser::DISCONTINUITY_FORMATCHANGE;
+ (audio &&
+ (type & ATSParser::DISCONTINUITY_AUDIO_FORMAT))
+ || (!audio &&
+ (type & ATSParser::DISCONTINUITY_VIDEO_FORMAT));
- LOGV("%s discontinuity (formatChange=%d)",
- audio ? "audio" : "video", formatChange);
+ bool timeChange = (type & ATSParser::DISCONTINUITY_TIME) != 0;
+
+ LOGI("%s discontinuity (formatChange=%d, time=%d)",
+ audio ? "audio" : "video", formatChange, timeChange);
if (audio) {
mSkipRenderingAudioUntilMediaTimeUs = -1;
@@ -674,26 +698,45 @@
mSkipRenderingVideoUntilMediaTimeUs = -1;
}
- sp<AMessage> extra;
- if (accessUnit->meta()->findMessage("extra", &extra)
- && extra != NULL) {
- int64_t resumeAtMediaTimeUs;
- if (extra->findInt64(
- "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
- LOGI("suppressing rendering of %s until %lld us",
- audio ? "audio" : "video", resumeAtMediaTimeUs);
+ if (timeChange) {
+ sp<AMessage> extra;
+ if (accessUnit->meta()->findMessage("extra", &extra)
+ && extra != NULL) {
+ int64_t resumeAtMediaTimeUs;
+ if (extra->findInt64(
+ "resume-at-mediatimeUs", &resumeAtMediaTimeUs)) {
+ LOGI("suppressing rendering of %s until %lld us",
+ audio ? "audio" : "video", resumeAtMediaTimeUs);
- if (audio) {
- mSkipRenderingAudioUntilMediaTimeUs =
- resumeAtMediaTimeUs;
- } else {
- mSkipRenderingVideoUntilMediaTimeUs =
- resumeAtMediaTimeUs;
+ if (audio) {
+ mSkipRenderingAudioUntilMediaTimeUs =
+ resumeAtMediaTimeUs;
+ } else {
+ mSkipRenderingVideoUntilMediaTimeUs =
+ resumeAtMediaTimeUs;
+ }
}
}
}
- flushDecoder(audio, formatChange);
+ mTimeDiscontinuityPending =
+ mTimeDiscontinuityPending || timeChange;
+
+ if (formatChange || timeChange) {
+ flushDecoder(audio, formatChange);
+ } else {
+ // This stream is unaffected by the discontinuity
+
+ if (audio) {
+ mFlushingAudio = FLUSHED;
+ } else {
+ mFlushingVideo = FLUSHED;
+ }
+
+ finishFlushIfPossible();
+
+ return -EWOULDBLOCK;
+ }
}
reply->setInt32("err", err);
@@ -794,6 +837,11 @@
}
void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
+ if ((audio && mAudioDecoder == NULL) || (!audio && mVideoDecoder == NULL)) {
+ LOGI("flushDecoder %s without decoder present",
+ audio ? "audio" : "video");
+ }
+
// Make sure we don't continue to scan sources until we finish flushing.
++mScanSourcesGeneration;
mScanSourcesPending = false;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index f23deea..ffc710e 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -112,6 +112,10 @@
SHUT_DOWN,
};
+ // Once the current flush is complete this indicates whether the
+ // notion of time has changed.
+ bool mTimeDiscontinuityPending;
+
FlushStatus mFlushingAudio;
FlushStatus mFlushingVideo;
bool mResetInProgress;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 640e9fa..0cb7f45 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -628,11 +628,16 @@
mAudioSink->pause();
}
+ LOGV("now paused audio queue has %d entries, video has %d entries",
+ mAudioQueue.size(), mVideoQueue.size());
+
mPaused = true;
}
void NuPlayer::Renderer::onResume() {
- CHECK(mPaused);
+ if (!mPaused) {
+ return;
+ }
if (mHasAudio) {
mAudioSink->start();
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
index f795654..2e63b3b 100644
--- a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -63,17 +63,22 @@
mFinalResult = ERROR_END_OF_STREAM;
break;
} else if (n == INFO_DISCONTINUITY) {
- ATSParser::DiscontinuityType type = ATSParser::DISCONTINUITY_SEEK;
+ int32_t type = ATSParser::DISCONTINUITY_SEEK;
- int32_t formatChange;
+ int32_t mask;
if (extra != NULL
&& extra->findInt32(
- IStreamListener::kKeyFormatChange, &formatChange)
- && formatChange != 0) {
- type = ATSParser::DISCONTINUITY_FORMATCHANGE;
+ IStreamListener::kKeyDiscontinuityMask, &mask)) {
+ if (mask == 0) {
+ LOGE("Client specified an illegal discontinuity type.");
+ return ERROR_UNSUPPORTED;
+ }
+
+ type = mask;
}
- mTSParser->signalDiscontinuity(type, extra);
+ mTSParser->signalDiscontinuity(
+ (ATSParser::DiscontinuityType)type, extra);
} else if (n < 0) {
CHECK_EQ(n, -EWOULDBLOCK);
break;
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index d947760..dbc9b7e 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -342,6 +342,7 @@
}
void ACodec::signalFlush() {
+ LOGV("[%s] signalFlush", mComponentName.c_str());
(new AMessage(kWhatFlush, id()))->post();
}
@@ -1092,6 +1093,20 @@
return OK;
}
+size_t ACodec::countBuffersOwnedByComponent(OMX_U32 portIndex) const {
+ size_t n = 0;
+
+ for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
+ const BufferInfo &info = mBuffers[portIndex].itemAt(i);
+
+ if (info.mStatus == BufferInfo::OWNED_BY_COMPONENT) {
+ ++n;
+ }
+ }
+
+ return n;
+}
+
bool ACodec::allYourBuffersAreBelongToUs(
OMX_U32 portIndex) {
for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
@@ -2041,6 +2056,14 @@
case kWhatFlush:
{
+ LOGV("[%s] ExecutingState flushing now "
+ "(codec owns %d/%d input, %d/%d output).",
+ mCodec->mComponentName.c_str(),
+ mCodec->countBuffersOwnedByComponent(kPortIndexInput),
+ mCodec->mBuffers[kPortIndexInput].size(),
+ mCodec->countBuffersOwnedByComponent(kPortIndexOutput),
+ mCodec->mBuffers[kPortIndexOutput].size());
+
mActive = false;
CHECK_EQ(mCodec->mOMX->sendCommand(
@@ -2180,6 +2203,12 @@
err);
mCodec->signalError();
+
+ // This is technically not correct, since we were unable
+ // to allocate output buffers and therefore the output port
+ // remains disabled. It is necessary however to allow us
+ // to shutdown the codec properly.
+ mCodec->changeState(mCodec->mExecutingState);
}
return true;
@@ -2408,6 +2437,9 @@
bool ACodec::FlushingState::onOMXEvent(
OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
+ LOGV("[%s] FlushingState onOMXEvent(%d,%ld)",
+ mCodec->mComponentName.c_str(), event, data1);
+
switch (event) {
case OMX_EventCmdComplete:
{
diff --git a/media/libstagefright/AVIExtractor.cpp b/media/libstagefright/AVIExtractor.cpp
index 0be2ca4..815f987 100644
--- a/media/libstagefright/AVIExtractor.cpp
+++ b/media/libstagefright/AVIExtractor.cpp
@@ -1094,7 +1094,7 @@
CHECK(meta->findData(kKeyAVCC, &type, &csd, &csdSize));
track->mMeta->setInt32(kKeyWidth, width);
- track->mMeta->setInt32(kKeyHeight, width);
+ track->mMeta->setInt32(kKeyHeight, height);
track->mMeta->setData(kKeyAVCC, type, csd, csdSize);
return OK;
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index f6d054d..18dd8ef 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1949,6 +1949,8 @@
mUri = newURI;
}
+ AString sniffedMIME;
+
if (!strncasecmp("http://", mUri.string(), 7)
|| !strncasecmp("https://", mUri.string(), 8)
|| isWidevineStreaming) {
@@ -1998,7 +2000,6 @@
mConnectingDataSource.clear();
-
String8 contentType = dataSource->getMIMEType();
if (strncasecmp(contentType.string(), "audio/", 6)) {
@@ -2020,16 +2021,51 @@
mLock.unlock();
+ // Initially make sure we have at least 128 bytes for the sniff
+ // to complete without blocking.
+ static const size_t kMinBytesForSniffing = 128;
+
+ off64_t metaDataSize = -1ll;
for (;;) {
status_t finalStatus;
size_t cachedDataRemaining =
mCachedSource->approxDataRemaining(&finalStatus);
- if (finalStatus != OK || cachedDataRemaining >= kHighWaterMarkBytes
+ if (finalStatus != OK
+ || (metaDataSize >= 0
+ && cachedDataRemaining >= metaDataSize)
|| (mFlags & PREPARE_CANCELLED)) {
break;
}
+ LOGV("now cached %d bytes of data", cachedDataRemaining);
+
+ if (metaDataSize < 0
+ && cachedDataRemaining >= kMinBytesForSniffing) {
+ String8 tmp;
+ float confidence;
+ sp<AMessage> meta;
+ if (!dataSource->sniff(&tmp, &confidence, &meta)) {
+ mLock.lock();
+ return UNKNOWN_ERROR;
+ }
+
+ // We successfully identified the file's extractor to
+ // be, remember this mime type so we don't have to
+ // sniff it again when we call MediaExtractor::Create()
+ // below.
+ sniffedMIME = tmp.string();
+
+ if (meta == NULL
+ || !meta->findInt64(
+ "meta-data-size", &metaDataSize)) {
+ metaDataSize = kHighWaterMarkBytes;
+ }
+
+ CHECK_GE(metaDataSize, 0ll);
+ LOGV("metaDataSize = %lld bytes", metaDataSize);
+ }
+
usleep(200000);
}
@@ -2067,7 +2103,8 @@
mWVMExtractor->setAdaptiveStreamingMode(true);
extractor = mWVMExtractor;
} else {
- extractor = MediaExtractor::Create(dataSource);
+ extractor = MediaExtractor::Create(
+ dataSource, sniffedMIME.empty() ? NULL : sniffedMIME.c_str());
if (extractor == NULL) {
return UNKNOWN_ERROR;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 1ebf0a8..f6b06c7 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -30,6 +30,7 @@
#include <string.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
@@ -2301,51 +2302,121 @@
// Attempt to actually parse the 'ftyp' atom and determine if a suitable
// compatible brand is present.
+// Also try to identify where this file's metadata ends
+// (end of the 'moov' atom) and report it to the caller as part of
+// the metadata.
static bool BetterSniffMPEG4(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
- uint8_t header[12];
- if (source->readAt(0, header, 12) != 12
- || memcmp("ftyp", &header[4], 4)) {
- return false;
- }
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *meta) {
+ // We scan up to 128 bytes to identify this file as an MP4.
+ static const off64_t kMaxScanOffset = 128ll;
- size_t atomSize = U32_AT(&header[0]);
- if (atomSize < 16 || (atomSize % 4) != 0) {
- return false;
- }
+ off64_t offset = 0ll;
+ bool foundGoodFileType = false;
+ off64_t moovAtomEndOffset = -1ll;
+ bool done = false;
- bool success = false;
- if (isCompatibleBrand(U32_AT(&header[8]))) {
- success = true;
- } else {
- size_t numCompatibleBrands = (atomSize - 16) / 4;
- for (size_t i = 0; i < numCompatibleBrands; ++i) {
- uint8_t tmp[4];
- if (source->readAt(16 + i * 4, tmp, 4) != 4) {
+ while (!done && offset < kMaxScanOffset) {
+ uint32_t hdr[2];
+ if (source->readAt(offset, hdr, 8) < 8) {
+ return false;
+ }
+
+ uint64_t chunkSize = ntohl(hdr[0]);
+ uint32_t chunkType = ntohl(hdr[1]);
+ off64_t chunkDataOffset = offset + 8;
+
+ if (chunkSize == 1) {
+ if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
return false;
}
- if (isCompatibleBrand(U32_AT(&tmp[0]))) {
- success = true;
+ chunkSize = ntoh64(chunkSize);
+ chunkDataOffset += 8;
+
+ if (chunkSize < 16) {
+ // The smallest valid chunk is 16 bytes long in this case.
+ return false;
+ }
+ } else if (chunkSize < 8) {
+ // The smallest valid chunk is 8 bytes long.
+ return false;
+ }
+
+ off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
+
+ switch (chunkType) {
+ case FOURCC('f', 't', 'y', 'p'):
+ {
+ if (chunkDataSize < 8) {
+ return false;
+ }
+
+ uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
+ for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
+ if (i == 1) {
+ // Skip this index, it refers to the minorVersion,
+ // not a brand.
+ continue;
+ }
+
+ uint32_t brand;
+ if (source->readAt(
+ chunkDataOffset + 4 * i, &brand, 4) < 4) {
+ return false;
+ }
+
+ brand = ntohl(brand);
+
+ if (isCompatibleBrand(brand)) {
+ foundGoodFileType = true;
+ break;
+ }
+ }
+
+ if (!foundGoodFileType) {
+ return false;
+ }
+
break;
}
+
+ case FOURCC('m', 'o', 'o', 'v'):
+ {
+ moovAtomEndOffset = offset + chunkSize;
+
+ done = true;
+ break;
+ }
+
+ default:
+ break;
}
+
+ offset += chunkSize;
}
- if (!success) {
+ if (!foundGoodFileType) {
return false;
}
*mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
*confidence = 0.4f;
+ if (moovAtomEndOffset >= 0) {
+ *meta = new AMessage;
+ (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
+
+ LOGV("found metadata size: %lld", moovAtomEndOffset);
+ }
+
return true;
}
bool SniffMPEG4(
const sp<DataSource> &source, String8 *mimeType, float *confidence,
- sp<AMessage> *) {
- if (BetterSniffMPEG4(source, mimeType, confidence)) {
+ sp<AMessage> *meta) {
+ if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
return true;
}
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index ebad321..69d1785 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -631,14 +631,7 @@
--left;
}
- uint32_t x;
- if (mDataSource->readAt(
- mSyncSampleOffset + 8 + left * 4, &x, 4) != 4) {
- return ERROR_IO;
- }
-
- x = ntohl(x);
- --x;
+ uint32_t x = mSyncSamples[left];
if (left + 1 < mNumSyncSamples) {
uint32_t y = mSyncSamples[left + 1];
@@ -679,13 +672,7 @@
if (x > start_sample_index) {
CHECK(left > 0);
- if (mDataSource->readAt(
- mSyncSampleOffset + 8 + (left - 1) * 4, &x, 4) != 4) {
- return ERROR_IO;
- }
-
- x = ntohl(x);
- --x;
+ x = mSyncSamples[left - 1];
CHECK(x <= start_sample_index);
}
diff --git a/media/libstagefright/SurfaceMediaSource.cpp b/media/libstagefright/SurfaceMediaSource.cpp
index 2b27ee2..86b33d1 100644
--- a/media/libstagefright/SurfaceMediaSource.cpp
+++ b/media/libstagefright/SurfaceMediaSource.cpp
@@ -336,7 +336,7 @@
(uint32_t(buffer->height) != h) ||
(uint32_t(buffer->format) != format) ||
((uint32_t(buffer->usage) & usage) != usage)) {
- usage |= GraphicBuffer::USAGE_HW_TEXTURE;
+ usage |= GraphicBuffer::USAGE_HW_VIDEO_ENCODER;
status_t error;
sp<GraphicBuffer> graphicBuffer(
mGraphicBufferAlloc->createGraphicBuffer(
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 72f1282..6cec63a 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -123,6 +123,9 @@
void extractAACFrames(const sp<ABuffer> &buffer);
+ bool isAudio() const;
+ bool isVideo() const;
+
DISALLOW_EVIL_CONSTRUCTORS(Stream);
};
@@ -401,7 +404,7 @@
case STREAMTYPE_H264:
mQueue = new ElementaryStreamQueue(ElementaryStreamQueue::H264);
break;
- case STREAMTYPE_MPEG2_AUDIO_ATDS:
+ case STREAMTYPE_MPEG2_AUDIO_ADTS:
mQueue = new ElementaryStreamQueue(ElementaryStreamQueue::AAC);
break;
case STREAMTYPE_MPEG1_AUDIO:
@@ -486,6 +489,31 @@
return OK;
}
+bool ATSParser::Stream::isVideo() const {
+ switch (mStreamType) {
+ case STREAMTYPE_H264:
+ case STREAMTYPE_MPEG1_VIDEO:
+ case STREAMTYPE_MPEG2_VIDEO:
+ case STREAMTYPE_MPEG4_VIDEO:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ATSParser::Stream::isAudio() const {
+ switch (mStreamType) {
+ case STREAMTYPE_MPEG1_AUDIO:
+ case STREAMTYPE_MPEG2_AUDIO:
+ case STREAMTYPE_MPEG2_AUDIO_ADTS:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
void ATSParser::Stream::signalDiscontinuity(
DiscontinuityType type, const sp<AMessage> &extra) {
if (mQueue == NULL) {
@@ -495,34 +523,34 @@
mPayloadStarted = false;
mBuffer->setRange(0, 0);
- switch (type) {
- case DISCONTINUITY_SEEK:
- case DISCONTINUITY_FORMATCHANGE:
- {
- bool isASeek = (type == DISCONTINUITY_SEEK);
-
- mQueue->clear(!isASeek);
-
- uint64_t resumeAtPTS;
- if (extra != NULL
- && extra->findInt64(
- IStreamListener::kKeyResumeAtPTS,
- (int64_t *)&resumeAtPTS)) {
- int64_t resumeAtMediaTimeUs =
- mProgram->convertPTSToTimestamp(resumeAtPTS);
-
- extra->setInt64("resume-at-mediatimeUs", resumeAtMediaTimeUs);
- }
-
- if (mSource != NULL) {
- mSource->queueDiscontinuity(type, extra);
- }
- break;
+ bool clearFormat = false;
+ if (isAudio()) {
+ if (type & DISCONTINUITY_AUDIO_FORMAT) {
+ clearFormat = true;
}
+ } else {
+ if (type & DISCONTINUITY_VIDEO_FORMAT) {
+ clearFormat = true;
+ }
+ }
- default:
- TRESPASS();
- break;
+ mQueue->clear(clearFormat);
+
+ if (type & DISCONTINUITY_TIME) {
+ uint64_t resumeAtPTS;
+ if (extra != NULL
+ && extra->findInt64(
+ IStreamListener::kKeyResumeAtPTS,
+ (int64_t *)&resumeAtPTS)) {
+ int64_t resumeAtMediaTimeUs =
+ mProgram->convertPTSToTimestamp(resumeAtPTS);
+
+ extra->setInt64("resume-at-mediatimeUs", resumeAtMediaTimeUs);
+ }
+ }
+
+ if (mSource != NULL) {
+ mSource->queueDiscontinuity(type, extra);
}
}
@@ -764,10 +792,7 @@
switch (type) {
case VIDEO:
{
- if (mStreamType == STREAMTYPE_H264
- || mStreamType == STREAMTYPE_MPEG1_VIDEO
- || mStreamType == STREAMTYPE_MPEG2_VIDEO
- || mStreamType == STREAMTYPE_MPEG4_VIDEO) {
+ if (isVideo()) {
return mSource;
}
break;
@@ -775,9 +800,7 @@
case AUDIO:
{
- if (mStreamType == STREAMTYPE_MPEG1_AUDIO
- || mStreamType == STREAMTYPE_MPEG2_AUDIO
- || mStreamType == STREAMTYPE_MPEG2_AUDIO_ATDS) {
+ if (isAudio()) {
return mSource;
}
break;
diff --git a/media/libstagefright/mpeg2ts/ATSParser.h b/media/libstagefright/mpeg2ts/ATSParser.h
index 878e534..c8038d1 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.h
+++ b/media/libstagefright/mpeg2ts/ATSParser.h
@@ -33,9 +33,18 @@
struct ATSParser : public RefBase {
enum DiscontinuityType {
- DISCONTINUITY_NONE,
- DISCONTINUITY_SEEK,
- DISCONTINUITY_FORMATCHANGE
+ DISCONTINUITY_NONE = 0,
+ DISCONTINUITY_TIME = 1,
+ DISCONTINUITY_AUDIO_FORMAT = 2,
+ DISCONTINUITY_VIDEO_FORMAT = 4,
+
+ DISCONTINUITY_SEEK = DISCONTINUITY_TIME,
+
+ // For legacy reasons this also implies a time discontinuity.
+ DISCONTINUITY_FORMATCHANGE =
+ DISCONTINUITY_AUDIO_FORMAT
+ | DISCONTINUITY_VIDEO_FORMAT
+ | DISCONTINUITY_TIME,
};
enum Flags {
@@ -71,7 +80,7 @@
STREAMTYPE_MPEG2_VIDEO = 0x02,
STREAMTYPE_MPEG1_AUDIO = 0x03,
STREAMTYPE_MPEG2_AUDIO = 0x04,
- STREAMTYPE_MPEG2_AUDIO_ATDS = 0x0f,
+ STREAMTYPE_MPEG2_AUDIO_ADTS = 0x0f,
STREAMTYPE_MPEG4_VIDEO = 0x10,
STREAMTYPE_H264 = 0x1b,
};
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index ce07e32..f782ce5 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -29,8 +29,17 @@
namespace android {
AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
- : mFormat(meta),
+ : mIsAudio(false),
+ mFormat(meta),
mEOSResult(OK) {
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (!strncasecmp("audio/", mime, 6)) {
+ mIsAudio = true;
+ } else {
+ CHECK(!strncasecmp("video/", mime, 6));
+ }
}
void AnotherPacketSource::setFormat(const sp<MetaData> &meta) {
@@ -67,8 +76,7 @@
int32_t discontinuity;
if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)) {
-
- if (discontinuity == ATSParser::DISCONTINUITY_FORMATCHANGE) {
+ if (wasFormatChange(discontinuity)) {
mFormat.clear();
}
@@ -96,7 +104,7 @@
int32_t discontinuity;
if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
- if (discontinuity == ATSParser::DISCONTINUITY_FORMATCHANGE) {
+ if (wasFormatChange(discontinuity)) {
mFormat.clear();
}
@@ -117,6 +125,15 @@
return mEOSResult;
}
+bool AnotherPacketSource::wasFormatChange(
+ int32_t discontinuityType) const {
+ if (mIsAudio) {
+ return (discontinuityType & ATSParser::DISCONTINUITY_AUDIO_FORMAT) != 0;
+ }
+
+ return (discontinuityType & ATSParser::DISCONTINUITY_VIDEO_FORMAT) != 0;
+}
+
void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
int32_t damaged;
if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
index 439c785..c99f7f2 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -61,10 +61,13 @@
Mutex mLock;
Condition mCondition;
+ bool mIsAudio;
sp<MetaData> mFormat;
List<sp<ABuffer> > mBuffers;
status_t mEOSResult;
+ bool wasFormatChange(int32_t discontinuityType) const;
+
DISALLOW_EVIL_CONSTRUCTORS(AnotherPacketSource);
};
diff --git a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
index f55be6e..a089dbf 100644
--- a/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2PSExtractor.cpp
@@ -543,7 +543,7 @@
case ATSParser::STREAMTYPE_H264:
mode = ElementaryStreamQueue::H264;
break;
- case ATSParser::STREAMTYPE_MPEG2_AUDIO_ATDS:
+ case ATSParser::STREAMTYPE_MPEG2_AUDIO_ADTS:
mode = ElementaryStreamQueue::AAC;
break;
case ATSParser::STREAMTYPE_MPEG1_AUDIO:
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index 20225ba..cfea7e8 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -25,10 +25,12 @@
#include "MtpDataPacket.h"
#include "MtpStringBuffer.h"
+#define MTP_BUFFER_SIZE 16384
+
namespace android {
MtpDataPacket::MtpDataPacket()
- : MtpPacket(16384), // MAX_USBFS_BUFFER_SIZE
+ : MtpPacket(MTP_BUFFER_SIZE), // MAX_USBFS_BUFFER_SIZE
mOffset(MTP_CONTAINER_HEADER_SIZE)
{
}
@@ -345,7 +347,7 @@
#ifdef MTP_DEVICE
int MtpDataPacket::read(int fd) {
- int ret = ::read(fd, mBuffer, mBufferSize);
+ int ret = ::read(fd, mBuffer, MTP_BUFFER_SIZE);
if (ret < MTP_CONTAINER_HEADER_SIZE)
return -1;
mPacketSize = ret;
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index dc6c011..1dcfb74 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -1053,11 +1053,14 @@
int result = mDatabase->getObjectFilePath(handle, filePath, fileLength, format);
if (result == MTP_RESPONSE_OK) {
LOGV("deleting %s", (const char *)filePath);
- deletePath((const char *)filePath);
- return mDatabase->deleteFile(handle);
- } else {
- return result;
+ result = mDatabase->deleteFile(handle);
+ // Don't delete the actual files unless the database deletion is allowed
+ if (result == MTP_RESPONSE_OK) {
+ deletePath((const char *)filePath);
+ }
}
+
+ return result;
}
MtpResponseCode MtpServer::doGetObjectPropDesc() {