Merge "Issue 5298399: Lost speech after a crash in gTalk."
diff --git a/include/media/mediascanner.h b/include/media/mediascanner.h
index 803bffb..a73403b 100644
--- a/include/media/mediascanner.h
+++ b/include/media/mediascanner.h
@@ -62,12 +62,17 @@
private:
// current locale (like "ja_JP"), created/destroyed with strdup()/free()
char *mLocale;
+ char *mSkipList;
+ int *mSkipIndex;
MediaScanResult doProcessDirectory(
char *path, int pathRemaining, MediaScannerClient &client, bool noMedia);
MediaScanResult doProcessDirectoryEntry(
char *path, int pathRemaining, MediaScannerClient &client, bool noMedia,
struct dirent* entry, char* fileSpot);
+ void loadSkipList();
+ bool shouldSkipDirectory(char *path);
+
MediaScanner(const MediaScanner &);
MediaScanner &operator=(const MediaScanner &);
@@ -103,4 +108,3 @@
}; // namespace android
#endif // MEDIASCANNER_H
-
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index e965f14..b7286e5 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -164,6 +164,8 @@
void sendFormatChange();
+ void signalError(OMX_ERRORTYPE error = OMX_ErrorUndefined);
+
DISALLOW_EVIL_CONSTRUCTORS(ACodec);
};
diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp
index 41f8593..19dedfc 100644
--- a/media/libmedia/MediaScanner.cpp
+++ b/media/libmedia/MediaScanner.cpp
@@ -16,6 +16,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaScanner"
+#include <cutils/properties.h>
#include <utils/Log.h>
#include <media/mediascanner.h>
@@ -26,11 +27,14 @@
namespace android {
MediaScanner::MediaScanner()
- : mLocale(NULL) {
+ : mLocale(NULL), mSkipList(NULL), mSkipIndex(NULL) {
+ loadSkipList();
}
MediaScanner::~MediaScanner() {
setLocale(NULL);
+ free(mSkipList);
+ free(mSkipIndex);
}
void MediaScanner::setLocale(const char *locale) {
@@ -47,6 +51,33 @@
return mLocale;
}
+void MediaScanner::loadSkipList() {
+ mSkipList = (char *)malloc(PROPERTY_VALUE_MAX * sizeof(char));
+ if (mSkipList) {
+ property_get("testing.mediascanner.skiplist", mSkipList, "");
+ }
+ if (!mSkipList || (strlen(mSkipList) == 0)) {
+ free(mSkipList);
+ mSkipList = NULL;
+ return;
+ }
+ mSkipIndex = (int *)malloc(PROPERTY_VALUE_MAX * sizeof(int));
+ if (mSkipIndex) {
+ // dup it because strtok will modify the string
+ char *skipList = strdup(mSkipList);
+ if (skipList) {
+ char * path = strtok(skipList, ",");
+ int i = 0;
+ while (path) {
+ mSkipIndex[i++] = strlen(path);
+ path = strtok(NULL, ",");
+ }
+ mSkipIndex[i] = -1;
+ free(skipList);
+ }
+ }
+}
+
MediaScanResult MediaScanner::processDirectory(
const char *path, MediaScannerClient &client) {
int pathLength = strlen(path);
@@ -75,12 +106,39 @@
return result;
}
+bool MediaScanner::shouldSkipDirectory(char *path) {
+ if (path && mSkipList && mSkipIndex) {
+ int len = strlen(path);
+ int idx = 0;
+ // track the start position of next path in the comma
+ // separated list obtained from getprop
+ int startPos = 0;
+ while (mSkipIndex[idx] != -1) {
+ // no point to match path name if strlen mismatch
+ if ((len == mSkipIndex[idx])
+ // pick out the path segment from comma separated list
+ // to compare against current path parameter
+ && (strncmp(path, &mSkipList[startPos], len) == 0)) {
+ return true;
+ }
+ startPos += mSkipIndex[idx] + 1; // extra char for the delimiter
+ idx++;
+ }
+ }
+ return false;
+}
+
MediaScanResult MediaScanner::doProcessDirectory(
char *path, int pathRemaining, MediaScannerClient &client, bool noMedia) {
// place to copy file or directory name
char* fileSpot = path + strlen(path);
struct dirent* entry;
+ if (shouldSkipDirectory(path)) {
+ LOGD("Skipping: %s", path);
+ return MEDIA_SCAN_RESULT_OK;
+ }
+
// Treat all files as non-media in directories that contain a ".nomedia" file
if (pathRemaining >= 8 /* strlen(".nomedia") */ ) {
strcpy(fileSpot, ".nomedia");
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 8f213da..bf83849 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -26,6 +26,9 @@
namespace android {
+// static
+const int64_t NuPlayer::Renderer::kMinPositionUpdateDelayUs = 100000ll;
+
NuPlayer::Renderer::Renderer(
const sp<MediaPlayerBase::AudioSink> &sink,
const sp<AMessage> ¬ify)
@@ -43,7 +46,8 @@
mHasAudio(false),
mHasVideo(false),
mSyncQueues(false),
- mPaused(false) {
+ mPaused(false),
+ mLastPositionUpdateUs(-1ll) {
}
NuPlayer::Renderer::~Renderer() {
@@ -190,7 +194,7 @@
mDrainAudioQueuePending = true;
sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, id());
msg->setInt32("generation", mAudioQueueGeneration);
- msg->post(10000);
+ msg->post();
}
void NuPlayer::Renderer::signalAudioSinkChanged() {
@@ -198,7 +202,6 @@
}
void NuPlayer::Renderer::onDrainAudioQueue() {
-
for (;;) {
if (mAudioQueue.empty()) {
break;
@@ -562,6 +565,13 @@
}
int64_t nowUs = ALooper::GetNowUs();
+
+ if (mLastPositionUpdateUs >= 0
+ && nowUs < mLastPositionUpdateUs + kMinPositionUpdateDelayUs) {
+ return;
+ }
+ mLastPositionUpdateUs = nowUs;
+
int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs;
sp<AMessage> notify = mNotify->dup();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 2713031..3a641a2 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -74,6 +74,8 @@
status_t mFinalResult;
};
+ static const int64_t kMinPositionUpdateDelayUs;
+
sp<MediaPlayerBase::AudioSink> mAudioSink;
sp<AMessage> mNotify;
List<QueueEntry> mAudioQueue;
@@ -98,6 +100,8 @@
bool mPaused;
+ int64_t mLastPositionUpdateUs;
+
void onDrainAudioQueue();
void postDrainAudioQueue();
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index e9dc61c..2ba2273 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1131,6 +1131,13 @@
mSentFormat = true;
}
+void ACodec::signalError(OMX_ERRORTYPE error) {
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", ACodec::kWhatError);
+ notify->setInt32("omx-error", error);
+ notify->post();
+}
+
////////////////////////////////////////////////////////////////////////////////
ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
@@ -1252,10 +1259,7 @@
LOGE("[%s] ERROR(0x%08lx)", mCodec->mComponentName.c_str(), data1);
- sp<AMessage> notify = mCodec->mNotify->dup();
- notify->setInt32("what", ACodec::kWhatError);
- notify->setInt32("omx-error", data1);
- notify->post();
+ mCodec->signalError((OMX_ERRORTYPE)data1);
return true;
}
@@ -1548,12 +1552,14 @@
&& msg->findInt32("render", &render) && render != 0) {
// The client wants this buffer to be rendered.
- CHECK_EQ(mCodec->mNativeWindow->queueBuffer(
+ if (mCodec->mNativeWindow->queueBuffer(
mCodec->mNativeWindow.get(),
- info->mGraphicBuffer.get()),
- 0);
-
- info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
+ info->mGraphicBuffer.get()) == OK) {
+ info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
+ } else {
+ mCodec->signalError();
+ info->mStatus = BufferInfo::OWNED_BY_US;
+ }
} else {
info->mStatus = BufferInfo::OWNED_BY_US;
}
@@ -1692,11 +1698,7 @@
if (node == NULL) {
LOGE("Unable to instantiate a decoder for type '%s'.", mime.c_str());
- sp<AMessage> notify = mCodec->mNotify->dup();
- notify->setInt32("what", ACodec::kWhatError);
- notify->setInt32("omx-error", OMX_ErrorComponentNotFound);
- notify->post();
-
+ mCodec->signalError(OMX_ErrorComponentNotFound);
return;
}
@@ -1744,10 +1746,7 @@
"(error 0x%08x)",
err);
- sp<AMessage> notify = mCodec->mNotify->dup();
- notify->setInt32("what", ACodec::kWhatError);
- notify->setInt32("omx-error", OMX_ErrorUndefined);
- notify->post();
+ mCodec->signalError();
}
}
@@ -2063,10 +2062,7 @@
"port reconfiguration (error 0x%08x)",
err);
- sp<AMessage> notify = mCodec->mNotify->dup();
- notify->setInt32("what", ACodec::kWhatError);
- notify->setInt32("omx-error", OMX_ErrorUndefined);
- notify->post();
+ mCodec->signalError();
}
return true;
diff --git a/media/libstagefright/AVIExtractor.cpp b/media/libstagefright/AVIExtractor.cpp
index 6313ca3..4e46414 100644
--- a/media/libstagefright/AVIExtractor.cpp
+++ b/media/libstagefright/AVIExtractor.cpp
@@ -117,14 +117,12 @@
}
}
- int64_t timeUs =
- (mSampleIndex * 1000000ll * mTrack.mRate) / mTrack.mScale;
-
off64_t offset;
size_t size;
bool isKey;
+ int64_t timeUs;
status_t err = mExtractor->getSampleInfo(
- mTrackIndex, mSampleIndex, &offset, &size, &isKey);
+ mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs);
++mSampleIndex;
@@ -396,6 +394,8 @@
uint32_t rate = U32LE_AT(&data[20]);
uint32_t scale = U32LE_AT(&data[24]);
+ uint32_t sampleSize = U32LE_AT(&data[44]);
+
const char *mime = NULL;
Track::Kind kind = Track::OTHER;
@@ -427,6 +427,7 @@
track->mMeta = meta;
track->mRate = rate;
track->mScale = scale;
+ track->mBytesPerSample = sampleSize;
track->mKind = kind;
track->mNumSyncSamples = 0;
track->mThumbnailSampleSize = 0;
@@ -612,11 +613,12 @@
off64_t offset;
size_t size;
bool isKey;
- status_t err = getSampleInfo(0, 0, &offset, &size, &isKey);
+ int64_t timeUs;
+ status_t err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
if (err != OK) {
mOffsetsAreAbsolute = !mOffsetsAreAbsolute;
- err = getSampleInfo(0, 0, &offset, &size, &isKey);
+ err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
if (err != OK) {
return err;
@@ -630,8 +632,9 @@
for (size_t i = 0; i < mTracks.size(); ++i) {
Track *track = &mTracks.editItemAt(i);
- int64_t durationUs =
- (track->mSamples.size() * 1000000ll * track->mRate) / track->mScale;
+ int64_t durationUs;
+ CHECK_EQ((status_t)OK,
+ getSampleTime(i, track->mSamples.size() - 1, &durationUs));
LOGV("track %d duration = %.2f secs", i, durationUs / 1E6);
@@ -645,9 +648,10 @@
if (!strncasecmp("video/", mime.c_str(), 6)
&& track->mThumbnailSampleIndex >= 0) {
- int64_t thumbnailTimeUs =
- (track->mThumbnailSampleIndex * 1000000ll * track->mRate)
- / track->mScale;
+ int64_t thumbnailTimeUs;
+ CHECK_EQ((status_t)OK,
+ getSampleTime(i, track->mThumbnailSampleIndex,
+ &thumbnailTimeUs));
track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
@@ -659,6 +663,21 @@
}
}
}
+
+ if (track->mBytesPerSample != 0) {
+ // Assume all chunks are the same size for now.
+
+ off64_t offset;
+ size_t size;
+ bool isKey;
+ int64_t sampleTimeUs;
+ CHECK_EQ((status_t)OK,
+ getSampleInfo(
+ i, 0,
+ &offset, &size, &isKey, &sampleTimeUs));
+
+ track->mRate *= size / track->mBytesPerSample;
+ }
}
mFoundIndex = true;
@@ -720,7 +739,9 @@
off64_t offset;
size_t size;
bool isKey;
- status_t err = getSampleInfo(trackIndex, 0, &offset, &size, &isKey);
+ int64_t timeUs;
+ status_t err =
+ getSampleInfo(trackIndex, 0, &offset, &size, &isKey, &timeUs);
if (err != OK) {
return err;
@@ -762,7 +783,8 @@
status_t AVIExtractor::getSampleInfo(
size_t trackIndex, size_t sampleIndex,
- off64_t *offset, size_t *size, bool *isKey) {
+ off64_t *offset, size_t *size, bool *isKey,
+ int64_t *sampleTimeUs) {
if (trackIndex >= mTracks.size()) {
return -ERANGE;
}
@@ -801,9 +823,20 @@
*isKey = info.mIsKey;
+ *sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale;
+
return OK;
}
+status_t AVIExtractor::getSampleTime(
+ size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs) {
+ off64_t offset;
+ size_t size;
+ bool isKey;
+ return getSampleInfo(
+ trackIndex, sampleIndex, &offset, &size, &isKey, sampleTimeUs);
+}
+
status_t AVIExtractor::getSampleIndexAtTime(
size_t trackIndex,
int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
@@ -911,7 +944,11 @@
if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) {
mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI);
- *confidence = 0.2;
+
+ // Just a tad over the mp3 extractor's confidence, since
+ // these .avi files may contain .mp3 content that otherwise would
+ // mistakenly lead to us identifying the entire file as a .mp3 file.
+ *confidence = 0.21;
return true;
}
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index fb49d7b..9ab470b 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -50,7 +50,7 @@
// Treat time out as an error if we have not received any output
// buffers after 3 seconds.
-const static int64_t kBufferFilledEventTimeOutUs = 3000000000LL;
+const static int64_t kBufferFilledEventTimeOutNs = 3000000000LL;
struct CodecInfo {
const char *mime;
@@ -2325,9 +2325,14 @@
{
CODEC_LOGV("OMX_EventPortSettingsChanged(port=%ld, data2=0x%08lx)",
data1, data2);
- CHECK(mFilledBuffers.empty());
if (data2 == 0 || data2 == OMX_IndexParamPortDefinition) {
+ // There is no need to check whether mFilledBuffers is empty or not
+ // when the OMX_EventPortSettingsChanged is not meant for reallocating
+ // the output buffers.
+ if (data1 == kPortIndexOutput) {
+ CHECK(mFilledBuffers.empty());
+ }
onPortSettingsChanged(data1);
} else if (data1 == kPortIndexOutput &&
(data2 == OMX_IndexConfigCommonOutputCrop ||
@@ -3220,7 +3225,7 @@
// for video encoding.
return mBufferFilled.wait(mLock);
}
- status_t err = mBufferFilled.waitRelative(mLock, kBufferFilledEventTimeOutUs);
+ status_t err = mBufferFilled.waitRelative(mLock, kBufferFilledEventTimeOutNs);
if (err != OK) {
CODEC_LOGE("Timed out waiting for output buffers: %d/%d",
countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
diff --git a/media/libstagefright/include/AVIExtractor.h b/media/libstagefright/include/AVIExtractor.h
index 375a94d..b575347 100644
--- a/media/libstagefright/include/AVIExtractor.h
+++ b/media/libstagefright/include/AVIExtractor.h
@@ -54,6 +54,11 @@
uint32_t mRate;
uint32_t mScale;
+ // If bytes per sample == 0, each chunk represents a single sample,
+ // otherwise each chunk should me a multiple of bytes-per-sample in
+ // size.
+ uint32_t mBytesPerSample;
+
enum Kind {
AUDIO,
VIDEO,
@@ -84,7 +89,11 @@
status_t getSampleInfo(
size_t trackIndex, size_t sampleIndex,
- off64_t *offset, size_t *size, bool *isKey);
+ off64_t *offset, size_t *size, bool *isKey,
+ int64_t *sampleTimeUs);
+
+ status_t getSampleTime(
+ size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs);
status_t getSampleIndexAtTime(
size_t trackIndex,
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 94efa74..a58f64c 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -87,6 +87,8 @@
// RecordThread loop sleep time upon application overrun or audio HAL read error
static const int kRecordThreadSleepUs = 5000;
+static const nsecs_t kSetParametersTimeout = seconds(2);
+
// ----------------------------------------------------------------------------
static bool recordingAllowed() {
@@ -1032,7 +1034,7 @@
mWaitWorkCV.signal();
// wait condition with timeout in case the thread loop has exited
// before the request could be processed
- if (mParamCond.waitRelative(mLock, seconds(2)) == NO_ERROR) {
+ if (mParamCond.waitRelative(mLock, kSetParametersTimeout) == NO_ERROR) {
status = mParamStatus;
mWaitWorkCV.signal();
} else {
@@ -2349,7 +2351,9 @@
mParamStatus = status;
mParamCond.signal();
- mWaitWorkCV.wait(mLock);
+ // wait for condition with time out in case the thread calling ThreadBase::setParameters()
+ // already timed out waiting for the status and will never signal the condition.
+ mWaitWorkCV.waitRelative(mLock, kSetParametersTimeout);
}
return reconfig;
}
@@ -2828,7 +2832,9 @@
mParamStatus = status;
mParamCond.signal();
- mWaitWorkCV.wait(mLock);
+ // wait for condition with time out in case the thread calling ThreadBase::setParameters()
+ // already timed out waiting for the status and will never signal the condition.
+ mWaitWorkCV.waitRelative(mLock, kSetParametersTimeout);
}
return reconfig;
}
@@ -4669,7 +4675,9 @@
mParamStatus = status;
mParamCond.signal();
- mWaitWorkCV.wait(mLock);
+ // wait for condition with time out in case the thread calling ThreadBase::setParameters()
+ // already timed out waiting for the status and will never signal the condition.
+ mWaitWorkCV.waitRelative(mLock, kSetParametersTimeout);
}
return reconfig;
}