Merge "IOMX: allow configuration after going to loaded state" into nyc-mr1-dev
diff --git a/drm/mediadrm/plugins/clearkey/DrmFactory.cpp b/drm/mediadrm/plugins/clearkey/DrmFactory.cpp
index 40275cf..d27956c 100644
--- a/drm/mediadrm/plugins/clearkey/DrmFactory.cpp
+++ b/drm/mediadrm/plugins/clearkey/DrmFactory.cpp
@@ -24,6 +24,7 @@
#include "DrmPlugin.h"
#include "ClearKeyUUID.h"
+#include "MimeType.h"
#include "SessionLibrary.h"
namespace clearkeydrm {
@@ -32,10 +33,14 @@
return isClearKeyUUID(uuid);
}
-bool DrmFactory::isContentTypeSupported(const android::String8 &initDataType) {
+bool DrmFactory::isContentTypeSupported(const android::String8 &type) {
// This should match the types handed by InitDataParser.
- return initDataType == "cenc" ||
- initDataType == "webm";
+ return type == kIsoBmffVideoMimeType ||
+ type == kIsoBmffAudioMimeType ||
+ type == kCencInitDataFormat ||
+ type == kWebmVideoMimeType ||
+ type == kWebmAudioMimeType ||
+ type == kWebmInitDataFormat;
}
android::status_t DrmFactory::createDrmPlugin(
diff --git a/drm/mediadrm/plugins/clearkey/DrmFactory.h b/drm/mediadrm/plugins/clearkey/DrmFactory.h
index 164d3d0..87db982 100644
--- a/drm/mediadrm/plugins/clearkey/DrmFactory.h
+++ b/drm/mediadrm/plugins/clearkey/DrmFactory.h
@@ -32,7 +32,7 @@
virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]);
- virtual bool isContentTypeSupported(const android::String8 &initDataType);
+ virtual bool isContentTypeSupported(const android::String8 &mimeType);
virtual android::status_t createDrmPlugin(
const uint8_t uuid[16], android::DrmPlugin** plugin);
diff --git a/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
index e5ee403..86bf047 100644
--- a/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/DrmPlugin.cpp
@@ -46,7 +46,7 @@
status_t DrmPlugin::getKeyRequest(
const Vector<uint8_t>& scope,
const Vector<uint8_t>& initData,
- const String8& initDataType,
+ const String8& mimeType,
KeyType keyType,
const KeyedVector<String8, String8>& optionalParameters,
Vector<uint8_t>& request,
@@ -62,7 +62,7 @@
if (!session.get()) {
return android::ERROR_DRM_SESSION_NOT_OPENED;
}
- return session->getKeyRequest(initData, initDataType, &request);
+ return session->getKeyRequest(initData, mimeType, &request);
}
status_t DrmPlugin::provideKeyResponse(
diff --git a/drm/mediadrm/plugins/clearkey/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
index 9095045..efb9f8b 100644
--- a/drm/mediadrm/plugins/clearkey/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
@@ -49,7 +49,7 @@
virtual status_t getKeyRequest(
const Vector<uint8_t>& scope,
- const Vector<uint8_t>& initData,
+ const Vector<uint8_t>& mimeType,
const String8& initDataType,
KeyType keyType,
const KeyedVector<String8, String8>& optionalParameters,
diff --git a/drm/mediadrm/plugins/clearkey/InitDataParser.cpp b/drm/mediadrm/plugins/clearkey/InitDataParser.cpp
index c22d73a..0216b8d 100644
--- a/drm/mediadrm/plugins/clearkey/InitDataParser.cpp
+++ b/drm/mediadrm/plugins/clearkey/InitDataParser.cpp
@@ -27,6 +27,7 @@
#include "InitDataParser.h"
#include "ClearKeyUUID.h"
+#include "MimeType.h"
#include "Utils.h"
namespace clearkeydrm {
@@ -41,16 +42,20 @@
}
android::status_t InitDataParser::parse(const Vector<uint8_t>& initData,
- const String8& initDataType,
+ const String8& type,
Vector<uint8_t>* licenseRequest) {
// Build a list of the key IDs
Vector<const uint8_t*> keyIds;
- if (initDataType == "cenc") {
+ if (type == kIsoBmffVideoMimeType ||
+ type == kIsoBmffAudioMimeType ||
+ type == kCencInitDataFormat) {
android::status_t res = parsePssh(initData, &keyIds);
if (res != android::OK) {
return res;
}
- } else if (initDataType == "webm") {
+ } else if (type == kWebmVideoMimeType ||
+ type == kWebmAudioMimeType ||
+ type == kWebmInitDataFormat) {
// WebM "init data" is just a single key ID
if (initData.size() != kKeyIdSize) {
return android::ERROR_DRM_CANNOT_HANDLE;
diff --git a/drm/mediadrm/plugins/clearkey/InitDataParser.h b/drm/mediadrm/plugins/clearkey/InitDataParser.h
index 9505d2a..a9707bf 100644
--- a/drm/mediadrm/plugins/clearkey/InitDataParser.h
+++ b/drm/mediadrm/plugins/clearkey/InitDataParser.h
@@ -29,7 +29,7 @@
InitDataParser() {}
android::status_t parse(const android::Vector<uint8_t>& initData,
- const android::String8& initDataType,
+ const android::String8& type,
android::Vector<uint8_t>* licenseRequest);
private:
diff --git a/drm/mediadrm/plugins/clearkey/MimeType.h b/drm/mediadrm/plugins/clearkey/MimeType.h
new file mode 100644
index 0000000..085f17a
--- /dev/null
+++ b/drm/mediadrm/plugins/clearkey/MimeType.h
@@ -0,0 +1,15 @@
+#ifndef CLEARKEY_MIMETYPE_H_
+#define CLEARKEY_MIMETYPE_H_
+
+#include <utils/String8.h>
+
+namespace {
+ const android::String8 kCencInitDataFormat("cenc");
+ const android::String8 kIsoBmffAudioMimeType("audio/mp4");
+ const android::String8 kIsoBmffVideoMimeType("video/mp4");
+ const android::String8 kWebmInitDataFormat("webm");
+ const android::String8 kWebmAudioMimeType("audio/webm");
+ const android::String8 kWebmVideoMimeType("video/webm");
+}
+
+#endif // CLEARKEY_MIMETYPE_H_
diff --git a/drm/mediadrm/plugins/clearkey/Session.cpp b/drm/mediadrm/plugins/clearkey/Session.cpp
index 95016f5..d210f5e 100644
--- a/drm/mediadrm/plugins/clearkey/Session.cpp
+++ b/drm/mediadrm/plugins/clearkey/Session.cpp
@@ -36,10 +36,10 @@
status_t Session::getKeyRequest(
const Vector<uint8_t>& initData,
- const String8& initDataType,
+ const String8& mimeType,
Vector<uint8_t>* keyRequest) const {
InitDataParser parser;
- return parser.parse(initData, initDataType, keyRequest);
+ return parser.parse(initData, mimeType, keyRequest);
}
status_t Session::provideKeyResponse(const Vector<uint8_t>& response) {
diff --git a/drm/mediadrm/plugins/clearkey/Session.h b/drm/mediadrm/plugins/clearkey/Session.h
index cab0dc3..0933506 100644
--- a/drm/mediadrm/plugins/clearkey/Session.h
+++ b/drm/mediadrm/plugins/clearkey/Session.h
@@ -38,7 +38,7 @@
const android::Vector<uint8_t>& sessionId() const { return mSessionId; }
android::status_t getKeyRequest(
- const android::Vector<uint8_t>& initData,
+ const android::Vector<uint8_t>& mimeType,
const android::String8& initDataType,
android::Vector<uint8_t>* keyRequest) const;
diff --git a/drm/mediadrm/plugins/clearkey/tests/InitDataParserUnittest.cpp b/drm/mediadrm/plugins/clearkey/tests/InitDataParserUnittest.cpp
index 4ba65ed..e275108 100644
--- a/drm/mediadrm/plugins/clearkey/tests/InitDataParserUnittest.cpp
+++ b/drm/mediadrm/plugins/clearkey/tests/InitDataParserUnittest.cpp
@@ -30,27 +30,27 @@
namespace {
const size_t kKeyIdSize = 16;
- const String8 kCencType("cenc");
- const String8 kWebMType("webm");
+ const String8 kCencMimeType("video/mp4");
+ const String8 kWebmMimeType("video/webm");
const String8 kBase64Padding("=");
}
class InitDataParserTest : public ::testing::Test {
protected:
status_t attemptParse(const Vector<uint8_t>& initData,
- const String8& initDataType,
+ const String8& mimeType,
Vector<uint8_t>* licenseRequest) {
InitDataParser parser;
- return parser.parse(initData, initDataType, licenseRequest);
+ return parser.parse(initData, mimeType, licenseRequest);
}
void attemptParseExpectingSuccess(const Vector<uint8_t>& initData,
- const String8& initDataType,
+ const String8& mimeType,
const Vector<String8>& expectedKeys) {
const String8 kRequestPrefix("{\"kids\":[");
const String8 kRequestSuffix("],\"type\":\"temporary\"}");
Vector<uint8_t> request;
- ASSERT_EQ(android::OK, attemptParse(initData, initDataType, &request));
+ ASSERT_EQ(android::OK, attemptParse(initData, mimeType, &request));
String8 requestString(reinterpret_cast<const char*>(request.array()),
request.size());
@@ -68,9 +68,9 @@
}
void attemptParseExpectingFailure(const Vector<uint8_t>& initData,
- const String8& initDataType) {
+ const String8& mimeType) {
Vector<uint8_t> request;
- ASSERT_NE(android::OK, attemptParse(initData, initDataType, &request));
+ ASSERT_NE(android::OK, attemptParse(initData, mimeType, &request));
EXPECT_EQ(0, request.size());
}
};
@@ -93,7 +93,7 @@
Vector<String8> expectedKeys;
expectedKeys.push(String8("01234567890ABCDE"));
- attemptParseExpectingSuccess(initData, kCencType, expectedKeys);
+ attemptParseExpectingSuccess(initData, kCencMimeType, expectedKeys);
}
TEST_F(InitDataParserTest, ParsesMultipleKeyPssh) {
@@ -120,7 +120,7 @@
expectedKeys.push(String8("ClearKeyClearKey"));
expectedKeys.push(String8(" GOOGLE GOOGLE "));
- attemptParseExpectingSuccess(initData, kCencType, expectedKeys);
+ attemptParseExpectingSuccess(initData, kCencMimeType, expectedKeys);
}
TEST_F(InitDataParserTest, ParsesWebM) {
@@ -134,7 +134,7 @@
Vector<String8> expectedKeys;
expectedKeys.push(String8("01234567890ABCDE"));
- attemptParseExpectingSuccess(initData, kWebMType, expectedKeys);
+ attemptParseExpectingSuccess(initData, kWebmMimeType, expectedKeys);
}
TEST_F(InitDataParserTest, FailsForPsshTooSmall) {
@@ -147,7 +147,7 @@
Vector<uint8_t> initData;
initData.appendArray(pssh, 16);
- attemptParseExpectingFailure(initData, kCencType);
+ attemptParseExpectingFailure(initData, kCencMimeType);
}
TEST_F(InitDataParserTest, FailsForWebMTooSmall) {
@@ -157,7 +157,7 @@
Vector<uint8_t> initData;
initData.appendArray(initDataRaw, 8);
- attemptParseExpectingFailure(initData, kWebMType);
+ attemptParseExpectingFailure(initData, kWebmMimeType);
}
TEST_F(InitDataParserTest, FailsForPsshBadSystemId) {
@@ -175,7 +175,7 @@
Vector<uint8_t> initData;
initData.appendArray(pssh, 52);
- attemptParseExpectingFailure(initData, kCencType);
+ attemptParseExpectingFailure(initData, kCencMimeType);
}
TEST_F(InitDataParserTest, FailsForPsshBadSize) {
@@ -193,7 +193,7 @@
Vector<uint8_t> initData;
initData.appendArray(pssh, 52);
- attemptParseExpectingFailure(initData, kCencType);
+ attemptParseExpectingFailure(initData, kCencMimeType);
}
TEST_F(InitDataParserTest, FailsForPsshWrongVersion) {
@@ -211,7 +211,7 @@
Vector<uint8_t> initData;
initData.appendArray(pssh, 52);
- attemptParseExpectingFailure(initData, kCencType);
+ attemptParseExpectingFailure(initData, kCencMimeType);
}
TEST_F(InitDataParserTest, FailsForPsshBadKeyCount) {
@@ -229,7 +229,7 @@
Vector<uint8_t> initData;
initData.appendArray(pssh, 52);
- attemptParseExpectingFailure(initData, kCencType);
+ attemptParseExpectingFailure(initData, kCencMimeType);
}
} // namespace clearkeydrm
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index ffdb9b5..7becf57 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -522,6 +522,12 @@
mTimestampMutator.push(timestamp);
}
+ // Flushes the shared ring buffer if the client had requested it using mStreaming.mFlush.
+ // If flush occurs then:
+ // cblk->u.mStreaming.mFront, ServerProxy::mFlush and ServerProxy::mFlushed will be modified
+ // client will be notified via Futex
+ virtual void flushBufferIfNeeded();
+
// Total count of the number of flushed frames since creation (never reset).
virtual int64_t framesFlushed() const { return mFlushed; }
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index 7119517..846f8b8 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -622,6 +622,56 @@
}
__attribute__((no_sanitize("integer")))
+void ServerProxy::flushBufferIfNeeded()
+{
+ audio_track_cblk_t* cblk = mCblk;
+ // The acquire_load is not really required. But since the write is a release_store in the
+ // client, using acquire_load here makes it easier for people to maintain the code,
+ // and the logic for communicating ipc variables seems somewhat standard,
+ // and there really isn't much penalty for 4 or 8 byte atomics.
+ int32_t flush = android_atomic_acquire_load(&cblk->u.mStreaming.mFlush);
+ if (flush != mFlush) {
+ ALOGV("ServerProxy::flushBufferIfNeeded() mStreaming.mFlush = 0x%x, mFlush = 0x%0x",
+ flush, mFlush);
+ int32_t rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
+ int32_t front = cblk->u.mStreaming.mFront;
+
+ // effectively obtain then release whatever is in the buffer
+ const size_t overflowBit = mFrameCountP2 << 1;
+ const size_t mask = overflowBit - 1;
+ int32_t newFront = (front & ~mask) | (flush & mask);
+ ssize_t filled = rear - newFront;
+ if (filled >= (ssize_t)overflowBit) {
+ // front and rear offsets span the overflow bit of the p2 mask
+ // so rebasing newFront on the front offset is off by the overflow bit.
+ // adjust newFront to match rear offset.
+ ALOGV("flush wrap: filled %zx >= overflowBit %zx", filled, overflowBit);
+ newFront += overflowBit;
+ filled -= overflowBit;
+ }
+ // Rather than shutting down on a corrupt flush, just treat it as a full flush
+ if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
+ ALOGE("mFlush %#x -> %#x, front %#x, rear %#x, mask %#x, newFront %#x, "
+ "filled %zd=%#x",
+ mFlush, flush, front, rear,
+ (unsigned)mask, newFront, filled, (unsigned)filled);
+ newFront = rear;
+ }
+ mFlush = flush;
+ android_atomic_release_store(newFront, &cblk->u.mStreaming.mFront);
+ // There is no danger from a false positive, so err on the side of caution
+ if (true /*front != newFront*/) {
+ int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
+ if (!(old & CBLK_FUTEX_WAKE)) {
+ (void) syscall(__NR_futex, &cblk->mFutex,
+ mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1);
+ }
+ }
+ mFlushed += (newFront - front) & mask;
+ }
+}
+
+__attribute__((no_sanitize("integer")))
status_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush)
{
LOG_ALWAYS_FATAL_IF(buffer == NULL || buffer->mFrameCount == 0);
@@ -636,44 +686,9 @@
int32_t rear;
// See notes on barriers at ClientProxy::obtainBuffer()
if (mIsOut) {
- int32_t flush = cblk->u.mStreaming.mFlush;
+ flushBufferIfNeeded(); // might modify mFront
rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
front = cblk->u.mStreaming.mFront;
- if (flush != mFlush) {
- // effectively obtain then release whatever is in the buffer
- const size_t overflowBit = mFrameCountP2 << 1;
- const size_t mask = overflowBit - 1;
- int32_t newFront = (front & ~mask) | (flush & mask);
- ssize_t filled = rear - newFront;
- if (filled >= (ssize_t)overflowBit) {
- // front and rear offsets span the overflow bit of the p2 mask
- // so rebasing newFront on the front offset is off by the overflow bit.
- // adjust newFront to match rear offset.
- ALOGV("flush wrap: filled %zx >= overflowBit %zx", filled, overflowBit);
- newFront += overflowBit;
- filled -= overflowBit;
- }
- // Rather than shutting down on a corrupt flush, just treat it as a full flush
- if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
- ALOGE("mFlush %#x -> %#x, front %#x, rear %#x, mask %#x, newFront %#x, "
- "filled %zd=%#x",
- mFlush, flush, front, rear,
- (unsigned)mask, newFront, filled, (unsigned)filled);
- newFront = rear;
- }
- mFlush = flush;
- android_atomic_release_store(newFront, &cblk->u.mStreaming.mFront);
- // There is no danger from a false positive, so err on the side of caution
- if (true /*front != newFront*/) {
- int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
- if (!(old & CBLK_FUTEX_WAKE)) {
- (void) syscall(__NR_futex, &cblk->mFutex,
- mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1);
- }
- }
- mFlushed += (newFront - front) & mask;
- front = newFront;
- }
} else {
front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront);
rear = cblk->u.mStreaming.mRear;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index b387af3..3cca054 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -777,6 +777,13 @@
Mutex::Autolock _l(thread->mLock);
PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ // Flush the ring buffer now if the track is not active in the PlaybackThread.
+ // Otherwise the flush would not be done until the track is resumed.
+ // Requires FastTrack removal be BLOCK_UNTIL_ACKED
+ if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+ (void)mServerProxy->flushBufferIfNeeded();
+ }
+
if (isOffloaded()) {
// If offloaded we allow flush during any state except terminated
// and keep the track active to avoid problems if user is seeking
@@ -828,6 +835,10 @@
if (!isOffloaded() && !isDirect())
return;
+ // Clear the client ring buffer so that the app can prime the buffer while paused.
+ // Otherwise it might not get cleared until playback is resumed and obtainBuffer() is called.
+ mServerProxy->flushBufferIfNeeded();
+
mFlushHwPending = false;
}