Merge "Camera: Add Y8 format in Camera NDK"
diff --git a/camera/ndk/Android.mk b/camera/ndk/Android.mk
index a5aab07..508f930 100644
--- a/camera/ndk/Android.mk
+++ b/camera/ndk/Android.mk
@@ -41,6 +41,8 @@
LOCAL_CFLAGS += -fvisibility=hidden -D EXPORT='__attribute__ ((visibility ("default")))'
LOCAL_CFLAGS += -Wall -Wextra -Werror
+LOCAL_LDFLAGS += -Wl,--version-script=$(LOCAL_PATH)/libcamera2ndk.map.txt
+
LOCAL_SHARED_LIBRARIES := \
libbinder \
liblog \
diff --git a/include/mediadrm/Crypto.h b/include/mediadrm/Crypto.h
deleted file mode 120000
index 9af6495..0000000
--- a/include/mediadrm/Crypto.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/Crypto.h
\ No newline at end of file
diff --git a/include/mediadrm/Drm.h b/include/mediadrm/Drm.h
deleted file mode 120000
index ac60003..0000000
--- a/include/mediadrm/Drm.h
+++ /dev/null
@@ -1 +0,0 @@
-../../media/libmedia/include/media/Drm.h
\ No newline at end of file
diff --git a/media/bufferpool/2.0/Accessor.cpp b/media/bufferpool/2.0/Accessor.cpp
index 3eaea7c..f264501 100644
--- a/media/bufferpool/2.0/Accessor.cpp
+++ b/media/bufferpool/2.0/Accessor.cpp
@@ -117,19 +117,18 @@
Return<void> Accessor::connect(
const sp<::android::hardware::media::bufferpool::V2_0::IObserver>& observer,
connect_cb _hidl_cb) {
- (void)observer;
sp<Connection> connection;
ConnectionId connectionId;
+ uint32_t msgId;
const StatusDescriptor* fmqDesc;
+ const InvalidationDescriptor* invDesc;
- ResultStatus status = connect(&connection, &connectionId, &fmqDesc, false);
+ ResultStatus status = connect(
+ observer, false, &connection, &connectionId, &msgId, &fmqDesc, &invDesc);
if (status == ResultStatus::OK) {
- _hidl_cb(status, connection, connectionId, *fmqDesc,
- android::hardware::MQDescriptorUnsync<BufferInvalidationMessage>(
- std::vector<android::hardware::GrantorDescriptor>(),
- nullptr /* nhandle */, 0 /* size */));
+ _hidl_cb(status, connection, connectionId, msgId, *fmqDesc, *invDesc);
} else {
- _hidl_cb(status, nullptr, -1LL,
+ _hidl_cb(status, nullptr, -1LL, 0,
android::hardware::MQDescriptorSync<BufferStatusMessage>(
std::vector<android::hardware::GrantorDescriptor>(),
nullptr /* nhandle */, 0 /* size */),
@@ -147,7 +146,15 @@
}
bool Accessor::isValid() {
- return (bool)mImpl;
+ return (bool)mImpl && mImpl->isValid();
+}
+
+ResultStatus Accessor::flush() {
+ if (mImpl) {
+ mImpl->flush();
+ return ResultStatus::OK;
+ }
+ return ResultStatus::CRITICAL_ERROR;
}
ResultStatus Accessor::allocate(
@@ -170,10 +177,15 @@
}
ResultStatus Accessor::connect(
+ const sp<IObserver> &observer, bool local,
sp<Connection> *connection, ConnectionId *pConnectionId,
- const StatusDescriptor** fmqDescPtr, bool local) {
+ uint32_t *pMsgId,
+ const StatusDescriptor** statusDescPtr,
+ const InvalidationDescriptor** invDescPtr) {
if (mImpl) {
- ResultStatus status = mImpl->connect(this, connection, pConnectionId, fmqDescPtr);
+ ResultStatus status = mImpl->connect(
+ this, observer, connection, pConnectionId, pMsgId,
+ statusDescPtr, invDescPtr);
if (!local && status == ResultStatus::OK) {
sp<Accessor> accessor(this);
sConnectionDeathRecipient->add(*pConnectionId, accessor);
diff --git a/media/bufferpool/2.0/Accessor.h b/media/bufferpool/2.0/Accessor.h
index a718da1..4b5b17a 100644
--- a/media/bufferpool/2.0/Accessor.h
+++ b/media/bufferpool/2.0/Accessor.h
@@ -95,6 +95,9 @@
/** Returns whether the accessor is valid. */
bool isValid();
+ /** Invalidates all buffers which are owned by bufferpool */
+ ResultStatus flush();
+
/** Allocates a buffer from a buffer pool.
*
* @param connectionId the connection id of the client.
@@ -135,20 +138,28 @@
* created connection in order to communicate with the buffer pool. An
* FMQ for buffer status message is also created for the client.
*
- * @param connection created connection
- * @param pConnectionId the id of the created connection
- * @param fmqDescPtr FMQ descriptor for shared buffer status message
- * queue between a buffer pool and the client.
+ * @param observer client observer for buffer invalidation
* @param local true when a connection request comes from local process,
* false otherwise.
+ * @param connection created connection
+ * @param pConnectionId the id of the created connection
+ * @param pMsgId the id of the recent buffer pool message
+ * @param statusDescPtr FMQ descriptor for shared buffer status message
+ * queue between a buffer pool and the client.
+ * @param invDescPtr FMQ descriptor for buffer invalidation message
+ * queue from a buffer pool to the client.
*
* @return OK when a connection is successfully made.
* NO_MEMORY when there is no memory.
* CRITICAL_ERROR otherwise.
*/
ResultStatus connect(
+ const sp<IObserver>& observer,
+ bool local,
sp<Connection> *connection, ConnectionId *pConnectionId,
- const StatusDescriptor** fmqDescPtr, bool local);
+ uint32_t *pMsgId,
+ const StatusDescriptor** statusDescPtr,
+ const InvalidationDescriptor** invDescPtr);
/**
* Closes the specified connection to the client.
@@ -176,7 +187,7 @@
private:
class Impl;
- std::unique_ptr<Impl> mImpl;
+ std::shared_ptr<Impl> mImpl;
};
} // namespace implementation
diff --git a/media/bufferpool/2.0/AccessorImpl.cpp b/media/bufferpool/2.0/AccessorImpl.cpp
index 0ba6600..4cc8abc 100644
--- a/media/bufferpool/2.0/AccessorImpl.cpp
+++ b/media/bufferpool/2.0/AccessorImpl.cpp
@@ -21,6 +21,7 @@
#include <time.h>
#include <unistd.h>
#include <utils/Log.h>
+#include <thread>
#include "AccessorImpl.h"
#include "Connection.h"
@@ -47,6 +48,7 @@
const std::shared_ptr<BufferPoolAllocation> mAllocation;
const size_t mAllocSize;
const std::vector<uint8_t> mConfig;
+ bool mInvalidated;
InternalBuffer(
BufferId id,
@@ -54,11 +56,16 @@
const size_t allocSize,
const std::vector<uint8_t> &allocConfig)
: mId(id), mOwnerCount(0), mTransactionCount(0),
- mAllocation(alloc), mAllocSize(allocSize), mConfig(allocConfig) {}
+ mAllocation(alloc), mAllocSize(allocSize), mConfig(allocConfig),
+ mInvalidated(false) {}
const native_handle_t *handle() {
return mAllocation->handle();
}
+
+ void invalidate() {
+ mInvalidated = true;
+ }
};
struct TransactionStatus {
@@ -138,21 +145,29 @@
}
ResultStatus Accessor::Impl::connect(
- const sp<Accessor> &accessor, sp<Connection> *connection,
- ConnectionId *pConnectionId, const StatusDescriptor** fmqDescPtr) {
+ const sp<Accessor> &accessor, const sp<IObserver> &observer,
+ sp<Connection> *connection,
+ ConnectionId *pConnectionId,
+ uint32_t *pMsgId,
+ const StatusDescriptor** statusDescPtr,
+ const InvalidationDescriptor** invDescPtr) {
sp<Connection> newConnection = new Connection();
ResultStatus status = ResultStatus::CRITICAL_ERROR;
{
std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
if (newConnection) {
ConnectionId id = (int64_t)sPid << 32 | sSeqId;
- status = mBufferPool.mObserver.open(id, fmqDescPtr);
+ status = mBufferPool.mObserver.open(id, statusDescPtr);
if (status == ResultStatus::OK) {
newConnection->initialize(accessor, id);
*connection = newConnection;
*pConnectionId = id;
+ *pMsgId = mBufferPool.mInvalidation.mInvalidationId;
+ mBufferPool.mInvalidationChannel.getDesc(invDescPtr);
+ mBufferPool.mInvalidation.onConnect(id, observer);
++sSeqId;
}
+
}
mBufferPool.processStatusMessages();
mBufferPool.cleanUp();
@@ -165,6 +180,7 @@
mBufferPool.processStatusMessages();
mBufferPool.handleClose(connectionId);
mBufferPool.mObserver.close(connectionId);
+ mBufferPool.mInvalidation.onClose(connectionId);
// Since close# will be called after all works are finished, it is OK to
// evict unused buffers.
mBufferPool.cleanUp(true);
@@ -229,11 +245,30 @@
mBufferPool.cleanUp(clearCache);
}
+void Accessor::Impl::flush() {
+ std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
+ mBufferPool.processStatusMessages();
+ mBufferPool.flush(shared_from_this());
+}
+
+void Accessor::Impl::handleInvalidateAck() {
+ std::lock_guard<std::mutex> lock(mBufferPool.mMutex);
+ mBufferPool.processStatusMessages();
+ mBufferPool.mInvalidation.onHandleAck();
+}
+
+bool Accessor::Impl::isValid() {
+ return mBufferPool.isValid();
+}
+
Accessor::Impl::Impl::BufferPool::BufferPool()
: mTimestampUs(getTimestampNow()),
mLastCleanUpUs(mTimestampUs),
mLastLogUs(mTimestampUs),
- mSeq(0) {}
+ mSeq(0),
+ mStartSeq(0) {
+ mValid = mInvalidationChannel.isValid();
+}
// Statistics helper
@@ -242,6 +277,8 @@
return int(total ? 0.5 + 100. * static_cast<S>(base) / total : 0);
}
+std::atomic<std::uint32_t> Accessor::Impl::BufferPool::Invalidation::sSeqId(0);
+
Accessor::Impl::Impl::BufferPool::~BufferPool() {
std::lock_guard<std::mutex> lock(mMutex);
ALOGD("Destruction - bufferpool %p "
@@ -255,6 +292,96 @@
percentage(mStats.mTotalTransfers - mStats.mTotalFetches, mStats.mTotalTransfers));
}
+void Accessor::Impl::BufferPool::Invalidation::onConnect(
+ ConnectionId conId, const sp<IObserver>& observer) {
+ mAcks[conId] = mInvalidationId; // starts from current invalidationId
+ mObservers.insert(std::make_pair(conId, observer));
+}
+
+void Accessor::Impl::BufferPool::Invalidation::onClose(ConnectionId conId) {
+ mAcks.erase(conId);
+ mObservers.erase(conId);
+}
+
+void Accessor::Impl::BufferPool::Invalidation::onAck(
+ ConnectionId conId,
+ uint32_t msgId) {
+ auto it = mAcks.find(conId);
+ if (it == mAcks.end() || isMessageLater(msgId, it->second)) {
+ mAcks[conId] = msgId;
+ }
+}
+
+void Accessor::Impl::BufferPool::Invalidation::onBufferInvalidated(
+ BufferId bufferId,
+ BufferInvalidationChannel &channel) {
+ for (auto it = mPendings.begin(); it != mPendings.end();) {
+ if (it->invalidate(bufferId)) {
+ it = mPendings.erase(it);
+ uint32_t msgId = 0;
+ if (it->mNeedsAck) {
+ msgId = ++mInvalidationId;
+ if (msgId == 0) {
+ // wrap happens
+ msgId = ++mInvalidationId;
+ }
+ }
+ channel.postInvalidation(msgId, it->mFrom, it->mTo);
+ sInvalidator.addAccessor(mId, it->mImpl);
+ continue;
+ }
+ ++it;
+ }
+}
+
+void Accessor::Impl::BufferPool::Invalidation::onInvalidationRequest(
+ bool needsAck,
+ uint32_t from,
+ uint32_t to,
+ size_t left,
+ BufferInvalidationChannel &channel,
+ const std::shared_ptr<Accessor::Impl> &impl) {
+ if (left == 0) {
+ uint32_t msgId = 0;
+ if (needsAck) {
+ msgId = ++mInvalidationId;
+ if (msgId == 0) {
+ // wrap happens
+ msgId = ++mInvalidationId;
+ }
+ }
+ channel.postInvalidation(msgId, from, to);
+ sInvalidator.addAccessor(mId, impl);
+ } else {
+ // TODO: sending hint message?
+ Pending pending(needsAck, from, to, left, impl);
+ mPendings.push_back(pending);
+ }
+}
+
+void Accessor::Impl::BufferPool::Invalidation::onHandleAck() {
+ if (mInvalidationId != 0) {
+ std::set<int> deads;
+ for (auto it = mAcks.begin(); it != mAcks.end(); ++it) {
+ if (it->second != mInvalidationId) {
+ const sp<IObserver> observer = mObservers[it->first].promote();
+ if (observer) {
+ observer->onMessage(it->first, mInvalidationId);
+ } else {
+ deads.insert(it->first);
+ }
+ }
+ }
+ if (deads.size() > 0) {
+ for (auto it = deads.begin(); it != deads.end(); ++it) {
+ onClose(*it);
+ }
+ }
+ }
+ // All invalidation Ids are synced.
+ sInvalidator.delAccessor(mId);
+}
+
bool Accessor::Impl::BufferPool::handleOwnBuffer(
ConnectionId connectionId, BufferId bufferId) {
@@ -275,8 +402,15 @@
iter->second->mOwnerCount--;
if (iter->second->mOwnerCount == 0 &&
iter->second->mTransactionCount == 0) {
- mStats.onBufferUnused(iter->second->mAllocSize);
- mFreeBuffers.insert(bufferId);
+ if (!iter->second->mInvalidated) {
+ mStats.onBufferUnused(iter->second->mAllocSize);
+ mFreeBuffers.insert(bufferId);
+ } else {
+ mStats.onBufferUnused(iter->second->mAllocSize);
+ mStats.onBufferEvicted(iter->second->mAllocSize);
+ mBuffers.erase(iter);
+ mInvalidation.onBufferInvalidated(bufferId, mInvalidationChannel);
+ }
}
}
erase(&mUsingConnections, bufferId, connectionId);
@@ -352,8 +486,15 @@
bufferIter->second->mTransactionCount--;
if (bufferIter->second->mOwnerCount == 0
&& bufferIter->second->mTransactionCount == 0) {
- mStats.onBufferUnused(bufferIter->second->mAllocSize);
- mFreeBuffers.insert(message.bufferId);
+ if (!bufferIter->second->mInvalidated) {
+ mStats.onBufferUnused(bufferIter->second->mAllocSize);
+ mFreeBuffers.insert(message.bufferId);
+ } else {
+ mStats.onBufferUnused(bufferIter->second->mAllocSize);
+ mStats.onBufferEvicted(bufferIter->second->mAllocSize);
+ mBuffers.erase(bufferIter);
+ mInvalidation.onBufferInvalidated(message.bufferId, mInvalidationChannel);
+ }
}
mTransactions.erase(found);
}
@@ -400,7 +541,7 @@
ret = handleTransferResult(message);
break;
case BufferStatus::INVALIDATION_ACK:
- // TODO
+ mInvalidation.onAck(message.connectionId, message.bufferId);
break;
}
if (ret == false) {
@@ -423,8 +564,15 @@
if (bufferIter->second->mOwnerCount == 0 &&
bufferIter->second->mTransactionCount == 0) {
// TODO: handle freebuffer insert fail
- mStats.onBufferUnused(bufferIter->second->mAllocSize);
- mFreeBuffers.insert(bufferId);
+ if (!bufferIter->second->mInvalidated) {
+ mStats.onBufferUnused(bufferIter->second->mAllocSize);
+ mFreeBuffers.insert(bufferId);
+ } else {
+ mStats.onBufferUnused(bufferIter->second->mAllocSize);
+ mStats.onBufferEvicted(bufferIter->second->mAllocSize);
+ mBuffers.erase(bufferIter);
+ mInvalidation.onBufferInvalidated(bufferId, mInvalidationChannel);
+ }
}
}
}
@@ -446,8 +594,15 @@
if (bufferIter->second->mOwnerCount == 0 &&
bufferIter->second->mTransactionCount == 0) {
// TODO: handle freebuffer insert fail
- mStats.onBufferUnused(bufferIter->second->mAllocSize);
- mFreeBuffers.insert(bufferId);
+ if (!bufferIter->second->mInvalidated) {
+ mStats.onBufferUnused(bufferIter->second->mAllocSize);
+ mFreeBuffers.insert(bufferId);
+ } else {
+ mStats.onBufferUnused(bufferIter->second->mAllocSize);
+ mStats.onBufferEvicted(bufferIter->second->mAllocSize);
+ mBuffers.erase(bufferIter);
+ mInvalidation.onBufferInvalidated(bufferId, mInvalidationChannel);
+ }
}
mTransactions.erase(iter);
}
@@ -538,6 +693,121 @@
}
}
+void Accessor::Impl::BufferPool::invalidate(
+ bool needsAck, BufferId from, BufferId to,
+ const std::shared_ptr<Accessor::Impl> &impl) {
+ for (auto freeIt = mFreeBuffers.begin(); freeIt != mFreeBuffers.end();) {
+ if (isBufferInRange(from, to, *freeIt)) {
+ auto it = mBuffers.find(*freeIt);
+ if (it != mBuffers.end() &&
+ it->second->mOwnerCount == 0 && it->second->mTransactionCount == 0) {
+ mStats.onBufferEvicted(it->second->mAllocSize);
+ mBuffers.erase(it);
+ freeIt = mFreeBuffers.erase(freeIt);
+ continue;
+ } else {
+ ALOGW("bufferpool inconsistent!");
+ }
+ }
+ ++freeIt;
+ }
+
+ size_t left = 0;
+ for (auto it = mBuffers.begin(); it != mBuffers.end(); ++it) {
+ if (isBufferInRange(from, to, it->first)) {
+ it->second->invalidate();
+ ++left;
+ }
+ }
+ mInvalidation.onInvalidationRequest(needsAck, from, to, left, mInvalidationChannel, impl);
+}
+
+void Accessor::Impl::BufferPool::flush(const std::shared_ptr<Accessor::Impl> &impl) {
+ BufferId from = mStartSeq;
+ BufferId to = mSeq;
+ mStartSeq = mSeq;
+ // TODO: needsAck params
+ if (from != to) {
+ invalidate(true, from, to, impl);
+ }
+}
+
+void Accessor::Impl::invalidatorThread(
+ std::map<uint32_t, const std::weak_ptr<Accessor::Impl>> &accessors,
+ std::mutex &mutex,
+ std::condition_variable &cv,
+ bool &ready) {
+ while(true) {
+ std::map<uint32_t, const std::weak_ptr<Accessor::Impl>> copied;
+ {
+ std::unique_lock<std::mutex> lock(mutex);
+ if (!ready) {
+ cv.wait(lock);
+ }
+ copied.insert(accessors.begin(), accessors.end());
+ }
+ std::list<ConnectionId> erased;
+ for (auto it = copied.begin(); it != copied.end(); ++it) {
+ const std::shared_ptr<Accessor::Impl> impl = it->second.lock();
+ if (!impl) {
+ erased.push_back(it->first);
+ } else {
+ impl->handleInvalidateAck();
+ }
+ }
+ {
+ std::unique_lock<std::mutex> lock(mutex);
+ for (auto it = erased.begin(); it != erased.end(); ++it) {
+ accessors.erase(*it);
+ }
+ if (accessors.size() == 0) {
+ ready = false;
+ } else {
+ // prevent draining cpu.
+ lock.unlock();
+ std::this_thread::yield();
+ }
+ }
+ }
+}
+
+Accessor::Impl::AccessorInvalidator::AccessorInvalidator() : mReady(false) {
+ std::thread invalidator(
+ invalidatorThread,
+ std::ref(mAccessors),
+ std::ref(mMutex),
+ std::ref(mCv),
+ std::ref(mReady));
+ invalidator.detach();
+}
+
+void Accessor::Impl::AccessorInvalidator::addAccessor(
+ uint32_t accessorId, const std::weak_ptr<Accessor::Impl> &impl) {
+ bool notify = false;
+ std::unique_lock<std::mutex> lock(mMutex);
+ if (mAccessors.find(accessorId) == mAccessors.end()) {
+ if (!mReady) {
+ mReady = true;
+ notify = true;
+ }
+ mAccessors.insert(std::make_pair(accessorId, impl));
+ }
+ lock.unlock();
+ if (notify) {
+ mCv.notify_one();
+ }
+}
+
+void Accessor::Impl::AccessorInvalidator::delAccessor(uint32_t accessorId) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mAccessors.erase(accessorId);
+ if (mAccessors.size() == 0) {
+ mReady = false;
+ }
+}
+
+Accessor::Impl::AccessorInvalidator Accessor::Impl::sInvalidator;
+
} // namespace implementation
} // namespace V2_0
} // namespace bufferpool
diff --git a/media/bufferpool/2.0/AccessorImpl.h b/media/bufferpool/2.0/AccessorImpl.h
index 1d33880..6b03494 100644
--- a/media/bufferpool/2.0/AccessorImpl.h
+++ b/media/bufferpool/2.0/AccessorImpl.h
@@ -19,6 +19,7 @@
#include <map>
#include <set>
+#include <condition_variable>
#include "Accessor.h"
namespace android {
@@ -33,15 +34,20 @@
/**
* An implementation of a buffer pool accessor(or a buffer pool implementation.) */
-class Accessor::Impl {
+class Accessor::Impl
+ : public std::enable_shared_from_this<Accessor::Impl> {
public:
Impl(const std::shared_ptr<BufferPoolAllocator> &allocator);
~Impl();
ResultStatus connect(
- const sp<Accessor> &accessor, sp<Connection> *connection,
- ConnectionId *pConnectionId, const StatusDescriptor** fmqDescPtr);
+ const sp<Accessor> &accessor, const sp<IObserver> &observer,
+ sp<Connection> *connection,
+ ConnectionId *pConnectionId,
+ uint32_t *pMsgId,
+ const StatusDescriptor** statusDescPtr,
+ const InvalidationDescriptor** invDescPtr);
ResultStatus close(ConnectionId connectionId);
@@ -55,8 +61,14 @@
BufferId bufferId,
const native_handle_t** handle);
+ void flush();
+
void cleanUp(bool clearCache);
+ bool isValid();
+
+ void handleInvalidateAck();
+
private:
// ConnectionId = pid : (timestamp_created + seqId)
// in order to guarantee uniqueness for each connection
@@ -78,7 +90,10 @@
int64_t mLastCleanUpUs;
int64_t mLastLogUs;
BufferId mSeq;
+ BufferId mStartSeq;
+ bool mValid;
BufferStatusObserver mObserver;
+ BufferInvalidationChannel mInvalidationChannel;
std::map<ConnectionId, std::set<BufferId>> mUsingBuffers;
std::map<BufferId, std::set<ConnectionId>> mUsingConnections;
@@ -95,6 +110,54 @@
std::map<BufferId, std::unique_ptr<InternalBuffer>> mBuffers;
std::set<BufferId> mFreeBuffers;
+ struct Invalidation {
+ static std::atomic<std::uint32_t> sSeqId;
+
+ struct Pending {
+ bool mNeedsAck;
+ uint32_t mFrom;
+ uint32_t mTo;
+ size_t mLeft;
+ const std::weak_ptr<Accessor::Impl> mImpl;
+ Pending(bool needsAck, uint32_t from, uint32_t to, size_t left,
+ const std::shared_ptr<Accessor::Impl> &impl)
+ : mNeedsAck(needsAck),
+ mFrom(from),
+ mTo(to),
+ mLeft(left),
+ mImpl(impl)
+ {}
+
+ bool invalidate(uint32_t bufferId) {
+ return isBufferInRange(mFrom, mTo, bufferId) && --mLeft == 0;
+ }
+ };
+
+ std::list<Pending> mPendings;
+ std::map<ConnectionId, uint32_t> mAcks;
+ std::map<ConnectionId, const wp<IObserver>> mObservers;
+ uint32_t mInvalidationId;
+ uint32_t mId;
+
+ Invalidation() : mInvalidationId(0), mId(sSeqId.fetch_add(1)) {}
+
+ void onConnect(ConnectionId conId, const sp<IObserver> &observer);
+
+ void onClose(ConnectionId conId);
+
+ void onAck(ConnectionId conId, uint32_t msgId);
+
+ void onBufferInvalidated(
+ BufferId bufferId,
+ BufferInvalidationChannel &channel);
+
+ void onInvalidationRequest(
+ bool needsAck, uint32_t from, uint32_t to, size_t left,
+ BufferInvalidationChannel &channel,
+ const std::shared_ptr<Accessor::Impl> &impl);
+
+ void onHandleAck();
+ } mInvalidation;
/// Buffer pool statistics which tracks allocation and transfer statistics.
struct Stats {
/// Total size of allocations which are used or available to use.
@@ -164,6 +227,13 @@
}
} mStats;
+ bool isValid() {
+ return mValid;
+ }
+
+ void invalidate(bool needsAck, BufferId from, BufferId to,
+ const std::shared_ptr<Accessor::Impl> &impl);
+
public:
/** Creates a buffer pool. */
BufferPool();
@@ -286,8 +356,33 @@
*/
void cleanUp(bool clearCache = false);
+ /**
+ * Processes pending buffer status messages and invalidate all current
+ * free buffers. Active buffers are invalidated after being inactive.
+ */
+ void flush(const std::shared_ptr<Accessor::Impl> &impl);
+
friend class Accessor::Impl;
} mBufferPool;
+
+ struct AccessorInvalidator {
+ std::map<uint32_t, const std::weak_ptr<Accessor::Impl>> mAccessors;
+ std::mutex mMutex;
+ std::condition_variable mCv;
+ bool mReady;
+
+ AccessorInvalidator();
+ void addAccessor(uint32_t accessorId, const std::weak_ptr<Accessor::Impl> &impl);
+ void delAccessor(uint32_t accessorId);
+ };
+
+ static AccessorInvalidator sInvalidator;
+
+ static void invalidatorThread(
+ std::map<uint32_t, const std::weak_ptr<Accessor::Impl>> &accessors,
+ std::mutex &mutex,
+ std::condition_variable &cv,
+ bool &ready);
};
} // namespace implementation
diff --git a/media/bufferpool/2.0/Android.bp b/media/bufferpool/2.0/Android.bp
index 413125a..cd4e06e 100644
--- a/media/bufferpool/2.0/Android.bp
+++ b/media/bufferpool/2.0/Android.bp
@@ -8,6 +8,7 @@
"BufferStatus.cpp",
"ClientManager.cpp",
"Connection.cpp",
+ "Observer.cpp",
],
export_include_dirs: [
"include",
diff --git a/media/bufferpool/2.0/BufferPoolClient.cpp b/media/bufferpool/2.0/BufferPoolClient.cpp
index 0f763f7..c80beff 100644
--- a/media/bufferpool/2.0/BufferPoolClient.cpp
+++ b/media/bufferpool/2.0/BufferPoolClient.cpp
@@ -36,9 +36,9 @@
class BufferPoolClient::Impl
: public std::enable_shared_from_this<BufferPoolClient::Impl> {
public:
- explicit Impl(const sp<Accessor> &accessor);
+ explicit Impl(const sp<Accessor> &accessor, const sp<IObserver> &observer);
- explicit Impl(const sp<IAccessor> &accessor);
+ explicit Impl(const sp<IAccessor> &accessor, const sp<IObserver> &observer);
bool isValid() {
return mValid;
@@ -58,6 +58,10 @@
bool isActive(int64_t *lastTransactionUs, bool clearCache);
+ void receiveInvalidation(uint32_t msgID);
+
+ ResultStatus flush();
+
ResultStatus allocate(const std::vector<uint8_t> ¶ms,
native_handle_t **handle,
std::shared_ptr<BufferPoolData> *buffer);
@@ -83,10 +87,14 @@
void trySyncFromRemote();
- bool syncReleased();
+ bool syncReleased(uint32_t msgId = 0);
void evictCaches(bool clearCache = false);
+ void invalidateBuffer(BufferId id);
+
+ void invalidateRange(BufferId from, BufferId to);
+
ResultStatus allocateBufferHandle(
const std::vector<uint8_t>& params, BufferId *bufferId,
native_handle_t **handle);
@@ -106,6 +114,7 @@
uint32_t mSeqId;
ConnectionId mConnectionId;
int64_t mLastEvictCacheUs;
+ std::unique_ptr<BufferInvalidationListener> mInvalidationListener;
// CachedBuffers
struct BufferCache {
@@ -130,12 +139,16 @@
} mCache;
// FMQ - release notifier
- struct {
+ struct ReleaseCache {
std::mutex mLock;
// TODO: use only one list?(using one list may dealy sending messages?)
std::list<BufferId> mReleasingIds;
std::list<BufferId> mReleasedIds;
+ uint32_t mInvalidateId; // TODO: invalidation ACK to bufferpool
+ bool mInvalidateAck;
std::unique_ptr<BufferStatusChannel> mStatusChannel;
+
+ ReleaseCache() : mInvalidateId(0), mInvalidateAck(true) {}
} mReleasing;
// This lock is held during synchronization from remote side.
@@ -162,7 +175,6 @@
struct BufferPoolClient::Impl::ClientBuffer {
private:
- bool mInvalidated; // TODO: implement
int64_t mExpireUs;
bool mHasCache;
ConnectionId mConnectionId;
@@ -177,9 +189,8 @@
public:
ClientBuffer(
ConnectionId connectionId, BufferId id, native_handle_t *handle)
- : mInvalidated(false), mHasCache(false),
- mConnectionId(connectionId), mId(id), mHandle(handle) {
- (void)mInvalidated;
+ : mHasCache(false), mConnectionId(connectionId),
+ mId(id), mHandle(handle) {
mExpireUs = getTimestampNow() + kCacheTtlUs;
}
@@ -190,6 +201,10 @@
}
}
+ BufferId id() const {
+ return mId;
+ }
+
bool expire() const {
int64_t now = getTimestampNow();
return now >= mExpireUs;
@@ -244,41 +259,53 @@
}
};
-BufferPoolClient::Impl::Impl(const sp<Accessor> &accessor)
+BufferPoolClient::Impl::Impl(const sp<Accessor> &accessor, const sp<IObserver> &observer)
: mLocal(true), mValid(false), mAccessor(accessor), mSeqId(0),
mLastEvictCacheUs(getTimestampNow()) {
- const StatusDescriptor *fmqDesc;
+ const StatusDescriptor *statusDesc;
+ const InvalidationDescriptor *invDesc;
ResultStatus status = accessor->connect(
- &mLocalConnection, &mConnectionId, &fmqDesc, true);
+ observer, true,
+ &mLocalConnection, &mConnectionId, &mReleasing.mInvalidateId,
+ &statusDesc, &invDesc);
if (status == ResultStatus::OK) {
mReleasing.mStatusChannel =
- std::make_unique<BufferStatusChannel>(*fmqDesc);
+ std::make_unique<BufferStatusChannel>(*statusDesc);
+ mInvalidationListener =
+ std::make_unique<BufferInvalidationListener>(*invDesc);
mValid = mReleasing.mStatusChannel &&
- mReleasing.mStatusChannel->isValid();
+ mReleasing.mStatusChannel->isValid() &&
+ mInvalidationListener &&
+ mInvalidationListener->isValid();
}
}
-BufferPoolClient::Impl::Impl(const sp<IAccessor> &accessor)
+BufferPoolClient::Impl::Impl(const sp<IAccessor> &accessor, const sp<IObserver> &observer)
: mLocal(false), mValid(false), mAccessor(accessor), mSeqId(0),
mLastEvictCacheUs(getTimestampNow()) {
bool valid = false;
- sp<IObserver> observer; // TODO
sp<IConnection>& outConnection = mRemoteConnection;
ConnectionId& id = mConnectionId;
+ uint32_t& outMsgId = mReleasing.mInvalidateId;
std::unique_ptr<BufferStatusChannel>& outChannel =
mReleasing.mStatusChannel;
+ std::unique_ptr<BufferInvalidationListener>& outObserver =
+ mInvalidationListener;
Return<void> transResult = accessor->connect(
observer,
- [&valid, &outConnection, &id, &outChannel]
+ [&valid, &outConnection, &id, &outMsgId, &outChannel, &outObserver]
(ResultStatus status, sp<IConnection> connection,
- ConnectionId connectionId, const StatusDescriptor& desc,
+ ConnectionId connectionId, uint32_t msgId,
+ const StatusDescriptor& statusDesc,
const InvalidationDescriptor& invDesc) {
- (void) invDesc;
if (status == ResultStatus::OK) {
outConnection = connection;
id = connectionId;
- outChannel = std::make_unique<BufferStatusChannel>(desc);
- if (outChannel && outChannel->isValid()) {
+ outMsgId = msgId;
+ outChannel = std::make_unique<BufferStatusChannel>(statusDesc);
+ outObserver = std::make_unique<BufferInvalidationListener>(invDesc);
+ if (outChannel && outChannel->isValid() &&
+ outObserver && outObserver->isValid()) {
valid = true;
}
}
@@ -302,6 +329,24 @@
return active;
}
+void BufferPoolClient::Impl::receiveInvalidation(uint32_t messageId) {
+ std::lock_guard<std::mutex> lock(mCache.mLock);
+ syncReleased(messageId);
+ // TODO: evict cache required?
+}
+
+ResultStatus BufferPoolClient::Impl::flush() {
+ if (!mLocal || !mLocalConnection || !mValid) {
+ return ResultStatus::CRITICAL_ERROR;
+ }
+ {
+ std::unique_lock<std::mutex> lock(mCache.mLock);
+ syncReleased();
+ evictCaches();
+ return mLocalConnection->flush();
+ }
+}
+
ResultStatus BufferPoolClient::Impl::allocate(
const std::vector<uint8_t> ¶ms,
native_handle_t **pHandle,
@@ -455,6 +500,11 @@
bool BufferPoolClient::Impl::postSend(
BufferId bufferId, ConnectionId receiver,
TransactionId *transactionId, int64_t *timestampUs) {
+ {
+ // TODO: don't need to call syncReleased every time
+ std::lock_guard<std::mutex> lock(mCache.mLock);
+ syncReleased();
+ }
bool ret = false;
bool needsSync = false;
{
@@ -538,34 +588,74 @@
}
// should have mCache.mLock
-bool BufferPoolClient::Impl::syncReleased() {
- std::lock_guard<std::mutex> lock(mReleasing.mLock);
- if (mReleasing.mReleasingIds.size() > 0) {
- mReleasing.mStatusChannel->postBufferRelease(
- mConnectionId, mReleasing.mReleasingIds,
- mReleasing.mReleasedIds);
- }
- if (mReleasing.mReleasedIds.size() > 0) {
- for (BufferId& id: mReleasing.mReleasedIds) {
- ALOGV("client release buffer %lld - %u", (long long)mConnectionId, id);
- auto found = mCache.mBuffers.find(id);
- if (found != mCache.mBuffers.end()) {
- if (found->second->onCacheRelease()) {
- mCache.decActive_l();
+bool BufferPoolClient::Impl::syncReleased(uint32_t messageId) {
+ bool cleared = false;
+ {
+ std::lock_guard<std::mutex> lock(mReleasing.mLock);
+ if (mReleasing.mReleasingIds.size() > 0) {
+ mReleasing.mStatusChannel->postBufferRelease(
+ mConnectionId, mReleasing.mReleasingIds,
+ mReleasing.mReleasedIds);
+ }
+ if (mReleasing.mReleasedIds.size() > 0) {
+ for (BufferId& id: mReleasing.mReleasedIds) {
+ ALOGV("client release buffer %lld - %u", (long long)mConnectionId, id);
+ auto found = mCache.mBuffers.find(id);
+ if (found != mCache.mBuffers.end()) {
+ if (found->second->onCacheRelease()) {
+ mCache.decActive_l();
+ } else {
+ // should not happen!
+ ALOGW("client %lld cache release status inconsitent!",
+ (long long)mConnectionId);
+ }
} else {
// should not happen!
- ALOGW("client %lld cache release status inconsitent!",
- (long long)mConnectionId);
+ ALOGW("client %lld cache status inconsitent!", (long long)mConnectionId);
}
+ }
+ mReleasing.mReleasedIds.clear();
+ cleared = true;
+ }
+ }
+ std::vector<BufferInvalidationMessage> invalidations;
+ mInvalidationListener->getInvalidations(invalidations);
+ uint32_t lastMsgId = 0;
+ if (invalidations.size() > 0) {
+ for (auto it = invalidations.begin(); it != invalidations.end(); ++it) {
+ if (it->messageId != 0) {
+ lastMsgId = it->messageId;
+ }
+ if (it->fromBufferId == it->toBufferId) {
+ // TODO: handle fromBufferId = UINT32_MAX
+ invalidateBuffer(it->fromBufferId);
} else {
- // should not happen!
- ALOGW("client %lld cache status inconsitent!", (long long)mConnectionId);
+ invalidateRange(it->fromBufferId, it->toBufferId);
}
}
- mReleasing.mReleasedIds.clear();
- return true;
}
- return false;
+ {
+ std::lock_guard<std::mutex> lock(mReleasing.mLock);
+ if (lastMsgId != 0) {
+ if (isMessageLater(lastMsgId, mReleasing.mInvalidateId)) {
+ mReleasing.mInvalidateId = lastMsgId;
+ mReleasing.mInvalidateAck = false;
+ }
+ } else if (messageId != 0) {
+ // messages are drained.
+ if (isMessageLater(messageId, mReleasing.mInvalidateId)) {
+ mReleasing.mInvalidateId = lastMsgId;
+ mReleasing.mInvalidateAck = true;
+ }
+ }
+ if (!mReleasing.mInvalidateAck) {
+ // post ACK
+ mReleasing.mStatusChannel->postBufferInvalidateAck(
+ mConnectionId,
+ mReleasing.mInvalidateId, &mReleasing.mInvalidateAck);
+ }
+ }
+ return cleared;
}
// should have mCache.mLock
@@ -587,6 +677,49 @@
}
}
+// should have mCache.mLock
+void BufferPoolClient::Impl::invalidateBuffer(BufferId id) {
+ for (auto it = mCache.mBuffers.begin(); it != mCache.mBuffers.end(); ++it) {
+ if (id == it->second->id()) {
+ if (!it->second->hasCache()) {
+ mCache.mBuffers.erase(it);
+ ALOGV("cache invalidated %lld : buffer %u",
+ (long long)mConnectionId, id);
+ } else {
+ ALOGW("Inconsitent invalidation %lld : activer buffer!! %u",
+ (long long)mConnectionId, (unsigned int)id);
+ }
+ break;
+ }
+ }
+}
+
+// should have mCache.mLock
+void BufferPoolClient::Impl::invalidateRange(BufferId from, BufferId to) {
+ size_t invalidated = 0;
+ for (auto it = mCache.mBuffers.begin(); it != mCache.mBuffers.end();) {
+ if (!it->second->hasCache()) {
+ BufferId bid = it->second->id();
+ if (from < to) {
+ if (from <= bid && bid < to) {
+ ++invalidated;
+ it = mCache.mBuffers.erase(it);
+ continue;
+ }
+ } else {
+ if (from <= bid || bid < to) {
+ ++invalidated;
+ it = mCache.mBuffers.erase(it);
+ continue;
+ }
+ }
+ }
+ ++it;
+ }
+ ALOGV("cache invalidated %lld : # of invalidated %zu",
+ (long long)mConnectionId, invalidated);
+}
+
ResultStatus BufferPoolClient::Impl::allocateBufferHandle(
const std::vector<uint8_t>& params, BufferId *bufferId,
native_handle_t** handle) {
@@ -629,12 +762,14 @@
}
-BufferPoolClient::BufferPoolClient(const sp<Accessor> &accessor) {
- mImpl = std::make_shared<Impl>(accessor);
+BufferPoolClient::BufferPoolClient(const sp<Accessor> &accessor,
+ const sp<IObserver> &observer) {
+ mImpl = std::make_shared<Impl>(accessor, observer);
}
-BufferPoolClient::BufferPoolClient(const sp<IAccessor> &accessor) {
- mImpl = std::make_shared<Impl>(accessor);
+BufferPoolClient::BufferPoolClient(const sp<IAccessor> &accessor,
+ const sp<IObserver> &observer) {
+ mImpl = std::make_shared<Impl>(accessor, observer);
}
BufferPoolClient::~BufferPoolClient() {
@@ -672,6 +807,19 @@
return ResultStatus::CRITICAL_ERROR;
}
+void BufferPoolClient::receiveInvalidation(uint32_t msgId) {
+ if (isValid()) {
+ mImpl->receiveInvalidation(msgId);
+ }
+}
+
+ResultStatus BufferPoolClient::flush() {
+ if (isValid()) {
+ return mImpl->flush();
+ }
+ return ResultStatus::CRITICAL_ERROR;
+}
+
ResultStatus BufferPoolClient::allocate(
const std::vector<uint8_t> ¶ms,
native_handle_t **handle,
diff --git a/media/bufferpool/2.0/BufferPoolClient.h b/media/bufferpool/2.0/BufferPoolClient.h
index 1889ea3..e8d9ae6 100644
--- a/media/bufferpool/2.0/BufferPoolClient.h
+++ b/media/bufferpool/2.0/BufferPoolClient.h
@@ -49,7 +49,8 @@
* Creates a buffer pool client from a local buffer pool
* (via ClientManager#create).
*/
- explicit BufferPoolClient(const sp<Accessor> &accessor);
+ explicit BufferPoolClient(const sp<Accessor> &accessor,
+ const sp<IObserver> &observer);
/**
* Creates a buffer pool client from a remote buffer pool
@@ -57,7 +58,8 @@
* Note: A buffer pool client created with remote buffer pool cannot
* allocate a buffer.
*/
- explicit BufferPoolClient(const sp<IAccessor> &accessor);
+ explicit BufferPoolClient(const sp<IAccessor> &accessor,
+ const sp<IObserver> &observer);
/** Destructs a buffer pool client. */
~BufferPoolClient();
@@ -73,6 +75,10 @@
ResultStatus getAccessor(sp<IAccessor> *accessor);
+ void receiveInvalidation(uint32_t msgId);
+
+ ResultStatus flush();
+
ResultStatus allocate(const std::vector<uint8_t> ¶ms,
native_handle_t **handle,
std::shared_ptr<BufferPoolData> *buffer);
@@ -92,6 +98,7 @@
std::shared_ptr<Impl> mImpl;
friend struct ClientManager;
+ friend struct Observer;
};
} // namespace implementation
diff --git a/media/bufferpool/2.0/BufferStatus.cpp b/media/bufferpool/2.0/BufferStatus.cpp
index 0d3f5a3..6937260 100644
--- a/media/bufferpool/2.0/BufferStatus.cpp
+++ b/media/bufferpool/2.0/BufferStatus.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "BufferPoolStatus"
//#define LOG_NDEBUG 0
+#include <thread>
#include <time.h>
#include "BufferStatus.h"
@@ -37,6 +38,18 @@
return stamp;
}
+bool isMessageLater(uint32_t curMsgId, uint32_t prevMsgId) {
+ return curMsgId != prevMsgId && curMsgId - prevMsgId < prevMsgId - curMsgId;
+}
+
+bool isBufferInRange(BufferId from, BufferId to, BufferId bufferId) {
+ if (from < to) {
+ return from <= bufferId && bufferId < to;
+ } else { // wrap happens
+ return from <= bufferId || bufferId < to;
+ }
+}
+
static constexpr int kNumElementsInQueue = 1024*16;
static constexpr int kMinElementsToSyncInQueue = 128;
@@ -139,6 +152,29 @@
}
}
+void BufferStatusChannel::postBufferInvalidateAck(
+ ConnectionId connectionId,
+ uint32_t invalidateId,
+ bool *invalidated) {
+ if (mValid && !*invalidated) {
+ size_t avail = mBufferStatusQueue->availableToWrite();
+ if (avail > 0) {
+ BufferStatusMessage message;
+ message.newStatus = BufferStatus::INVALIDATION_ACK;
+ message.bufferId = invalidateId;
+ message.connectionId = connectionId;
+ if (!mBufferStatusQueue->write(&message, 1)) {
+ // Since avaliable # of writes are already confirmed,
+ // this should not happen.
+ // TODO: error handing?
+ ALOGW("FMQ message cannot be sent from %lld", (long long)connectionId);
+ return;
+ }
+ *invalidated = true;
+ }
+ }
+}
+
bool BufferStatusChannel::postBufferStatusMessage(
TransactionId transactionId, BufferId bufferId,
BufferStatus status, ConnectionId connectionId, ConnectionId targetId,
@@ -182,6 +218,83 @@
return false;
}
+BufferInvalidationListener::BufferInvalidationListener(
+ const InvalidationDescriptor &fmqDesc) {
+ std::unique_ptr<BufferInvalidationQueue> queue =
+ std::make_unique<BufferInvalidationQueue>(fmqDesc);
+ if (!queue || queue->isValid() == false) {
+ mValid = false;
+ return;
+ }
+ mValid = true;
+ mBufferInvalidationQueue = std::move(queue);
+ // drain previous messages
+ size_t avail = std::min(
+ mBufferInvalidationQueue->availableToRead(), (size_t) kNumElementsInQueue);
+ std::vector<BufferInvalidationMessage> temp(avail);
+ if (avail > 0) {
+ mBufferInvalidationQueue->read(temp.data(), avail);
+ }
+}
+
+void BufferInvalidationListener::getInvalidations(
+ std::vector<BufferInvalidationMessage> &messages) {
+ // Try twice in case of overflow.
+ // TODO: handling overflow though it may not happen.
+ for (int i = 0; i < 2; ++i) {
+ size_t avail = std::min(
+ mBufferInvalidationQueue->availableToRead(), (size_t) kNumElementsInQueue);
+ if (avail > 0) {
+ std::vector<BufferInvalidationMessage> temp(avail);
+ if (mBufferInvalidationQueue->read(temp.data(), avail)) {
+ messages.reserve(messages.size() + avail);
+ for (auto it = temp.begin(); it != temp.end(); ++it) {
+ messages.push_back(*it);
+ }
+ break;
+ }
+ } else {
+ return;
+ }
+ }
+}
+
+bool BufferInvalidationListener::isValid() {
+ return mValid;
+}
+
+BufferInvalidationChannel::BufferInvalidationChannel()
+ : mValid(true),
+ mBufferInvalidationQueue(
+ std::make_unique<BufferInvalidationQueue>(kNumElementsInQueue, true)) {
+ if (!mBufferInvalidationQueue || mBufferInvalidationQueue->isValid() == false) {
+ mValid = false;
+ }
+}
+
+bool BufferInvalidationChannel::isValid() {
+ return mValid;
+}
+
+void BufferInvalidationChannel::getDesc(const InvalidationDescriptor **fmqDescPtr) {
+ if (mValid) {
+ *fmqDescPtr = mBufferInvalidationQueue->getDesc();
+ } else {
+ *fmqDescPtr = nullptr;
+ }
+}
+
+void BufferInvalidationChannel::postInvalidation(
+ uint32_t msgId, BufferId fromId, BufferId toId) {
+ BufferInvalidationMessage message;
+
+ message.messageId = msgId;
+ message.fromBufferId = fromId;
+ message.toBufferId = toId;
+ // TODO: handle failure (it does not happen normally.)
+ mBufferInvalidationQueue->write(&message);
+}
+
} // namespace implementation
} // namespace V2_0
} // namespace bufferpool
diff --git a/media/bufferpool/2.0/BufferStatus.h b/media/bufferpool/2.0/BufferStatus.h
index 777a320..fa65838 100644
--- a/media/bufferpool/2.0/BufferStatus.h
+++ b/media/bufferpool/2.0/BufferStatus.h
@@ -37,9 +37,13 @@
/** Returns monotonic timestamp in Us since fixed point in time. */
int64_t getTimestampNow();
+bool isMessageLater(uint32_t curMsgId, uint32_t prevMsgId);
+
+bool isBufferInRange(BufferId from, BufferId to, BufferId bufferId);
+
/**
- * A collection of FMQ for a buffer pool. buffer ownership/status change
- * messages are sent via the FMQs from the clients.
+ * A collection of buffer status message FMQ for a buffer pool. buffer
+ * ownership/status change messages are sent via the FMQs from the clients.
*/
class BufferStatusObserver {
private:
@@ -47,7 +51,8 @@
mBufferStatusQueues;
public:
- /** Creates an FMQ for the specified connection(client).
+ /** Creates a buffer status message FMQ for the specified
+ * connection(client).
*
* @param connectionId connection Id of the specified client.
* @param fmqDescPtr double ptr of created FMQ's descriptor.
@@ -58,7 +63,8 @@
*/
ResultStatus open(ConnectionId id, const StatusDescriptor** fmqDescPtr);
- /** Closes an FMQ for the specified connection(client).
+ /** Closes a buffer status message FMQ for the specified
+ * connection(client).
*
* @param connectionId connection Id of the specified client.
*
@@ -75,8 +81,8 @@
};
/**
- * An FMQ for a buffer pool client. Buffer ownership/status change messages
- * are sent via the fmq to the buffer pool.
+ * A buffer status message FMQ for a buffer pool client. Buffer ownership/status
+ * change messages are sent via the fmq to the buffer pool.
*/
class BufferStatusChannel {
private:
@@ -85,7 +91,8 @@
public:
/**
- * Connects to an FMQ from a descriptor of the created FMQ.
+ * Connects to a buffer status message FMQ from a descriptor of
+ * the created FMQ.
*
* @param fmqDesc Descriptor of the created FMQ.
*/
@@ -131,6 +138,86 @@
ConnectionId connectionId,
ConnectionId targetId,
std::list<BufferId> &pending, std::list<BufferId> &posted);
+
+ /**
+ * Posts a buffer invaliadation messge to the buffer pool.
+ *
+ * @param connectionId connection Id of the client.
+ * @param invalidateId invalidation ack to the buffer pool.
+ * if invalidation id is zero, the ack will not be
+ * posted.
+ * @param invalidated sets {@code true} only when the invalidation ack is
+ * posted.
+ */
+ void postBufferInvalidateAck(
+ ConnectionId connectionId,
+ uint32_t invalidateId,
+ bool *invalidated);
+};
+
+/**
+ * A buffer invalidation FMQ for a buffer pool client. Buffer invalidation
+ * messages are received via the fmq from the buffer pool. Buffer invalidation
+ * messages are handled as soon as possible.
+ */
+class BufferInvalidationListener {
+private:
+ bool mValid;
+ std::unique_ptr<BufferInvalidationQueue> mBufferInvalidationQueue;
+
+public:
+ /**
+ * Connects to a buffer invalidation FMQ from a descriptor of the created FMQ.
+ *
+ * @param fmqDesc Descriptor of the created FMQ.
+ */
+ BufferInvalidationListener(const InvalidationDescriptor &fmqDesc);
+
+ /** Retrieves all pending buffer invalidation messages from the buffer pool.
+ *
+ * @param messages retrieved pending messages.
+ */
+ void getInvalidations(std::vector<BufferInvalidationMessage> &messages);
+
+ /** Returns whether the FMQ is connected succesfully. */
+ bool isValid();
+};
+
+/**
+ * A buffer invalidation FMQ for a buffer pool. A buffer pool will send buffer
+ * invalidation messages to the clients via the FMQ. The FMQ is shared among
+ * buffer pool clients.
+ */
+class BufferInvalidationChannel {
+private:
+ bool mValid;
+ std::unique_ptr<BufferInvalidationQueue> mBufferInvalidationQueue;
+
+public:
+ /**
+ * Creates a buffer invalidation FMQ for a buffer pool.
+ */
+ BufferInvalidationChannel();
+
+ /** Returns whether the FMQ is connected succesfully. */
+ bool isValid();
+
+ /**
+ * Retrieves the descriptor of a buffer invalidation FMQ. the descriptor may
+ * be passed to the client for buffer invalidation handling.
+ *
+ * @param fmqDescPtr double ptr of created FMQ's descriptor.
+ */
+ void getDesc(const InvalidationDescriptor **fmqDescPtr);
+
+ /** Posts a buffer invalidation for invalidated buffers.
+ *
+ * @param msgId Invalidation message id which is used when clients send
+ * acks back via BufferStatusMessage
+ * @param fromId The start bufferid of the invalidated buffers(inclusive)
+ * @param toId The end bufferId of the invalidated buffers(inclusive)
+ */
+ void postInvalidation(uint32_t msgId, BufferId fromId, BufferId toId);
};
} // namespace implementation
diff --git a/media/bufferpool/2.0/ClientManager.cpp b/media/bufferpool/2.0/ClientManager.cpp
index eeaf093..f8531d8 100644
--- a/media/bufferpool/2.0/ClientManager.cpp
+++ b/media/bufferpool/2.0/ClientManager.cpp
@@ -23,6 +23,7 @@
#include <unistd.h>
#include <utils/Log.h>
#include "BufferPoolClient.h"
+#include "Observer.h"
namespace android {
namespace hardware {
@@ -106,6 +107,8 @@
ResultStatus close(ConnectionId connectionId);
+ ResultStatus flush(ConnectionId connectionId);
+
ResultStatus allocate(ConnectionId connectionId,
const std::vector<uint8_t> ¶ms,
native_handle_t **handle,
@@ -153,10 +156,13 @@
mClients;
} mActive;
+ sp<Observer> mObserver;
+
ClientManagerCookieHolder mRemoteClientCookies;
};
-ClientManager::Impl::Impl() {}
+ClientManager::Impl::Impl()
+ : mObserver(new Observer()) {}
ResultStatus ClientManager::Impl::registerSender(
const sp<IAccessor> &accessor, ConnectionId *pConnectionId) {
@@ -185,7 +191,7 @@
lock.unlock();
ResultStatus result = ResultStatus::OK;
const std::shared_ptr<BufferPoolClient> client =
- std::make_shared<BufferPoolClient>(accessor);
+ std::make_shared<BufferPoolClient>(accessor, mObserver);
lock.lock();
if (!client) {
result = ResultStatus::NO_MEMORY;
@@ -197,6 +203,7 @@
const std::weak_ptr<BufferPoolClient> wclient = client;
mCache.mClients.push_back(std::make_pair(accessor, wclient));
ConnectionId conId = client->getConnectionId();
+ mObserver->addClient(conId, wclient);
{
std::lock_guard<std::mutex> lock(mActive.mMutex);
mActive.mClients.insert(std::make_pair(conId, client));
@@ -266,8 +273,9 @@
if (!accessor || !accessor->isValid()) {
return ResultStatus::CRITICAL_ERROR;
}
+ // TODO: observer is local. use direct call instead of hidl call.
std::shared_ptr<BufferPoolClient> client =
- std::make_shared<BufferPoolClient>(accessor);
+ std::make_shared<BufferPoolClient>(accessor, mObserver);
if (!client || !client->isValid()) {
return ResultStatus::CRITICAL_ERROR;
}
@@ -280,6 +288,7 @@
const std::weak_ptr<BufferPoolClient> wclient = client;
mCache.mClients.push_back(std::make_pair(accessor, wclient));
ConnectionId conId = client->getConnectionId();
+ mObserver->addClient(conId, wclient);
{
std::lock_guard<std::mutex> lock(mActive.mMutex);
mActive.mClients.insert(std::make_pair(conId, client));
@@ -291,12 +300,13 @@
}
ResultStatus ClientManager::Impl::close(ConnectionId connectionId) {
- std::lock_guard<std::mutex> lock1(mCache.mMutex);
- std::lock_guard<std::mutex> lock2(mActive.mMutex);
+ std::unique_lock<std::mutex> lock1(mCache.mMutex);
+ std::unique_lock<std::mutex> lock2(mActive.mMutex);
auto it = mActive.mClients.find(connectionId);
if (it != mActive.mClients.end()) {
sp<IAccessor> accessor;
it->second->getAccessor(&accessor);
+ std::shared_ptr<BufferPoolClient> closing = it->second;
mActive.mClients.erase(connectionId);
for (auto cit = mCache.mClients.begin(); cit != mCache.mClients.end();) {
// clean up dead client caches
@@ -307,11 +317,27 @@
cit++;
}
}
+ lock2.unlock();
+ lock1.unlock();
+ closing->flush();
return ResultStatus::OK;
}
return ResultStatus::NOT_FOUND;
}
+ResultStatus ClientManager::Impl::flush(ConnectionId connectionId) {
+ std::shared_ptr<BufferPoolClient> client;
+ {
+ std::lock_guard<std::mutex> lock(mActive.mMutex);
+ auto it = mActive.mClients.find(connectionId);
+ if (it == mActive.mClients.end()) {
+ return ResultStatus::NOT_FOUND;
+ }
+ client = it->second;
+ }
+ return client->flush();
+}
+
ResultStatus ClientManager::Impl::allocate(
ConnectionId connectionId, const std::vector<uint8_t> ¶ms,
native_handle_t **handle, std::shared_ptr<BufferPoolData> *buffer) {
@@ -461,6 +487,13 @@
return ResultStatus::CRITICAL_ERROR;
}
+ResultStatus ClientManager::flush(ConnectionId connectionId) {
+ if (mImpl) {
+ return mImpl->flush(connectionId);
+ }
+ return ResultStatus::CRITICAL_ERROR;
+}
+
ResultStatus ClientManager::allocate(
ConnectionId connectionId, const std::vector<uint8_t> ¶ms,
native_handle_t **handle, std::shared_ptr<BufferPoolData> *buffer) {
diff --git a/media/bufferpool/2.0/Connection.cpp b/media/bufferpool/2.0/Connection.cpp
index cd837a1..6bd0e79 100644
--- a/media/bufferpool/2.0/Connection.cpp
+++ b/media/bufferpool/2.0/Connection.cpp
@@ -60,6 +60,13 @@
}
}
+ResultStatus Connection::flush() {
+ if (mInitialized && mAccessor) {
+ return mAccessor->flush();
+ }
+ return ResultStatus::CRITICAL_ERROR;
+}
+
ResultStatus Connection::allocate(
const std::vector<uint8_t> ¶ms, BufferId *bufferId,
const native_handle_t **handle) {
diff --git a/media/bufferpool/2.0/Connection.h b/media/bufferpool/2.0/Connection.h
index e2b47f1..8507749 100644
--- a/media/bufferpool/2.0/Connection.h
+++ b/media/bufferpool/2.0/Connection.h
@@ -44,6 +44,11 @@
Return<void> fetch(uint64_t transactionId, uint32_t bufferId, fetch_cb _hidl_cb) override;
/**
+ * Invalidates all buffers which are active and/or are ready to be recycled.
+ */
+ ResultStatus flush();
+
+ /**
* Allocates a buffer using the specified parameters. Recycles a buffer if
* it is possible. The returned buffer can be transferred to other remote
* clients(Connection).
diff --git a/media/bufferpool/2.0/Observer.cpp b/media/bufferpool/2.0/Observer.cpp
new file mode 100644
index 0000000..5b23160
--- /dev/null
+++ b/media/bufferpool/2.0/Observer.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Observer.h"
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace bufferpool {
+namespace V2_0 {
+namespace implementation {
+
+Observer::Observer() {
+}
+
+Observer::~Observer() {
+}
+
+// Methods from ::android::hardware::media::bufferpool::V2_0::IObserver follow.
+Return<void> Observer::onMessage(int64_t connectionId, uint32_t msgId) {
+ std::unique_lock<std::mutex> lock(mLock);
+ auto it = mClients.find(connectionId);
+ if (it != mClients.end()) {
+ const std::shared_ptr<BufferPoolClient> client = it->second.lock();
+ if (!client) {
+ mClients.erase(it);
+ } else {
+ lock.unlock();
+ client->receiveInvalidation(msgId);
+ }
+ }
+ return Void();
+}
+
+void Observer::addClient(ConnectionId connectionId,
+ const std::weak_ptr<BufferPoolClient> &wclient) {
+ std::lock_guard<std::mutex> lock(mLock);
+ for (auto it = mClients.begin(); it != mClients.end();) {
+ if (!it->second.lock() || it->first == connectionId) {
+ it = mClients.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ mClients.insert(std::make_pair(connectionId, wclient));
+
+}
+
+void Observer::delClient(ConnectionId connectionId) {
+ std::lock_guard<std::mutex> lock(mLock);
+ mClients.erase(connectionId);
+}
+
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace bufferpool
+} // namespace media
+} // namespace hardware
+} // namespace android
diff --git a/media/bufferpool/2.0/Observer.h b/media/bufferpool/2.0/Observer.h
new file mode 100644
index 0000000..42bd7c1
--- /dev/null
+++ b/media/bufferpool/2.0/Observer.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_OBSERVER_H
+#define ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_OBSERVER_H
+
+#include <android/hardware/media/bufferpool/2.0/IObserver.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include "BufferPoolClient.h"
+
+namespace android {
+namespace hardware {
+namespace media {
+namespace bufferpool {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct Observer : public IObserver {
+ // Methods from ::android::hardware::media::bufferpool::V2_0::IObserver follow.
+ Return<void> onMessage(int64_t connectionId, uint32_t msgId) override;
+
+ ~Observer();
+
+ void addClient(ConnectionId connectionId,
+ const std::weak_ptr<BufferPoolClient> &wclient);
+
+ void delClient(ConnectionId connectionId);
+
+private:
+ Observer();
+
+ friend struct ClientManager;
+
+ std::mutex mLock;
+ std::map<ConnectionId, const std::weak_ptr<BufferPoolClient>> mClients;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace bufferpool
+} // namespace media
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_MEDIA_BUFFERPOOL_V2_0_OBSERVER_H
diff --git a/media/bufferpool/2.0/include/bufferpool/ClientManager.h b/media/bufferpool/2.0/include/bufferpool/ClientManager.h
index cfc3bc3..953c304 100644
--- a/media/bufferpool/2.0/include/bufferpool/ClientManager.h
+++ b/media/bufferpool/2.0/include/bufferpool/ClientManager.h
@@ -92,6 +92,18 @@
ResultStatus close(ConnectionId connectionId);
/**
+ * Evicts cached allocations. If it's local connection, release the
+ * previous allocations and do not recycle current active allocations.
+ *
+ * @param connectionId The id of the connection.
+ *
+ * @return OK when the connection is resetted.
+ * NOT_FOUND when the specified connection was not found.
+ * CRITICAL_ERROR otherwise.
+ */
+ ResultStatus flush(ConnectionId connectionId);
+
+ /**
* Allocates a buffer from the specified connection.
*
* @param connectionId The id of the connection.
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index fcfdaff..be6d9fd 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -622,6 +622,8 @@
AMediaFormat_setInt32(mTrackMetadata,
AMEDIAFORMAT_KEY_SAMPLE_RATE, getSampleRate());
AMediaFormat_setInt32(mTrackMetadata,
+ AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, getBitsPerSample());
+ AMediaFormat_setInt32(mTrackMetadata,
AMEDIAFORMAT_KEY_PCM_ENCODING, kAudioEncodingPcm16bit);
// sample rate is non-zero, so division by zero not possible
AMediaFormat_setInt64(mTrackMetadata,
diff --git a/media/extractors/mkv/Android.bp b/media/extractors/mkv/Android.bp
index 681fd35..ae108ec 100644
--- a/media/extractors/mkv/Android.bp
+++ b/media/extractors/mkv/Android.bp
@@ -12,6 +12,7 @@
shared_libs: [
"liblog",
"libmediaextractor",
+ "libmediandk",
],
static_libs: [
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index e15cbdb..1fdac05 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -127,15 +127,15 @@
BlockIterator &operator=(const BlockIterator &);
};
-struct MatroskaSource : public MediaTrackHelper {
+struct MatroskaSource : public MediaTrackHelperV2 {
MatroskaSource(MatroskaExtractor *extractor, size_t index);
- virtual status_t start();
- virtual status_t stop();
+ virtual media_status_t start();
+ virtual media_status_t stop();
- virtual status_t getFormat(MetaDataBase &);
+ virtual media_status_t getFormat(AMediaFormat *);
- virtual status_t read(
+ virtual media_status_t read(
MediaBufferBase **buffer, const ReadOptions *options);
protected:
@@ -161,7 +161,7 @@
status_t advance();
status_t setWebmBlockCryptoInfo(MediaBufferBase *mbuf);
- status_t readBlock();
+ media_status_t readBlock();
void clearPendingFrames();
MatroskaSource(const MatroskaSource &);
@@ -226,43 +226,30 @@
index),
mNALSizeLen(-1) {
MatroskaExtractor::TrackInfo &trackInfo = mExtractor->mTracks.editItemAt(index);
- MetaDataBase &meta = trackInfo.mMeta;
+ AMediaFormat *meta = trackInfo.mMeta;
const char *mime;
- CHECK(meta.findCString(kKeyMIMEType, &mime));
+ CHECK(AMediaFormat_getString(meta, AMEDIAFORMAT_KEY_MIME, &mime));
mIsAudio = !strncasecmp("audio/", mime, 6);
if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
mType = AVC;
- uint32_t dummy;
- const uint8_t *avcc;
- size_t avccSize;
int32_t nalSizeLen = trackInfo.mNalLengthSize;
- if (nalSizeLen >= 0) {
- if (nalSizeLen <= 4) {
- mNALSizeLen = nalSizeLen;
- }
- } else if (meta.findData(kKeyAVCC, &dummy, (const void **)&avcc, &avccSize)
- && avccSize >= 5u) {
- mNALSizeLen = 1 + (avcc[4] & 3);
- ALOGV("mNALSizeLen = %zd", mNALSizeLen);
+ if (nalSizeLen >= 0 && nalSizeLen <= 4) {
+ mNALSizeLen = nalSizeLen;
} else {
- ALOGE("No mNALSizeLen");
+ ALOGE("No AVC mNALSizeLen");
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
mType = HEVC;
- uint32_t dummy;
- const uint8_t *hvcc;
- size_t hvccSize;
- if (meta.findData(kKeyHVCC, &dummy, (const void **)&hvcc, &hvccSize)
- && hvccSize >= 22u) {
- mNALSizeLen = 1 + (hvcc[14+7] & 3);
- ALOGV("mNALSizeLen = %zu", mNALSizeLen);
+ int32_t nalSizeLen = trackInfo.mNalLengthSize;
+ if (nalSizeLen >= 0 && nalSizeLen <= 4) {
+ mNALSizeLen = nalSizeLen;
} else {
- ALOGE("No mNALSizeLen");
+ ALOGE("No HEVC mNALSizeLen");
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
mType = AAC;
@@ -273,25 +260,24 @@
clearPendingFrames();
}
-status_t MatroskaSource::start() {
+media_status_t MatroskaSource::start() {
if (mType == AVC && mNALSizeLen < 0) {
- return ERROR_MALFORMED;
+ return AMEDIA_ERROR_MALFORMED;
}
mBlockIter.reset();
- return OK;
+ return AMEDIA_OK;
}
-status_t MatroskaSource::stop() {
+media_status_t MatroskaSource::stop() {
clearPendingFrames();
- return OK;
+ return AMEDIA_OK;
}
-status_t MatroskaSource::getFormat(MetaDataBase &meta) {
- meta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
- return OK;
+media_status_t MatroskaSource::getFormat(AMediaFormat *meta) {
+ return AMediaFormat_copy(meta, mExtractor->mTracks.itemAt(mTrackIndex).mMeta);
}
////////////////////////////////////////////////////////////////////////////////
@@ -608,11 +594,11 @@
MetaDataBase &meta = mbuf->meta_data();
if (encrypted) {
uint8_t ctrCounter[16] = { 0 };
- uint32_t type;
const uint8_t *keyId;
size_t keyIdSize;
- const MetaDataBase &trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
- CHECK(trackMeta.findData(kKeyCryptoKey, &type, (const void **)&keyId, &keyIdSize));
+ AMediaFormat *trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
+ AMediaFormat_getBuffer(trackMeta, AMEDIAFORMAT_KEY_CRYPTO_KEY,
+ (void**)&keyId, &keyIdSize);
meta.setData(kKeyCryptoKey, 0, keyId, keyIdSize);
memcpy(ctrCounter, data + 1, 8);
meta.setData(kKeyCryptoIV, 0, ctrCounter, 16);
@@ -715,11 +701,11 @@
return OK;
}
-status_t MatroskaSource::readBlock() {
+media_status_t MatroskaSource::readBlock() {
CHECK(mPendingFrames.empty());
if (mBlockIter.eos()) {
- return ERROR_END_OF_STREAM;
+ return AMEDIA_ERROR_END_OF_STREAM;
}
const mkvparser::Block *block = mBlockIter.block();
@@ -731,7 +717,7 @@
const mkvparser::Block::Frame &frame = block->GetFrame(i);
size_t len = frame.len;
if (SIZE_MAX - len < trackInfo->mHeaderLen) {
- return ERROR_MALFORMED;
+ return AMEDIA_ERROR_MALFORMED;
}
len += trackInfo->mHeaderLen;
@@ -756,7 +742,7 @@
mBlockIter.advance();
mbuf->release();
- return err;
+ return AMEDIA_ERROR_UNKNOWN;
}
mPendingFrames.push_back(mbuf);
@@ -764,10 +750,10 @@
mBlockIter.advance();
- return OK;
+ return AMEDIA_OK;
}
-status_t MatroskaSource::read(
+media_status_t MatroskaSource::read(
MediaBufferBase **out, const ReadOptions *options) {
*out = NULL;
@@ -777,7 +763,7 @@
ReadOptions::SeekMode mode;
if (options && options->getSeekTo(&seekTimeUs, &mode)) {
if (mode == ReadOptions::SEEK_FRAME_INDEX) {
- return ERROR_UNSUPPORTED;
+ return AMEDIA_ERROR_UNSUPPORTED;
}
if (!mExtractor->isLiveStreaming()) {
@@ -795,7 +781,7 @@
}
while (mPendingFrames.empty()) {
- status_t err = readBlock();
+ media_status_t err = readBlock();
if (err != OK) {
clearPendingFrames();
@@ -815,7 +801,7 @@
*out = frame;
- return OK;
+ return AMEDIA_OK;
}
// Each input frame contains one or more NAL fragments, each fragment
@@ -854,7 +840,7 @@
frame->release();
frame = NULL;
- return ERROR_MALFORMED;
+ return AMEDIA_ERROR_MALFORMED;
} else if (srcOffset + mNALSizeLen + NALsize > srcSize) {
break;
}
@@ -882,7 +868,7 @@
frame->release();
frame = NULL;
- return ERROR_MALFORMED;
+ return AMEDIA_ERROR_MALFORMED;
}
if (pass == 0) {
@@ -920,7 +906,7 @@
*out = buffer;
- return OK;
+ return AMEDIA_OK;
}
////////////////////////////////////////////////////////////////////////////////
@@ -1006,7 +992,7 @@
return mTracks.size();
}
-MediaTrackHelper *MatroskaExtractor::getTrack(size_t index) {
+MediaTrackHelperV2 *MatroskaExtractor::getTrack(size_t index) {
if (index >= mTracks.size()) {
return NULL;
}
@@ -1014,11 +1000,11 @@
return new MatroskaSource(this, index);
}
-status_t MatroskaExtractor::getTrackMetaData(
- MetaDataBase &meta,
+media_status_t MatroskaExtractor::getTrackMetaData(
+ AMediaFormat *meta,
size_t index, uint32_t flags) {
if (index >= mTracks.size()) {
- return UNKNOWN_ERROR;
+ return AMEDIA_ERROR_UNKNOWN;
}
if ((flags & kIncludeExtensiveMetaData) && !mExtractedThumbnails
@@ -1027,8 +1013,7 @@
mExtractedThumbnails = true;
}
- meta = mTracks.itemAt(index).mMeta;
- return OK;
+ return AMediaFormat_copy(meta, mTracks.itemAt(index).mMeta);
}
bool MatroskaExtractor::isLiveStreaming() const {
@@ -1063,7 +1048,7 @@
}
static void addESDSFromCodecPrivate(
- MetaDataBase &meta,
+ AMediaFormat *meta,
bool isAudio, const void *priv, size_t privSize) {
int privSizeBytesRequired = bytesForSize(privSize);
@@ -1091,14 +1076,14 @@
storeSize(esds, idx, privSize);
memcpy(esds + idx, priv, privSize);
- meta.setData(kKeyESDS, 0, esds, esdsSize);
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_0, priv, privSize);
delete[] esds;
esds = NULL;
}
status_t addVorbisCodecInfo(
- MetaDataBase &meta,
+ AMediaFormat *meta,
const void *_codecPrivate, size_t codecPrivateSize) {
// hexdump(_codecPrivate, codecPrivateSize);
@@ -1156,7 +1141,8 @@
if (codecPrivate[offset] != 0x01) {
return ERROR_MALFORMED;
}
- meta.setData(kKeyVorbisInfo, 0, &codecPrivate[offset], len1);
+ // formerly kKeyVorbisInfo
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_0, &codecPrivate[offset], len1);
offset += len1;
if (codecPrivate[offset] != 0x03) {
@@ -1168,19 +1154,20 @@
return ERROR_MALFORMED;
}
- meta.setData(
- kKeyVorbisBooks, 0, &codecPrivate[offset],
- codecPrivateSize - offset);
+ // formerly kKeyVorbisBooks
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_1,
+ &codecPrivate[offset], codecPrivateSize - offset);
return OK;
}
static status_t addFlacMetadata(
- MetaDataBase &meta,
+ AMediaFormat *meta,
const void *codecPrivate, size_t codecPrivateSize) {
// hexdump(codecPrivate, codecPrivateSize);
- meta.setData(kKeyFlacMetadata, 0, codecPrivate, codecPrivateSize);
+ // formerly kKeyFlacMetadata
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_0, codecPrivate, codecPrivateSize);
int32_t maxInputSize = 64 << 10;
FLACDecoder *flacDecoder = FLACDecoder::Create();
@@ -1202,7 +1189,7 @@
* streamInfo.max_blocksize * streamInfo.channels;
}
}
- meta.setInt32(kKeyMaxInputSize, maxInputSize);
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, maxInputSize);
delete flacDecoder;
return OK;
@@ -1253,7 +1240,7 @@
}
void MatroskaExtractor::getColorInformation(
- const mkvparser::VideoTrack *vtrack, MetaDataBase &meta) {
+ const mkvparser::VideoTrack *vtrack, AMediaFormat *meta) {
const mkvparser::Colour *color = vtrack->GetColour();
if (color == NULL) {
return;
@@ -1262,7 +1249,7 @@
// Color Aspects
{
int32_t primaries = 2; // ISO unspecified
- int32_t transfer = 2; // ISO unspecified
+ int32_t isotransfer = 2; // ISO unspecified
int32_t coeffs = 2; // ISO unspecified
bool fullRange = false; // default
bool rangeSpecified = false;
@@ -1271,7 +1258,7 @@
primaries = color->primaries;
}
if (isValidInt32ColourValue(color->transfer_characteristics)) {
- transfer = color->transfer_characteristics;
+ isotransfer = color->transfer_characteristics;
}
if (isValidInt32ColourValue(color->matrix_coefficients)) {
coeffs = color->matrix_coefficients;
@@ -1284,14 +1271,21 @@
rangeSpecified = true;
}
- ColorAspects aspects;
- ColorUtils::convertIsoColorAspectsToCodecAspects(
- primaries, transfer, coeffs, fullRange, aspects);
- meta.setInt32(kKeyColorPrimaries, aspects.mPrimaries);
- meta.setInt32(kKeyTransferFunction, aspects.mTransfer);
- meta.setInt32(kKeyColorMatrix, aspects.mMatrixCoeffs);
- meta.setInt32(
- kKeyColorRange, rangeSpecified ? aspects.mRange : ColorAspects::RangeUnspecified);
+ int32_t range = 0;
+ int32_t standard = 0;
+ int32_t transfer = 0;
+ ColorUtils::convertIsoColorAspectsToPlatformAspects(
+ primaries, isotransfer, coeffs, fullRange,
+ &range, &standard, &transfer);
+ if (range != 0) {
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_COLOR_RANGE, range);
+ }
+ if (standard != 0) {
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_COLOR_STANDARD, standard);
+ }
+ if (transfer != 0) {
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_COLOR_TRANSFER, transfer);
+ }
}
// HDR Static Info
@@ -1335,13 +1329,13 @@
// Only advertise static info if at least one of the groups have been specified.
if (memcmp(&info, &nullInfo, sizeof(info)) != 0) {
info.mID = HDRStaticInfo::kType1;
- meta.setData(kKeyHdrStaticInfo, 'hdrS', &info, sizeof(info));
+ ColorUtils::setHDRStaticInfoIntoAMediaFormat(info, meta);
}
}
}
status_t MatroskaExtractor::initTrackInfo(
- const mkvparser::Track *track, MetaDataBase &meta, TrackInfo *trackInfo) {
+ const mkvparser::Track *track, AMediaFormat *meta, TrackInfo *trackInfo) {
trackInfo->mTrackNum = track->GetNumber();
trackInfo->mMeta = meta;
trackInfo->mExtractor = this;
@@ -1355,7 +1349,8 @@
for(size_t j = 0; j < encoding->GetEncryptionCount(); j++) {
const mkvparser::ContentEncoding::ContentEncryption *encryption;
encryption = encoding->GetEncryptionByIndex(j);
- trackInfo->mMeta.setData(kKeyCryptoKey, 0, encryption->key_id, encryption->key_id_len);
+ AMediaFormat_setBuffer(trackInfo->mMeta,
+ AMEDIAFORMAT_KEY_CRYPTO_KEY, encryption->key_id, encryption->key_id_len);
trackInfo->mEncrypted = true;
break;
}
@@ -1404,9 +1399,10 @@
enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 };
- MetaDataBase meta;
+ AMediaFormat *meta = AMediaFormat_new();
status_t err = OK;
+ int32_t nalSize = -1;
switch (track->GetType()) {
case VIDEO_TRACK:
@@ -1415,20 +1411,28 @@
static_cast<const mkvparser::VideoTrack *>(track);
if (!strcmp("V_MPEG4/ISO/AVC", codecID)) {
- meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
- meta.setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize);
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AVC);
+ AMediaFormat_setBuffer(meta,
+ AMEDIAFORMAT_KEY_CSD_AVC, codecPrivate, codecPrivateSize);
+ if (codecPrivateSize > 4) {
+ nalSize = 1 + (codecPrivate[4] & 3);
+ }
} else if (!strcmp("V_MPEGH/ISO/HEVC", codecID)) {
- meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_HEVC);
if (codecPrivateSize > 0) {
- meta.setData(kKeyHVCC, kTypeHVCC, codecPrivate, codecPrivateSize);
+ AMediaFormat_setBuffer(meta,
+ AMEDIAFORMAT_KEY_CSD_HEVC, codecPrivate, codecPrivateSize);
+ if (codecPrivateSize > 14 + 7) {
+ nalSize = 1 + (codecPrivate[14 + 7] & 3);
+ }
} else {
ALOGW("HEVC is detected, but does not have configuration.");
continue;
}
} else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) {
if (codecPrivateSize > 0) {
- meta.setCString(
- kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
+ AMediaFormat_setString(meta,
+ AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_MPEG4);
addESDSFromCodecPrivate(
meta, false, codecPrivate, codecPrivateSize);
} else {
@@ -1437,15 +1441,14 @@
continue;
}
} else if (!strcmp("V_VP8", codecID)) {
- meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8);
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_VP8);
} else if (!strcmp("V_VP9", codecID)) {
- meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9);
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_VP9);
if (codecPrivateSize > 0) {
// 'csd-0' for VP9 is the Blob of Codec Private data as
// specified in http://www.webmproject.org/vp9/profiles/.
- meta.setData(
- kKeyVp9CodecPrivate, 0, codecPrivate,
- codecPrivateSize);
+ AMediaFormat_setBuffer(meta,
+ AMEDIAFORMAT_KEY_CSD_0, codecPrivate, codecPrivateSize);
}
} else {
ALOGW("%s is not supported.", codecID);
@@ -1462,8 +1465,8 @@
ALOGW("track height exceeds int32_t, %lld", height);
continue;
}
- meta.setInt32(kKeyWidth, (int32_t)width);
- meta.setInt32(kKeyHeight, (int32_t)height);
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_WIDTH, (int32_t)width);
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_HEIGHT, (int32_t)height);
// setting display width/height is optional
const long long displayUnit = vtrack->GetDisplayUnit();
@@ -1473,8 +1476,10 @@
&& displayHeight > 0 && displayHeight <= INT32_MAX) {
switch (displayUnit) {
case 0: // pixels
- meta.setInt32(kKeyDisplayWidth, (int32_t)displayWidth);
- meta.setInt32(kKeyDisplayHeight, (int32_t)displayHeight);
+ AMediaFormat_setInt32(meta,
+ AMEDIAFORMAT_KEY_DISPLAY_WIDTH, (int32_t)displayWidth);
+ AMediaFormat_setInt32(meta,
+ AMEDIAFORMAT_KEY_DISPLAY_HEIGHT, (int32_t)displayHeight);
break;
case 1: // centimeters
case 2: // inches
@@ -1488,8 +1493,10 @@
const long long computedHeight =
std::max(height, width * displayHeight / displayWidth);
if (computedWidth <= INT32_MAX && computedHeight <= INT32_MAX) {
- meta.setInt32(kKeyDisplayWidth, (int32_t)computedWidth);
- meta.setInt32(kKeyDisplayHeight, (int32_t)computedHeight);
+ AMediaFormat_setInt32(meta,
+ AMEDIAFORMAT_KEY_DISPLAY_WIDTH, (int32_t)computedWidth);
+ AMediaFormat_setInt32(meta,
+ AMEDIAFORMAT_KEY_DISPLAY_HEIGHT, (int32_t)computedHeight);
}
break;
}
@@ -1509,34 +1516,39 @@
static_cast<const mkvparser::AudioTrack *>(track);
if (!strcmp("A_AAC", codecID)) {
- meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_AAC);
CHECK(codecPrivateSize >= 2);
addESDSFromCodecPrivate(
meta, true, codecPrivate, codecPrivateSize);
} else if (!strcmp("A_VORBIS", codecID)) {
- meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS);
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_VORBIS);
err = addVorbisCodecInfo(
meta, codecPrivate, codecPrivateSize);
} else if (!strcmp("A_OPUS", codecID)) {
- meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS);
- meta.setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize);
- meta.setInt64(kKeyOpusCodecDelay, track->GetCodecDelay());
- meta.setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll());
+ AMediaFormat_setString(meta,
+ AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_OPUS);
+ AMediaFormat_setBuffer(meta,
+ AMEDIAFORMAT_KEY_CSD_0, codecPrivate, codecPrivateSize);
+ int64_t codecDelay = track->GetCodecDelay();
+ AMediaFormat_setBuffer(meta,
+ AMEDIAFORMAT_KEY_CSD_1, &codecDelay, sizeof(codecDelay));
mSeekPreRollNs = track->GetSeekPreRoll();
+ AMediaFormat_setBuffer(meta,
+ AMEDIAFORMAT_KEY_CSD_2, &mSeekPreRollNs, sizeof(mSeekPreRollNs));
} else if (!strcmp("A_MPEG/L3", codecID)) {
- meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG);
} else if (!strcmp("A_FLAC", codecID)) {
- meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_FLAC);
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_FLAC);
err = addFlacMetadata(meta, codecPrivate, codecPrivateSize);
} else {
ALOGW("%s is not supported.", codecID);
continue;
}
- meta.setInt32(kKeySampleRate, atrack->GetSamplingRate());
- meta.setInt32(kKeyChannelCount, atrack->GetChannels());
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, atrack->GetSamplingRate());
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, atrack->GetChannels());
break;
}
@@ -1549,7 +1561,7 @@
char lang[4];
strncpy(lang, language, 3);
lang[3] = '\0';
- meta.setCString(kKeyMediaLanguage, lang);
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_LANGUAGE, lang);
}
if (err != OK) {
@@ -1558,12 +1570,13 @@
}
long long durationNs = mSegment->GetDuration();
- meta.setInt64(kKeyDuration, (durationNs + 500) / 1000);
+ AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_DURATION, (durationNs + 500) / 1000);
mTracks.push();
size_t n = mTracks.size() - 1;
TrackInfo *trackInfo = &mTracks.editItemAt(n);
initTrackInfo(track, meta, trackInfo);
+ trackInfo->mNalLengthSize = nalSize;
if (!strcmp("V_MPEG4/ISO/AVC", codecID) && codecPrivateSize == 0) {
// Attempt to recover from AVC track without codec private data
@@ -1580,7 +1593,7 @@
TrackInfo *info = &mTracks.editItemAt(i);
const char *mime;
- CHECK(info->mMeta.findCString(kKeyMIMEType, &mime));
+ CHECK(AMediaFormat_getString(info->mMeta, AMEDIAFORMAT_KEY_MIME, &mime));
if (strncasecmp(mime, "video/", 6)) {
continue;
@@ -1606,16 +1619,16 @@
}
iter.advance();
}
- info->mMeta.setInt64(kKeyThumbnailTime, thumbnailTimeUs);
+ AMediaFormat_setInt64(info->mMeta,
+ AMEDIAFORMAT_KEY_THUMBNAIL_TIME, thumbnailTimeUs);
}
}
-status_t MatroskaExtractor::getMetaData(MetaDataBase &meta) {
- meta.setCString(
- kKeyMIMEType,
- mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA);
+media_status_t MatroskaExtractor::getMetaData(AMediaFormat *meta) {
+ AMediaFormat_setString(meta,
+ AMEDIAFORMAT_KEY_MIME, mIsWebm ? "video/webm" : MEDIA_MIMETYPE_CONTAINER_MATROSKA);
- return OK;
+ return AMEDIA_OK;
}
uint32_t MatroskaExtractor::flags() const {
@@ -1647,22 +1660,22 @@
__attribute__ ((visibility ("default")))
ExtractorDef GETEXTRACTORDEF() {
return {
- EXTRACTORDEF_VERSION,
+ EXTRACTORDEF_VERSION_CURRENT,
UUID("abbedd92-38c4-4904-a4c1-b3f45f899980"),
1,
"Matroska Extractor",
{
- [](
+ .v2 = [](
CDataSource *source,
float *confidence,
void **,
- FreeMetaFunc *) -> CreatorFunc {
+ FreeMetaFunc *) -> CreatorFuncV2 {
DataSourceHelper helper(source);
if (SniffMatroska(&helper, confidence)) {
return [](
CDataSource *source,
- void *) -> CMediaExtractor* {
- return wrap(new MatroskaExtractor(new DataSourceHelper(source)));};
+ void *) -> CMediaExtractorV2* {
+ return wrapV2(new MatroskaExtractor(new DataSourceHelper(source)));};
}
return NULL;
}
diff --git a/media/extractors/mkv/MatroskaExtractor.h b/media/extractors/mkv/MatroskaExtractor.h
index 03fdeee..2fa8881 100644
--- a/media/extractors/mkv/MatroskaExtractor.h
+++ b/media/extractors/mkv/MatroskaExtractor.h
@@ -22,7 +22,7 @@
#include <media/MediaExtractorPluginApi.h>
#include <media/MediaExtractorPluginHelper.h>
-#include <media/stagefright/MetaDataBase.h>
+#include <media/NdkMediaFormat.h>
#include <utils/Vector.h>
#include <utils/threads.h>
@@ -35,16 +35,16 @@
struct DataSourceBaseReader;
struct MatroskaSource;
-struct MatroskaExtractor : public MediaExtractorPluginHelper {
+struct MatroskaExtractor : public MediaExtractorPluginHelperV2 {
explicit MatroskaExtractor(DataSourceHelper *source);
virtual size_t countTracks();
- virtual MediaTrackHelper *getTrack(size_t index);
+ virtual MediaTrackHelperV2 *getTrack(size_t index);
- virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags);
+ virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
- virtual status_t getMetaData(MetaDataBase& meta);
+ virtual media_status_t getMetaData(AMediaFormat *meta);
virtual uint32_t flags() const;
@@ -58,9 +58,17 @@
friend struct BlockIterator;
struct TrackInfo {
+ TrackInfo() {
+ mMeta = NULL;
+ }
+ ~TrackInfo() {
+ if (mMeta) {
+ AMediaFormat_delete(mMeta);
+ }
+ }
unsigned long mTrackNum;
bool mEncrypted;
- MetaDataBase mMeta;
+ AMediaFormat *mMeta;
const MatroskaExtractor *mExtractor;
Vector<const mkvparser::CuePoint*> mCuePoints;
@@ -89,13 +97,13 @@
status_t synthesizeAVCC(TrackInfo *trackInfo, size_t index);
status_t initTrackInfo(
const mkvparser::Track *track,
- MetaDataBase &meta,
+ AMediaFormat *meta,
TrackInfo *trackInfo);
void addTracks();
void findThumbnails();
void getColorInformation(
const mkvparser::VideoTrack *vtrack,
- MetaDataBase &meta);
+ AMediaFormat *meta);
bool isLiveStreaming() const;
MatroskaExtractor(const MatroskaExtractor &);
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 3a58aa6..524d02f 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -5316,14 +5316,7 @@
// Whole NAL units are returned but each fragment is prefixed by
// the start code (0x00 00 00 01).
ssize_t num_bytes_read = 0;
- int32_t drm = 0;
- bool usesDRM = (mFormat.findInt32(kKeyIsDRM, &drm) && drm != 0);
- if (usesDRM) {
- num_bytes_read =
- mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
- } else {
- num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
- }
+ num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
if (num_bytes_read < (ssize_t)size) {
mBuffer->release();
@@ -5332,57 +5325,51 @@
return ERROR_IO;
}
- if (usesDRM) {
- CHECK(mBuffer != NULL);
- mBuffer->set_range(0, size);
+ uint8_t *dstData = (uint8_t *)mBuffer->data();
+ size_t srcOffset = 0;
+ size_t dstOffset = 0;
- } else {
- uint8_t *dstData = (uint8_t *)mBuffer->data();
- size_t srcOffset = 0;
- size_t dstOffset = 0;
-
- while (srcOffset < size) {
- bool isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
- size_t nalLength = 0;
- if (!isMalFormed) {
- nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
- srcOffset += mNALLengthSize;
- isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength);
- }
-
- if (isMalFormed) {
- ALOGE("Video is malformed");
- mBuffer->release();
- mBuffer = NULL;
- return ERROR_MALFORMED;
- }
-
- if (nalLength == 0) {
- continue;
- }
-
- if (dstOffset > SIZE_MAX - 4 ||
- dstOffset + 4 > SIZE_MAX - nalLength ||
- dstOffset + 4 + nalLength > mBuffer->size()) {
- ALOGE("b/27208621 : %zu %zu", dstOffset, mBuffer->size());
- android_errorWriteLog(0x534e4554, "27208621");
- mBuffer->release();
- mBuffer = NULL;
- return ERROR_MALFORMED;
- }
-
- dstData[dstOffset++] = 0;
- dstData[dstOffset++] = 0;
- dstData[dstOffset++] = 0;
- dstData[dstOffset++] = 1;
- memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
- srcOffset += nalLength;
- dstOffset += nalLength;
+ while (srcOffset < size) {
+ bool isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
+ size_t nalLength = 0;
+ if (!isMalFormed) {
+ nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
+ srcOffset += mNALLengthSize;
+ isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength);
}
- CHECK_EQ(srcOffset, size);
- CHECK(mBuffer != NULL);
- mBuffer->set_range(0, dstOffset);
+
+ if (isMalFormed) {
+ ALOGE("Video is malformed");
+ mBuffer->release();
+ mBuffer = NULL;
+ return ERROR_MALFORMED;
+ }
+
+ if (nalLength == 0) {
+ continue;
+ }
+
+ if (dstOffset > SIZE_MAX - 4 ||
+ dstOffset + 4 > SIZE_MAX - nalLength ||
+ dstOffset + 4 + nalLength > mBuffer->size()) {
+ ALOGE("b/27208621 : %zu %zu", dstOffset, mBuffer->size());
+ android_errorWriteLog(0x534e4554, "27208621");
+ mBuffer->release();
+ mBuffer = NULL;
+ return ERROR_MALFORMED;
+ }
+
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 1;
+ memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
+ srcOffset += nalLength;
+ dstOffset += nalLength;
}
+ CHECK_EQ(srcOffset, size);
+ CHECK(mBuffer != NULL);
+ mBuffer->set_range(0, dstOffset);
mBuffer->meta_data().clear();
mBuffer->meta_data().setInt64(
@@ -5669,24 +5656,14 @@
// Whole NAL units are returned but each fragment is prefixed by
// the start code (0x00 00 00 01).
ssize_t num_bytes_read = 0;
- int32_t drm = 0;
- bool usesDRM = (mFormat.findInt32(kKeyIsDRM, &drm) && drm != 0);
void *data = NULL;
bool isMalFormed = false;
- if (usesDRM) {
- if (mBuffer == NULL || !isInRange((size_t)0u, mBuffer->size(), size)) {
- isMalFormed = true;
- } else {
- data = mBuffer->data();
- }
+ int32_t max_size;
+ if (!mFormat.findInt32(kKeyMaxInputSize, &max_size)
+ || !isInRange((size_t)0u, (size_t)max_size, size)) {
+ isMalFormed = true;
} else {
- int32_t max_size;
- if (!mFormat.findInt32(kKeyMaxInputSize, &max_size)
- || !isInRange((size_t)0u, (size_t)max_size, size)) {
- isMalFormed = true;
- } else {
- data = mSrcBuffer;
- }
+ data = mSrcBuffer;
}
if (isMalFormed || data == NULL) {
@@ -5707,59 +5684,53 @@
return ERROR_IO;
}
- if (usesDRM) {
- CHECK(mBuffer != NULL);
- mBuffer->set_range(0, size);
+ uint8_t *dstData = (uint8_t *)mBuffer->data();
+ size_t srcOffset = 0;
+ size_t dstOffset = 0;
- } else {
- uint8_t *dstData = (uint8_t *)mBuffer->data();
- size_t srcOffset = 0;
- size_t dstOffset = 0;
-
- while (srcOffset < size) {
- isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
- size_t nalLength = 0;
- if (!isMalFormed) {
- nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
- srcOffset += mNALLengthSize;
- isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength)
- || !isInRange((size_t)0u, mBuffer->size(), dstOffset, (size_t)4u)
- || !isInRange((size_t)0u, mBuffer->size(), dstOffset + 4, nalLength);
- }
-
- if (isMalFormed) {
- ALOGE("Video is malformed; nalLength %zu", nalLength);
- mBuffer->release();
- mBuffer = NULL;
- return ERROR_MALFORMED;
- }
-
- if (nalLength == 0) {
- continue;
- }
-
- if (dstOffset > SIZE_MAX - 4 ||
- dstOffset + 4 > SIZE_MAX - nalLength ||
- dstOffset + 4 + nalLength > mBuffer->size()) {
- ALOGE("b/26365349 : %zu %zu", dstOffset, mBuffer->size());
- android_errorWriteLog(0x534e4554, "26365349");
- mBuffer->release();
- mBuffer = NULL;
- return ERROR_MALFORMED;
- }
-
- dstData[dstOffset++] = 0;
- dstData[dstOffset++] = 0;
- dstData[dstOffset++] = 0;
- dstData[dstOffset++] = 1;
- memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
- srcOffset += nalLength;
- dstOffset += nalLength;
+ while (srcOffset < size) {
+ isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
+ size_t nalLength = 0;
+ if (!isMalFormed) {
+ nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
+ srcOffset += mNALLengthSize;
+ isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength)
+ || !isInRange((size_t)0u, mBuffer->size(), dstOffset, (size_t)4u)
+ || !isInRange((size_t)0u, mBuffer->size(), dstOffset + 4, nalLength);
}
- CHECK_EQ(srcOffset, size);
- CHECK(mBuffer != NULL);
- mBuffer->set_range(0, dstOffset);
+
+ if (isMalFormed) {
+ ALOGE("Video is malformed; nalLength %zu", nalLength);
+ mBuffer->release();
+ mBuffer = NULL;
+ return ERROR_MALFORMED;
+ }
+
+ if (nalLength == 0) {
+ continue;
+ }
+
+ if (dstOffset > SIZE_MAX - 4 ||
+ dstOffset + 4 > SIZE_MAX - nalLength ||
+ dstOffset + 4 + nalLength > mBuffer->size()) {
+ ALOGE("b/26365349 : %zu %zu", dstOffset, mBuffer->size());
+ android_errorWriteLog(0x534e4554, "26365349");
+ mBuffer->release();
+ mBuffer = NULL;
+ return ERROR_MALFORMED;
+ }
+
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 0;
+ dstData[dstOffset++] = 1;
+ memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
+ srcOffset += nalLength;
+ dstOffset += nalLength;
}
+ CHECK_EQ(srcOffset, size);
+ CHECK(mBuffer != NULL);
+ mBuffer->set_range(0, dstOffset);
mBuffer->meta_data().setInt64(
kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index 9a329f1..ddc7031 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -311,6 +311,7 @@
AMediaFormat_setInt32(mTrackMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, mNumChannels);
AMediaFormat_setInt32(mTrackMeta, AMEDIAFORMAT_KEY_CHANNEL_MASK, mChannelMask);
AMediaFormat_setInt32(mTrackMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, mSampleRate);
+ AMediaFormat_setInt32(mTrackMeta, AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, mBitsPerSample);
AMediaFormat_setInt32(mTrackMeta, AMEDIAFORMAT_KEY_PCM_ENCODING,
kAudioEncodingPcm16bit);
diff --git a/media/libaaudio/examples/input_monitor/Android.bp b/media/libaaudio/examples/input_monitor/Android.bp
index d8c5843..5d399b5 100644
--- a/media/libaaudio/examples/input_monitor/Android.bp
+++ b/media/libaaudio/examples/input_monitor/Android.bp
@@ -5,6 +5,7 @@
cflags: ["-Wall", "-Werror"],
shared_libs: ["libaaudio"],
header_libs: ["libaaudio_example_utils"],
+ pack_relocations: false,
}
cc_test {
@@ -14,4 +15,5 @@
cflags: ["-Wall", "-Werror"],
shared_libs: ["libaaudio"],
header_libs: ["libaaudio_example_utils"],
+ pack_relocations: false,
}
diff --git a/media/libaaudio/examples/loopback/Android.bp b/media/libaaudio/examples/loopback/Android.bp
index 5b7d956..53e5020 100644
--- a/media/libaaudio/examples/loopback/Android.bp
+++ b/media/libaaudio/examples/loopback/Android.bp
@@ -9,4 +9,5 @@
"libaudioutils",
],
header_libs: ["libaaudio_example_utils"],
+ pack_relocations: false,
}
diff --git a/media/libaaudio/examples/loopback/src/LoopbackAnalyzer.h b/media/libaaudio/examples/loopback/src/LoopbackAnalyzer.h
index ef9a753..64deb60 100644
--- a/media/libaaudio/examples/loopback/src/LoopbackAnalyzer.h
+++ b/media/libaaudio/examples/loopback/src/LoopbackAnalyzer.h
@@ -163,8 +163,7 @@
const float *needle, int needleSize,
LatencyReport *report) {
const double threshold = 0.1;
- printf("measureLatencyFromEchos: haystackSize = %d, needleSize = %d\n",
- haystackSize, needleSize);
+ // printf("%s: haystackSize = %d, needleSize = %d\n", __func__, haystackSize, needleSize);
// Find first peak
int first = (int) (findFirstMatch(haystack,
@@ -181,8 +180,6 @@
needle,
needleSize,
threshold) + 0.5);
-
- printf("measureLatencyFromEchos: first = %d, again at %d\n", first, again);
first = again;
// Allocate results array
@@ -199,7 +196,7 @@
// Add higher harmonics mapped onto lower harmonics.
// This reinforces the "fundamental" echo.
- const int numEchoes = 10;
+ const int numEchoes = 8;
for (int partial = 1; partial < numEchoes; partial++) {
for (int i = 0; i < numCorrelations; i++) {
harmonicSums[i / partial] += correlations[i] / partial;
@@ -216,7 +213,7 @@
maxCorrelation = harmonicSums[i];
sumOfPeaks += maxCorrelation;
peakIndex = i;
- printf("maxCorrelation = %f at %d\n", maxCorrelation, peakIndex);
+ // printf("maxCorrelation = %f at %d\n", maxCorrelation, peakIndex);
}
}
@@ -476,9 +473,13 @@
void report() override {
printf("EchoAnalyzer ---------------\n");
- printf(LOOPBACK_RESULT_TAG "measured.gain = %f\n", mMeasuredLoopGain);
- printf(LOOPBACK_RESULT_TAG "echo.gain = %f\n", mEchoGain);
- printf(LOOPBACK_RESULT_TAG "test.state = %d\n", mState);
+ printf(LOOPBACK_RESULT_TAG "measured.gain = %8f\n", mMeasuredLoopGain);
+ printf(LOOPBACK_RESULT_TAG "echo.gain = %8f\n", mEchoGain);
+ printf(LOOPBACK_RESULT_TAG "test.state = %8d\n", mState);
+ printf(LOOPBACK_RESULT_TAG "test.state.name = %8s\n", convertStateToText(mState));
+ if (mState == STATE_WAITING_FOR_SILENCE) {
+ printf("WARNING - Stuck waiting for silence. Input may be too noisy!\n");
+ }
if (mMeasuredLoopGain >= 0.9999) {
printf(" ERROR - clipping, turn down volume slightly\n");
} else {
@@ -491,9 +492,12 @@
printf(" ERROR - confidence too low = %f\n", mLatencyReport.confidence);
} else {
double latencyMillis = 1000.0 * mLatencyReport.latencyInFrames / getSampleRate();
- printf(LOOPBACK_RESULT_TAG "latency.frames = %8.2f\n", mLatencyReport.latencyInFrames);
- printf(LOOPBACK_RESULT_TAG "latency.msec = %8.2f\n", latencyMillis);
- printf(LOOPBACK_RESULT_TAG "latency.confidence = %8.6f\n", mLatencyReport.confidence);
+ printf(LOOPBACK_RESULT_TAG "latency.frames = %8.2f\n",
+ mLatencyReport.latencyInFrames);
+ printf(LOOPBACK_RESULT_TAG "latency.msec = %8.2f\n",
+ latencyMillis);
+ printf(LOOPBACK_RESULT_TAG "latency.confidence = %8.6f\n",
+ mLatencyReport.confidence);
}
}
}
@@ -527,7 +531,7 @@
int numWritten;
int numSamples;
- echo_state_t nextState = mState;
+ echo_state nextState = mState;
switch (mState) {
case STATE_INITIAL_SILENCE:
@@ -553,6 +557,7 @@
// mLoopCounter, peak);
mDownCounter = 8;
mMeasuredLoopGain = peak; // assumes original pulse amplitude is one
+ mSilenceThreshold = peak * 0.1; // scale silence to measured pulse
// Calculate gain that will give us a nice decaying echo.
mEchoGain = mDesiredEchoGain / mMeasuredLoopGain;
if (mEchoGain > MAX_ECHO_GAIN) {
@@ -638,7 +643,7 @@
private:
- enum echo_state_t {
+ enum echo_state {
STATE_INITIAL_SILENCE,
STATE_MEASURING_GAIN,
STATE_WAITING_FOR_SILENCE,
@@ -648,6 +653,35 @@
STATE_FAILED
};
+ const char *convertStateToText(echo_state state) {
+ const char *result = "Unknown";
+ switch(state) {
+ case STATE_INITIAL_SILENCE:
+ result = "INIT";
+ break;
+ case STATE_MEASURING_GAIN:
+ result = "GAIN";
+ break;
+ case STATE_WAITING_FOR_SILENCE:
+ result = "SILENCE";
+ break;
+ case STATE_SENDING_PULSE:
+ result = "PULSE";
+ break;
+ case STATE_GATHERING_ECHOS:
+ result = "ECHOS";
+ break;
+ case STATE_DONE:
+ result = "DONE";
+ break;
+ case STATE_FAILED:
+ result = "FAILED";
+ break;
+ }
+ return result;
+ }
+
+
int32_t mDownCounter = 500;
int32_t mLoopCounter = 0;
int32_t mSampleIndex = 0;
@@ -656,7 +690,7 @@
float mMeasuredLoopGain = 0.0f;
float mDesiredEchoGain = 0.95f;
float mEchoGain = 1.0f;
- echo_state_t mState = STATE_INITIAL_SILENCE;
+ echo_state mState = STATE_INITIAL_SILENCE;
AudioRecording mAudioRecording; // contains only the input after the gain detection burst
LatencyReport mLatencyReport;
@@ -680,21 +714,32 @@
void report() override {
printf("SineAnalyzer ------------------\n");
- printf(LOOPBACK_RESULT_TAG "peak.amplitude = %7.5f\n", mPeakAmplitude);
- printf(LOOPBACK_RESULT_TAG "sine.magnitude = %7.5f\n", mMagnitude);
- printf(LOOPBACK_RESULT_TAG "phase.offset = %7.5f\n", mPhaseOffset);
- printf(LOOPBACK_RESULT_TAG "ref.phase = %7.5f\n", mPhase);
- printf(LOOPBACK_RESULT_TAG "frames.accumulated = %6d\n", mFramesAccumulated);
- printf(LOOPBACK_RESULT_TAG "sine.period = %6d\n", mSinePeriod);
- printf(LOOPBACK_RESULT_TAG "test.state = %6d\n", mState);
- printf(LOOPBACK_RESULT_TAG "frame.count = %6d\n", mFrameCounter);
+ printf(LOOPBACK_RESULT_TAG "peak.amplitude = %8f\n", mPeakAmplitude);
+ printf(LOOPBACK_RESULT_TAG "sine.magnitude = %8f\n", mMagnitude);
+ printf(LOOPBACK_RESULT_TAG "peak.noise = %8f\n", mPeakNoise);
+ printf(LOOPBACK_RESULT_TAG "rms.noise = %8f\n", mRootMeanSquareNoise);
+ float amplitudeRatio = mMagnitude / mPeakNoise;
+ float signalToNoise = amplitudeRatio * amplitudeRatio;
+ printf(LOOPBACK_RESULT_TAG "signal.to.noise = %8.2f\n", signalToNoise);
+ float signalToNoiseDB = 10.0 * log(signalToNoise);
+ printf(LOOPBACK_RESULT_TAG "signal.to.noise.db = %8.2f\n", signalToNoiseDB);
+ if (signalToNoiseDB < MIN_SNRATIO_DB) {
+ printf("WARNING - signal to noise ratio is too low! < %d dB\n", MIN_SNRATIO_DB);
+ }
+ printf(LOOPBACK_RESULT_TAG "phase.offset = %8.5f\n", mPhaseOffset);
+ printf(LOOPBACK_RESULT_TAG "ref.phase = %8.5f\n", mPhase);
+ printf(LOOPBACK_RESULT_TAG "frames.accumulated = %8d\n", mFramesAccumulated);
+ printf(LOOPBACK_RESULT_TAG "sine.period = %8d\n", mSinePeriod);
+ printf(LOOPBACK_RESULT_TAG "test.state = %8d\n", mState);
+ printf(LOOPBACK_RESULT_TAG "frame.count = %8d\n", mFrameCounter);
// Did we ever get a lock?
bool gotLock = (mState == STATE_LOCKED) || (mGlitchCount > 0);
if (!gotLock) {
printf("ERROR - failed to lock on reference sine tone\n");
} else {
// Only print if meaningful.
- printf(LOOPBACK_RESULT_TAG "glitch.count = %6d\n", mGlitchCount);
+ printf(LOOPBACK_RESULT_TAG "glitch.count = %8d\n", mGlitchCount);
+ printf(LOOPBACK_RESULT_TAG "max.glitch = %8f\n", mMaxGlitchDelta);
}
}
@@ -732,15 +777,48 @@
}
for (int i = 0; i < numFrames; i++) {
+ bool sineEnabled = true;
float sample = inputData[i * inputChannelCount];
float sinOut = sinf(mPhase);
switch (mState) {
case STATE_IDLE:
- case STATE_IMMUNE:
- case STATE_WAITING_FOR_SIGNAL:
+ sineEnabled = false;
+ mDownCounter--;
+ if (mDownCounter <= 0) {
+ mState = STATE_MEASURE_NOISE;
+ mDownCounter = NOISE_FRAME_COUNT;
+ }
break;
+ case STATE_MEASURE_NOISE:
+ sineEnabled = false;
+ mPeakNoise = std::max(abs(sample), mPeakNoise);
+ mNoiseSumSquared += sample * sample;
+ mDownCounter--;
+ if (mDownCounter <= 0) {
+ mState = STATE_WAITING_FOR_SIGNAL;
+ mRootMeanSquareNoise = sqrt(mNoiseSumSquared / NOISE_FRAME_COUNT);
+ mTolerance = std::max(MIN_TOLERANCE, mPeakNoise * 2.0f);
+ mPhase = 0.0; // prevent spike at start
+ }
+ break;
+
+ case STATE_IMMUNE:
+ mDownCounter--;
+ if (mDownCounter <= 0) {
+ mState = STATE_WAITING_FOR_SIGNAL;
+ }
+ break;
+
+ case STATE_WAITING_FOR_SIGNAL:
+ if (peak > mThreshold) {
+ mState = STATE_WAITING_FOR_LOCK;
+ //printf("%5d: switch to STATE_WAITING_FOR_LOCK\n", mFrameCounter);
+ resetAccumulator();
+ }
+ break;
+
case STATE_WAITING_FOR_LOCK:
mSinAccumulator += sample * sinOut;
mCosAccumulator += sample * cosf(mPhase);
@@ -766,13 +844,14 @@
// printf(" predicted = %f, actual = %f\n", predicted, sample);
float diff = predicted - sample;
- if (fabs(diff) > mTolerance) {
+ float absDiff = fabs(diff);
+ mMaxGlitchDelta = std::max(mMaxGlitchDelta, absDiff);
+ if (absDiff > mTolerance) {
mGlitchCount++;
//printf("%5d: Got a glitch # %d, predicted = %f, actual = %f\n",
// mFrameCounter, mGlitchCount, predicted, sample);
mState = STATE_IMMUNE;
- //printf("%5d: switch to STATE_IMMUNE\n", mFrameCounter);
- mDownCounter = mSinePeriod; // Set duration of IMMUNE state.
+ mDownCounter = mSinePeriod * PERIODS_IMMUNE;
}
// Track incoming signal and slowly adjust magnitude to account
@@ -792,44 +871,23 @@
} break;
}
+ float output = 0.0f;
// Output sine wave so we can measure it.
- outputData[i * outputChannelCount] = (sinOut * mOutputAmplitude)
- + (mWhiteNoise.nextRandomDouble() * mNoiseAmplitude);
- // printf("%5d: sin(%f) = %f, %f\n", i, mPhase, sinOut, mPhaseIncrement);
-
- // advance and wrap phase
- mPhase += mPhaseIncrement;
- if (mPhase > M_PI) {
- mPhase -= (2.0 * M_PI);
+ if (sineEnabled) {
+ output = (sinOut * mOutputAmplitude)
+ + (mWhiteNoise.nextRandomDouble() * mNoiseAmplitude);
+ // printf("%5d: sin(%f) = %f, %f\n", i, mPhase, sinOut, mPhaseIncrement);
+ // advance and wrap phase
+ mPhase += mPhaseIncrement;
+ if (mPhase > M_PI) {
+ mPhase -= (2.0 * M_PI);
+ }
}
+ outputData[i * outputChannelCount] = output;
+
mFrameCounter++;
}
-
- // Do these once per buffer.
- switch (mState) {
- case STATE_IDLE:
- mState = STATE_IMMUNE; // so we can tell when
- break;
- case STATE_IMMUNE:
- mDownCounter -= numFrames;
- if (mDownCounter <= 0) {
- mState = STATE_WAITING_FOR_SIGNAL;
- //printf("%5d: switch to STATE_WAITING_FOR_SIGNAL\n", mFrameCounter);
- }
- break;
- case STATE_WAITING_FOR_SIGNAL:
- if (peak > mThreshold) {
- mState = STATE_WAITING_FOR_LOCK;
- //printf("%5d: switch to STATE_WAITING_FOR_LOCK\n", mFrameCounter);
- resetAccumulator();
- }
- break;
- case STATE_WAITING_FOR_LOCK:
- case STATE_LOCKED:
- break;
- }
-
}
void resetAccumulator() {
@@ -840,18 +898,24 @@
void reset() override {
mGlitchCount = 0;
- mState = STATE_IMMUNE;
- mDownCounter = IMMUNE_FRAME_COUNT;
+ mState = STATE_IDLE;
+ mDownCounter = IDLE_FRAME_COUNT;
mPhaseIncrement = 2.0 * M_PI / mSinePeriod;
printf("phaseInc = %f for period %d\n", mPhaseIncrement, mSinePeriod);
resetAccumulator();
mProcessCount = 0;
+ mPeakNoise = 0.0f;
+ mNoiseSumSquared = 0.0;
+ mRootMeanSquareNoise = 0.0;
+ mPhase = 0.0f;
+ mMaxGlitchDelta = 0.0;
}
private:
enum sine_state_t {
STATE_IDLE,
+ STATE_MEASURE_NOISE,
STATE_IMMUNE,
STATE_WAITING_FOR_SIGNAL,
STATE_WAITING_FOR_LOCK,
@@ -859,10 +923,16 @@
};
enum constants {
- IMMUNE_FRAME_COUNT = 48 * 500,
- PERIODS_NEEDED_FOR_LOCK = 8
+ // Arbitrary durations, assuming 48000 Hz
+ IDLE_FRAME_COUNT = 48 * 100,
+ NOISE_FRAME_COUNT = 48 * 600,
+ PERIODS_NEEDED_FOR_LOCK = 8,
+ PERIODS_IMMUNE = 2,
+ MIN_SNRATIO_DB = 65
};
+ static constexpr float MIN_TOLERANCE = 0.01;
+
int mSinePeriod = 79;
double mPhaseIncrement = 0.0;
double mPhase = 0.0;
@@ -870,17 +940,23 @@
double mPreviousPhaseOffset = 0.0;
double mMagnitude = 0.0;
double mThreshold = 0.005;
- double mTolerance = 0.01;
+ double mTolerance = MIN_TOLERANCE;
int32_t mFramesAccumulated = 0;
int32_t mProcessCount = 0;
double mSinAccumulator = 0.0;
double mCosAccumulator = 0.0;
+ float mMaxGlitchDelta = 0.0f;
int32_t mGlitchCount = 0;
double mPeakAmplitude = 0.0;
- int mDownCounter = IMMUNE_FRAME_COUNT;
+ int mDownCounter = IDLE_FRAME_COUNT;
int32_t mFrameCounter = 0;
float mOutputAmplitude = 0.75;
+ // measure background noise
+ float mPeakNoise = 0.0f;
+ double mNoiseSumSquared = 0.0;
+ double mRootMeanSquareNoise = 0.0;
+
PseudoRandom mWhiteNoise;
float mNoiseAmplitude = 0.00; // Used to experiment with warbling caused by DRC.
diff --git a/media/libaaudio/examples/loopback/src/loopback.cpp b/media/libaaudio/examples/loopback/src/loopback.cpp
index 84f9c22..124efd8 100644
--- a/media/libaaudio/examples/loopback/src/loopback.cpp
+++ b/media/libaaudio/examples/loopback/src/loopback.cpp
@@ -37,13 +37,12 @@
// Tag for machine readable results as property = value pairs
#define RESULT_TAG "RESULT: "
-#define NUM_SECONDS 5
-#define PERIOD_MILLIS 1000
-#define NUM_INPUT_CHANNELS 1
#define FILENAME_ALL "/data/loopback_all.wav"
#define FILENAME_ECHOS "/data/loopback_echos.wav"
-#define APP_VERSION "0.2.04"
+#define APP_VERSION "0.3.00"
+constexpr int kLogPeriodMillis = 1000;
+constexpr int kNumInputChannels = 1;
constexpr int kNumCallbacksToDrain = 20;
constexpr int kNumCallbacksToDiscard = 20;
@@ -336,7 +335,7 @@
aaudio_result_t result = AAUDIO_OK;
aaudio_sharing_mode_t requestedInputSharingMode = AAUDIO_SHARING_MODE_SHARED;
- int requestedInputChannelCount = NUM_INPUT_CHANNELS;
+ int requestedInputChannelCount = kNumInputChannels;
aaudio_format_t requestedInputFormat = AAUDIO_FORMAT_UNSPECIFIED;
int32_t requestedInputCapacity = AAUDIO_UNSPECIFIED;
aaudio_performance_mode_t inputPerformanceLevel = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
@@ -459,7 +458,9 @@
argParser.setPerformanceMode(inputPerformanceLevel);
argParser.setChannelCount(requestedInputChannelCount);
argParser.setSharingMode(requestedInputSharingMode);
- // Warning! If you change input capacity then you may not get a FAST track on Legacy path.
+ if (requestedInputCapacity != AAUDIO_UNSPECIFIED) {
+ printf("Warning! If you set input capacity then maybe no FAST track on Legacy path!\n");
+ }
argParser.setBufferCapacity(requestedInputCapacity);
result = recorder.open(argParser);
@@ -510,15 +511,11 @@
// Start OUTPUT first so INPUT does not overflow.
result = player.start();
if (result != AAUDIO_OK) {
- printf("ERROR - AAudioStream_requestStart(output) returned %d = %s\n",
- result, AAudio_convertResultToText(result));
goto finish;
}
result = recorder.start();
if (result != AAUDIO_OK) {
- printf("ERROR - AAudioStream_requestStart(input) returned %d = %s\n",
- result, AAudio_convertResultToText(result));
goto finish;
}
@@ -561,7 +558,7 @@
AAudioStream_getXRunCount(outputStream)
);
}
- int32_t periodMillis = (timeMillis < 2000) ? PERIOD_MILLIS / 4 : PERIOD_MILLIS;
+ int32_t periodMillis = (timeMillis < 2000) ? kLogPeriodMillis / 4 : kLogPeriodMillis;
usleep(periodMillis * 1000);
timeMillis += periodMillis;
}
@@ -586,12 +583,12 @@
if (loopbackData.inputError == AAUDIO_OK) {
if (testMode == TEST_SINE_MAGNITUDE) {
printAudioGraph(loopbackData.audioRecording, 200);
+ // Print again so we don't have to scroll past waveform.
+ printf("OUTPUT Stream ----------------------------------------\n");
+ argParser.compareWithStream(outputStream);
+ printf("INPUT Stream ----------------------------------------\n");
+ argParser.compareWithStream(inputStream);
}
- // Print again so we don't have to scroll past waveform.
- printf("OUTPUT Stream ----------------------------------------\n");
- argParser.compareWithStream(outputStream);
- printf("INPUT Stream ----------------------------------------\n");
- argParser.compareWithStream(inputStream);
loopbackData.loopbackProcessor->report();
}
@@ -600,21 +597,21 @@
int32_t framesRead = AAudioStream_getFramesRead(inputStream);
int32_t framesWritten = AAudioStream_getFramesWritten(inputStream);
printf("Callback Results ---------------------------------------- INPUT\n");
- printf(" input overruns = %d\n", AAudioStream_getXRunCount(inputStream));
+ printf(" input overruns = %8d\n", AAudioStream_getXRunCount(inputStream));
printf(" framesWritten = %8d\n", framesWritten);
printf(" framesRead = %8d\n", framesRead);
printf(" myFramesRead = %8d\n", (int) loopbackData.framesReadTotal);
printf(" written - read = %8d\n", (int) (framesWritten - framesRead));
printf(" insufficient # = %8d\n", (int) loopbackData.insufficientReadCount);
if (loopbackData.insufficientReadCount > 0) {
- printf(" insufficient frames = %8d\n", (int) loopbackData.insufficientReadFrames);
+ printf(" insuffic. frames = %8d\n", (int) loopbackData.insufficientReadFrames);
}
}
{
int32_t framesRead = AAudioStream_getFramesRead(outputStream);
int32_t framesWritten = AAudioStream_getFramesWritten(outputStream);
printf("Callback Results ---------------------------------------- OUTPUT\n");
- printf(" output underruns = %d\n", AAudioStream_getXRunCount(outputStream));
+ printf(" output underruns = %8d\n", AAudioStream_getXRunCount(outputStream));
printf(" myFramesWritten = %8d\n", (int) loopbackData.framesWrittenTotal);
printf(" framesWritten = %8d\n", framesWritten);
printf(" framesRead = %8d\n", framesRead);
@@ -659,4 +656,3 @@
return EXIT_SUCCESS;
}
}
-
diff --git a/media/libaaudio/examples/utils/AAudioSimplePlayer.h b/media/libaaudio/examples/utils/AAudioSimplePlayer.h
index 54b77ba..1645986 100644
--- a/media/libaaudio/examples/utils/AAudioSimplePlayer.h
+++ b/media/libaaudio/examples/utils/AAudioSimplePlayer.h
@@ -193,7 +193,7 @@
aaudio_result_t start() {
aaudio_result_t result = AAudioStream_requestStart(mStream);
if (result != AAUDIO_OK) {
- printf("ERROR - AAudioStream_requestStart() returned %d %s\n",
+ printf("ERROR - AAudioStream_requestStart(output) returned %d %s\n",
result, AAudio_convertResultToText(result));
}
return result;
@@ -203,7 +203,7 @@
aaudio_result_t stop() {
aaudio_result_t result = AAudioStream_requestStop(mStream);
if (result != AAUDIO_OK) {
- printf("ERROR - AAudioStream_requestStop() returned %d %s\n",
+ printf("ERROR - AAudioStream_requestStop(output) returned %d %s\n",
result, AAudio_convertResultToText(result));
}
int32_t xRunCount = AAudioStream_getXRunCount(mStream);
@@ -215,7 +215,7 @@
aaudio_result_t pause() {
aaudio_result_t result = AAudioStream_requestPause(mStream);
if (result != AAUDIO_OK) {
- printf("ERROR - AAudioStream_requestPause() returned %d %s\n",
+ printf("ERROR - AAudioStream_requestPause(output) returned %d %s\n",
result, AAudio_convertResultToText(result));
}
int32_t xRunCount = AAudioStream_getXRunCount(mStream);
@@ -223,11 +223,27 @@
return result;
}
+ aaudio_result_t waitUntilPaused() {
+ aaudio_result_t result = AAUDIO_OK;
+ aaudio_stream_state_t currentState = AAudioStream_getState(mStream);
+ aaudio_stream_state_t inputState = AAUDIO_STREAM_STATE_PAUSING;
+ while (result == AAUDIO_OK && currentState == AAUDIO_STREAM_STATE_PAUSING) {
+ result = AAudioStream_waitForStateChange(mStream, inputState,
+ ¤tState, NANOS_PER_SECOND);
+ inputState = currentState;
+ }
+ if (result != AAUDIO_OK) {
+ return result;
+ }
+ return (currentState == AAUDIO_STREAM_STATE_PAUSED)
+ ? AAUDIO_OK : AAUDIO_ERROR_INVALID_STATE;
+ }
+
// Flush the stream. AAudio will stop calling your callback function.
aaudio_result_t flush() {
aaudio_result_t result = AAudioStream_requestFlush(mStream);
if (result != AAUDIO_OK) {
- printf("ERROR - AAudioStream_requestFlush() returned %d %s\n",
+ printf("ERROR - AAudioStream_requestFlush(output) returned %d %s\n",
result, AAudio_convertResultToText(result));
}
return result;
diff --git a/media/libaaudio/examples/utils/AAudioSimpleRecorder.h b/media/libaaudio/examples/utils/AAudioSimpleRecorder.h
index 869fad0..246e2d7 100644
--- a/media/libaaudio/examples/utils/AAudioSimpleRecorder.h
+++ b/media/libaaudio/examples/utils/AAudioSimpleRecorder.h
@@ -201,8 +201,10 @@
aaudio_result_t start() {
aaudio_result_t result = AAudioStream_requestStart(mStream);
if (result != AAUDIO_OK) {
- fprintf(stderr, "ERROR - AAudioStream_requestStart() returned %d %s\n",
+ fprintf(stderr, "ERROR - AAudioStream_requestStart(input) returned %d %s\n",
result, AAudio_convertResultToText(result));
+ fprintf(stderr, " Did you remember to enter: adb root ????\n");
+
}
return result;
}
@@ -211,8 +213,9 @@
aaudio_result_t stop() {
aaudio_result_t result = AAudioStream_requestStop(mStream);
if (result != AAUDIO_OK) {
- fprintf(stderr, "ERROR - AAudioStream_requestStop() returned %d %s\n",
+ fprintf(stderr, "ERROR - AAudioStream_requestStop(input) returned %d %s\n",
result, AAudio_convertResultToText(result));
+
}
return result;
}
@@ -221,7 +224,7 @@
aaudio_result_t pause() {
aaudio_result_t result = AAudioStream_requestPause(mStream);
if (result != AAUDIO_OK) {
- fprintf(stderr, "ERROR - AAudioStream_requestPause() returned %d %s\n",
+ fprintf(stderr, "ERROR - AAudioStream_requestPause(input) returned %d %s\n",
result, AAudio_convertResultToText(result));
}
return result;
diff --git a/media/libaaudio/examples/write_sine/Android.bp b/media/libaaudio/examples/write_sine/Android.bp
index aa25e67..cc80861 100644
--- a/media/libaaudio/examples/write_sine/Android.bp
+++ b/media/libaaudio/examples/write_sine/Android.bp
@@ -4,6 +4,7 @@
cflags: ["-Wall", "-Werror"],
shared_libs: ["libaaudio"],
header_libs: ["libaaudio_example_utils"],
+ pack_relocations: false,
}
cc_test {
@@ -12,4 +13,5 @@
cflags: ["-Wall", "-Werror"],
shared_libs: ["libaaudio"],
header_libs: ["libaaudio_example_utils"],
+ pack_relocations: false,
}
diff --git a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
index e33e9f8..7a48153 100644
--- a/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
+++ b/media/libaaudio/examples/write_sine/src/write_sine_callback.cpp
@@ -30,6 +30,8 @@
#include "AAudioSimplePlayer.h"
#include "AAudioArgsParser.h"
+#define APP_VERSION "0.1.5"
+
/**
* Open stream, play some sine waves, then close the stream.
*
@@ -109,13 +111,13 @@
startedAtNanos = getNanoseconds(CLOCK_MONOTONIC);
for (int second = 0; second < durationSeconds; second++) {
// Sleep a while. Wake up early if there is an error, for example a DISCONNECT.
- long ret = myData.waker.wait(AAUDIO_OK, NANOS_PER_SECOND);
+ myData.waker.wait(AAUDIO_OK, NANOS_PER_SECOND);
int64_t millis =
(getNanoseconds(CLOCK_MONOTONIC) - startedAtNanos) / NANOS_PER_MILLISECOND;
result = myData.waker.get();
- printf("wait() returns %ld, aaudio_result = %d, at %6d millis"
+ printf(" waker result = %d, at %6d millis"
", second = %3d, framesWritten = %8d, underruns = %d\n",
- ret, result, (int) millis,
+ result, (int) millis,
second,
(int) AAudioStream_getFramesWritten(player.getStream()),
(int) AAudioStream_getXRunCount(player.getStream()));
@@ -138,6 +140,10 @@
if (result != AAUDIO_OK) {
goto error;
}
+ result = player.waitUntilPaused();
+ if (result != AAUDIO_OK) {
+ goto error;
+ }
result = player.flush();
}
if (result != AAUDIO_OK) {
@@ -219,7 +225,7 @@
// in a buffer if we hang or crash.
setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
- printf("%s - Play a sine sweep using an AAudio callback V0.1.4\n", argv[0]);
+ printf("%s - Play a sine sweep using an AAudio callback V%s\n", argv[0], APP_VERSION);
for (int i = 1; i < argc; i++) {
const char *arg = argv[i];
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 8dc31d0..e272f2a 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -146,14 +146,14 @@
AAUDIO_API void AAudioStreamBuilder_setChannelCount(AAudioStreamBuilder* builder,
int32_t channelCount)
{
- AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
- streamBuilder->setSamplesPerFrame(channelCount);
+ AAudioStreamBuilder_setSamplesPerFrame(builder, channelCount);
}
AAUDIO_API void AAudioStreamBuilder_setSamplesPerFrame(AAudioStreamBuilder* builder,
- int32_t channelCount)
+ int32_t samplesPerFrame)
{
- AAudioStreamBuilder_setChannelCount(builder, channelCount);
+ AudioStreamBuilder *streamBuilder = convertAAudioBuilderToStreamBuilder(builder);
+ streamBuilder->setSamplesPerFrame(samplesPerFrame);
}
AAUDIO_API void AAudioStreamBuilder_setDirection(AAudioStreamBuilder* builder,
diff --git a/media/libeffects/visualizer/Android.mk b/media/libeffects/visualizer/Android.mk
index 3534149..35e2f3d 100644
--- a/media/libeffects/visualizer/Android.mk
+++ b/media/libeffects/visualizer/Android.mk
@@ -9,6 +9,7 @@
LOCAL_CFLAGS+= -O2 -fvisibility=hidden
LOCAL_CFLAGS += -Wall -Werror
+LOCAL_CFLAGS += -DBUILD_FLOAT -DSUPPORT_MC
LOCAL_SHARED_LIBRARIES := \
libcutils \
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index e2ccfb7..00bc371 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -32,8 +32,6 @@
#include <audio_effects/effect_visualizer.h>
#include <audio_utils/primitives.h>
-#define BUILD_FLOAT
-
#ifdef BUILD_FLOAT
static constexpr audio_format_t kProcessFormat = AUDIO_FORMAT_PCM_FLOAT;
@@ -157,7 +155,12 @@
if (pConfig->inputCfg.samplingRate != pConfig->outputCfg.samplingRate) return -EINVAL;
if (pConfig->inputCfg.channels != pConfig->outputCfg.channels) return -EINVAL;
if (pConfig->inputCfg.format != pConfig->outputCfg.format) return -EINVAL;
- if (pConfig->inputCfg.channels != AUDIO_CHANNEL_OUT_STEREO) return -EINVAL;
+ const uint32_t channelCount = audio_channel_count_from_out_mask(pConfig->inputCfg.channels);
+#ifdef SUPPORT_MC
+ if (channelCount < 1 || channelCount > FCC_8) return -EINVAL;
+#else
+ if (channelCount != FCC_2) return -EINVAL;
+#endif
if (pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_WRITE &&
pConfig->outputCfg.accessMode != EFFECT_BUFFER_ACCESS_ACCUMULATE) return -EINVAL;
if (pConfig->inputCfg.format != kProcessFormat) return -EINVAL;
@@ -356,7 +359,7 @@
// store the measurement
pContext->mPastMeasurements[pContext->mMeasurementBufferIdx].mPeakU16 = (uint16_t)maxSample;
pContext->mPastMeasurements[pContext->mMeasurementBufferIdx].mRmsSquared =
- rmsSqAcc / (inBuffer->frameCount * pContext->mChannelCount);
+ rmsSqAcc / sampleLen;
pContext->mPastMeasurements[pContext->mMeasurementBufferIdx].mIsValid = true;
if (++pContext->mMeasurementBufferIdx >= pContext->mMeasurementWindowSizeInBuffers) {
pContext->mMeasurementBufferIdx = 0;
@@ -375,12 +378,17 @@
#ifdef BUILD_FLOAT
float maxSample = 0.f;
- for (size_t inIdx = 0; inIdx < sampleLen; ++inIdx) {
- maxSample = fmax(maxSample, fabs(inBuffer->f32[inIdx]));
+ for (size_t inIdx = 0; inIdx < sampleLen; ) {
+ // we reconstruct the actual summed value to ensure proper normalization
+ // for multichannel outputs (channels > 2 may often be 0).
+ float smp = 0.f;
+ for (int i = 0; i < pContext->mChannelCount; ++i) {
+ smp += inBuffer->f32[inIdx++];
+ }
+ maxSample = fmax(maxSample, fabs(smp));
}
if (maxSample > 0.f) {
- constexpr float halfish = 127.f / 256.f;
- fscale = halfish / maxSample;
+ fscale = 127.f / maxSample;
int exp; // unused
const float significand = frexp(fscale, &exp);
if (significand == 0.5f) {
@@ -412,7 +420,8 @@
} else {
assert(pContext->mScalingMode == VISUALIZER_SCALING_MODE_AS_PLAYED);
#ifdef BUILD_FLOAT
- fscale = 0.5f; // default divide by 2 to account for sum of L + R.
+ // Note: if channels are uncorrelated, 1/sqrt(N) could be used at the risk of clipping.
+ fscale = 1.f / pContext->mChannelCount; // account for summing all the channels together.
#else
shift = 9;
#endif // BUILD_FLOAT
@@ -422,17 +431,19 @@
uint32_t inIdx;
uint8_t *buf = pContext->mCaptureBuf;
for (inIdx = 0, captIdx = pContext->mCaptureIdx;
- inIdx < inBuffer->frameCount;
- inIdx++, captIdx++) {
- if (captIdx >= CAPTURE_BUF_SIZE) {
- // wrap around
- captIdx = 0;
- }
+ inIdx < sampleLen;
+ captIdx++) {
+ if (captIdx >= CAPTURE_BUF_SIZE) captIdx = 0; // wrap
+
#ifdef BUILD_FLOAT
- const float smp = (inBuffer->f32[2 * inIdx] + inBuffer->f32[2 * inIdx + 1]) * fscale;
- buf[captIdx] = clamp8_from_float(smp);
+ float smp = 0.f;
+ for (uint32_t i = 0; i < pContext->mChannelCount; ++i) {
+ smp += inBuffer->f32[inIdx++];
+ }
+ buf[captIdx] = clamp8_from_float(smp * fscale);
#else
- const int32_t smp = (inBuffer->s16[2 * inIdx] + inBuffer->s16[2 * inIdx + 1]) >> shift;
+ const int32_t smp = (inBuffer->s16[inIdx] + inBuffer->s16[inIdx + 1]) >> shift;
+ inIdx += FCC_2; // integer supports stereo only.
buf[captIdx] = ((uint8_t)smp)^0x80;
#endif // BUILD_FLOAT
}
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 25d28ff..3d9e62e 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -291,6 +291,7 @@
"libmediaextractor",
"libmediandk",
"libnativewindow",
+ "libmediandk_utils",
"libstagefright_foundation",
"libui",
"libutils",
@@ -305,6 +306,10 @@
"media_plugin_headers",
],
+ include_dirs: [
+ "frameworks/av/media/ndk",
+ ],
+
static_libs: [
"libstagefright_rtsp",
"libstagefright_timedtext",
diff --git a/media/libmedia/MediaUtils.cpp b/media/libmedia/MediaUtils.cpp
index 320c7a9..bcc7ebf 100644
--- a/media/libmedia/MediaUtils.cpp
+++ b/media/libmedia/MediaUtils.cpp
@@ -25,6 +25,7 @@
#include "MediaUtils.h"
extern "C" size_t __cfi_shadow_size();
+extern "C" void __scudo_set_rss_limit(size_t, int) __attribute__((weak));
namespace android {
@@ -65,6 +66,14 @@
maxMem = propVal;
}
+ // If 64-bit Scudo is in use, enforce the hard RSS limit (in MB).
+ if (maxMem != SIZE_MAX && sizeof(void *) == 8 &&
+ &__scudo_set_rss_limit != 0) {
+ __scudo_set_rss_limit(maxMem >> 20, 1);
+ ALOGV("Scudo hard RSS limit set to %zu MB", maxMem >> 20);
+ return;
+ }
+
// Increase by the size of the CFI shadow mapping. Most of the shadow is not
// backed with physical pages, and it is possible for the result to be
// higher than total physical memory. This is fine for RLIMIT_AS.
diff --git a/media/libmedia/NdkWrapper.cpp b/media/libmedia/NdkWrapper.cpp
index 9e09c7e..eed96e7 100644
--- a/media/libmedia/NdkWrapper.cpp
+++ b/media/libmedia/NdkWrapper.cpp
@@ -31,6 +31,8 @@
#include <media/stagefright/foundation/AMessage.h>
#include <utils/Errors.h>
+#include "NdkMediaDataSourceCallbacksPriv.h"
+
namespace android {
static const size_t kAESBlockSize = 16; // AES_BLOCK_SIZE
@@ -1244,8 +1246,14 @@
return new AMediaCodecCryptoInfoWrapper(AMediaExtractor_getSampleCryptoInfo(mAMediaExtractor));
}
+AMediaDataSourceWrapper::AMediaDataSourceWrapper(const sp<DataSource> &dataSource)
+ : mDataSource(dataSource),
+ mAMediaDataSource(convertDataSourceToAMediaDataSource(dataSource)) {
+}
+
AMediaDataSourceWrapper::AMediaDataSourceWrapper(AMediaDataSource *aDataSource)
- : mAMediaDataSource(aDataSource) {
+ : mDataSource(NULL),
+ mAMediaDataSource(aDataSource) {
}
AMediaDataSourceWrapper::~AMediaDataSourceWrapper() {
diff --git a/media/libmedia/include/media/Crypto.h b/media/libmedia/include/media/Crypto.h
deleted file mode 100644
index b68413d..0000000
--- a/media/libmedia/include/media/Crypto.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CRYPTO_H_
-
-#define CRYPTO_H_
-
-#include <media/ICrypto.h>
-#include <utils/threads.h>
-#include <utils/KeyedVector.h>
-
-#include "SharedLibrary.h"
-
-namespace android {
-
-struct CryptoFactory;
-struct CryptoPlugin;
-
-struct Crypto : public BnCrypto {
- Crypto();
- virtual ~Crypto();
-
- virtual status_t initCheck() const;
-
- virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]);
-
- virtual status_t createPlugin(
- const uint8_t uuid[16], const void *data, size_t size);
-
- virtual status_t destroyPlugin();
-
- virtual bool requiresSecureDecoderComponent(
- const char *mime) const;
-
- virtual void notifyResolution(uint32_t width, uint32_t height);
-
- virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId);
-
- virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16],
- CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern,
- const sp<IMemory> &source, size_t offset,
- const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
- const DestinationBuffer &destination, AString *errorDetailMsg);
-
- virtual void setHeap(const sp<IMemoryHeap>&) {}
- virtual void unsetHeap(const sp<IMemoryHeap>&) {}
-
-private:
- mutable Mutex mLock;
-
- status_t mInitCheck;
- sp<SharedLibrary> mLibrary;
- CryptoFactory *mFactory;
- CryptoPlugin *mPlugin;
-
- static KeyedVector<Vector<uint8_t>, String8> mUUIDToLibraryPathMap;
- static KeyedVector<String8, wp<SharedLibrary> > mLibraryPathToOpenLibraryMap;
- static Mutex mMapLock;
-
- void findFactoryForScheme(const uint8_t uuid[16]);
- bool loadLibraryForScheme(const String8 &path, const uint8_t uuid[16]);
- void closeFactory();
-
- DISALLOW_EVIL_CONSTRUCTORS(Crypto);
-};
-
-} // namespace android
-
-#endif // CRYPTO_H_
diff --git a/media/libmedia/include/media/Drm.h b/media/libmedia/include/media/Drm.h
deleted file mode 100644
index fc869cc..0000000
--- a/media/libmedia/include/media/Drm.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef DRM_H_
-
-#define DRM_H_
-
-#include "SharedLibrary.h"
-
-#include <media/IDrm.h>
-#include <media/IDrmClient.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class DrmFactory;
-class DrmPlugin;
-struct DrmSessionClientInterface;
-
-struct Drm : public BnDrm,
- public IBinder::DeathRecipient,
- public DrmPluginListener {
- Drm();
- virtual ~Drm();
-
- virtual status_t initCheck() const;
-
- virtual bool isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType);
-
- virtual status_t createPlugin(const uint8_t uuid[16], const String8 &appPackageName);
-
- virtual status_t destroyPlugin();
-
- virtual status_t openSession(Vector<uint8_t> &sessionId);
-
- virtual status_t closeSession(Vector<uint8_t> const &sessionId);
-
- virtual status_t
- getKeyRequest(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &initData,
- String8 const &mimeType, DrmPlugin::KeyType keyType,
- KeyedVector<String8, String8> const &optionalParameters,
- Vector<uint8_t> &request, String8 &defaultUrl,
- DrmPlugin::KeyRequestType *keyRequestType);
-
- virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &response,
- Vector<uint8_t> &keySetId);
-
- virtual status_t removeKeys(Vector<uint8_t> const &keySetId);
-
- virtual status_t restoreKeys(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keySetId);
-
- virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
- KeyedVector<String8, String8> &infoMap) const;
-
- virtual status_t getProvisionRequest(String8 const &certType,
- String8 const &certAuthority,
- Vector<uint8_t> &request,
- String8 &defaulUrl);
-
- virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
- Vector<uint8_t> &certificate,
- Vector<uint8_t> &wrappedKey);
-
- virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops);
- virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
-
- virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
- virtual status_t releaseAllSecureStops();
-
- virtual status_t getPropertyString(String8 const &name, String8 &value ) const;
- virtual status_t getPropertyByteArray(String8 const &name,
- Vector<uint8_t> &value ) const;
- virtual status_t setPropertyString(String8 const &name, String8 const &value ) const;
- virtual status_t setPropertyByteArray(String8 const &name,
- Vector<uint8_t> const &value ) const;
-
- virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm);
-
- virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
- String8 const &algorithm);
-
- virtual status_t encrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output);
-
- virtual status_t decrypt(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &input,
- Vector<uint8_t> const &iv,
- Vector<uint8_t> &output);
-
- virtual status_t sign(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> &signature);
-
- virtual status_t verify(Vector<uint8_t> const &sessionId,
- Vector<uint8_t> const &keyId,
- Vector<uint8_t> const &message,
- Vector<uint8_t> const &signature,
- bool &match);
-
- virtual status_t signRSA(Vector<uint8_t> const &sessionId,
- String8 const &algorithm,
- Vector<uint8_t> const &message,
- Vector<uint8_t> const &wrappedKey,
- Vector<uint8_t> &signature);
-
- virtual status_t setListener(const sp<IDrmClient>& listener);
-
- virtual void sendEvent(DrmPlugin::EventType eventType, int extra,
- Vector<uint8_t> const *sessionId,
- Vector<uint8_t> const *data);
-
- virtual void sendExpirationUpdate(Vector<uint8_t> const *sessionId,
- int64_t expiryTimeInMS);
-
- virtual void sendKeysChange(Vector<uint8_t> const *sessionId,
- Vector<DrmPlugin::KeyStatus> const *keyStatusList,
- bool hasNewUsableKey);
-
- virtual void binderDied(const wp<IBinder> &the_late_who);
-
-private:
- static Mutex mLock;
-
- status_t mInitCheck;
-
- sp<DrmSessionClientInterface> mDrmSessionClient;
-
- sp<IDrmClient> mListener;
- mutable Mutex mEventLock;
- mutable Mutex mNotifyLock;
-
- sp<SharedLibrary> mLibrary;
- DrmFactory *mFactory;
- DrmPlugin *mPlugin;
-
- static KeyedVector<Vector<uint8_t>, String8> mUUIDToLibraryPathMap;
- static KeyedVector<String8, wp<SharedLibrary> > mLibraryPathToOpenLibraryMap;
- static Mutex mMapLock;
-
- void findFactoryForScheme(const uint8_t uuid[16]);
- bool loadLibraryForScheme(const String8 &path, const uint8_t uuid[16]);
- void closeFactory();
- void writeByteArray(Parcel &obj, Vector<uint8_t> const *array);
-
- DISALLOW_EVIL_CONSTRUCTORS(Drm);
-};
-
-} // namespace android
-
-#endif // CRYPTO_H_
diff --git a/media/libmedia/include/media/NdkWrapper.h b/media/libmedia/include/media/NdkWrapper.h
index b3b0688..8a417f6 100644
--- a/media/libmedia/include/media/NdkWrapper.h
+++ b/media/libmedia/include/media/NdkWrapper.h
@@ -280,13 +280,10 @@
struct AMediaDataSourceWrapper : public RefBase {
+ AMediaDataSourceWrapper(const sp<DataSource>&);
AMediaDataSourceWrapper(AMediaDataSource*);
- AMediaDataSourceWrapper(int fd, int64_t offset, int64_t length);
AMediaDataSource *getAMediaDataSource();
- int getFd() { return mFd; }
- int64_t getOffset() { return mOffset; }
- int64_t getLength() { return mLength; }
void close();
@@ -294,10 +291,8 @@
virtual ~AMediaDataSourceWrapper();
private:
+ sp<DataSource> mDataSource;
AMediaDataSource *mAMediaDataSource;
- int mFd;
- int64_t mOffset;
- int64_t mLength;
DISALLOW_EVIL_CONSTRUCTORS(AMediaDataSourceWrapper);
};
diff --git a/media/libmedia/include/media/mediametadataretriever.h b/media/libmedia/include/media/mediametadataretriever.h
index 1e5fa07..d29e97d 100644
--- a/media/libmedia/include/media/mediametadataretriever.h
+++ b/media/libmedia/include/media/mediametadataretriever.h
@@ -71,6 +71,8 @@
METADATA_KEY_COLOR_STANDARD = 35,
METADATA_KEY_COLOR_TRANSFER = 36,
METADATA_KEY_COLOR_RANGE = 37,
+ METADATA_KEY_SAMPLERATE = 38,
+ METADATA_KEY_BITS_PER_SAMPLE = 39,
// Add more here...
};
diff --git a/media/libmediaextractor/include/media/stagefright/MetaDataBase.h b/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
index 0a99974..28b8c2b 100644
--- a/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
+++ b/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
@@ -89,7 +89,6 @@
kKeyMaxHeight = 'maxH',
kKeyThumbnailTime = 'thbT', // int64_t (usecs)
kKeyTrackID = 'trID',
- kKeyIsDRM = 'idrm', // int32_t (bool)
kKeyEncoderDelay = 'encd', // int32_t (frames)
kKeyEncoderPadding = 'encp', // int32_t (frames)
diff --git a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
index f795478..1860b0c 100644
--- a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
+++ b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
@@ -34,7 +34,6 @@
#include <media/stagefright/MetaData.h>
#include <media/stagefright/NdkUtils.h>
#include <media/stagefright/Utils.h>
-#include "NdkMediaDataSourceCallbacksPriv.h"
namespace android {
@@ -137,8 +136,7 @@
ALOGV("setDataSource (source: %p)", source.get());
resetDataSource();
- AMediaDataSource *aSource = convertDataSourceToAMediaDataSource(source);
- mDataSourceWrapper = new AMediaDataSourceWrapper(aSource);
+ mDataSourceWrapper = new AMediaDataSourceWrapper(source);
return OK;
}
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index a37973b..09b19d7 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -29,6 +29,7 @@
"libmediametrics",
"libmediautils",
"libmemunreachable",
+ "libnetd_client",
"libpowermanager",
"libstagefright",
"libstagefright_foundation",
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 3208d16..d96d358 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -239,52 +239,29 @@
name: "libstagefright_player2",
srcs: [
- "CallbackDataSource.cpp",
- "CallbackMediaSource.cpp",
- "ClearDataSourceFactory.cpp",
"ClearFileSource.cpp",
"DataURISource.cpp",
"HTTPBase.cpp",
"HevcUtils.cpp",
- "InterfaceUtils.cpp",
"MediaClock.cpp",
- "MediaExtractor.cpp",
- "MediaExtractorFactory.cpp",
"NdkUtils.cpp",
- "NuCachedSource2.cpp",
- "RemoteMediaExtractor.cpp",
- "RemoteMediaSource.cpp",
"Utils.cpp",
"VideoFrameScheduler.cpp",
"http/ClearMediaHTTP.cpp",
],
shared_libs: [
- "libbinder",
- "libcutils",
"libgui",
"liblog",
- "libaudioclient",
- "libmediaextractor",
- "libmediametrics",
- "libmediautils",
"libnetd_client",
- "libui",
"libutils",
- "libmedia_helper",
"libstagefright_foundation",
- "libziparchive",
],
static_libs: [
- "libstagefright_esds",
"libmedia_player2_util",
],
- header_libs:[
- "media_plugin_headers",
- ],
-
export_include_dirs: [
"include",
],
diff --git a/media/libstagefright/ClearDataSourceFactory.cpp b/media/libstagefright/ClearDataSourceFactory.cpp
deleted file mode 100644
index 5d23fda..0000000
--- a/media/libstagefright/ClearDataSourceFactory.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-//#define LOG_NDEBUG 0
-#define LOG_TAG "ClearDataSourceFactory"
-
-#include "include/HTTPBase.h"
-#include "include/NuCachedSource2.h"
-
-#include <media/MediaHTTPConnection.h>
-#include <media/MediaHTTPService.h>
-#include <media/stagefright/ClearFileSource.h>
-#include <media/stagefright/ClearMediaHTTP.h>
-#include <media/stagefright/ClearDataSourceFactory.h>
-#include <media/stagefright/DataURISource.h>
-#include <utils/String8.h>
-
-namespace android {
-
-// static
-sp<DataSource> ClearDataSourceFactory::CreateFromURI(
- const sp<MediaHTTPService> &httpService,
- const char *uri,
- const KeyedVector<String8, String8> *headers,
- String8 *contentType,
- HTTPBase *httpSource) {
- if (contentType != NULL) {
- *contentType = "";
- }
-
- sp<DataSource> source;
- if (!strncasecmp("file://", uri, 7)) {
- source = new ClearFileSource(uri + 7);
- } else if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
- if (httpService == NULL) {
- ALOGE("Invalid http service!");
- return NULL;
- }
-
- if (httpSource == NULL) {
- sp<MediaHTTPConnection> conn = httpService->makeHTTPConnection();
- if (conn == NULL) {
- ALOGE("Failed to make http connection from http service!");
- return NULL;
- }
- httpSource = new ClearMediaHTTP(conn);
- }
-
- String8 cacheConfig;
- bool disconnectAtHighwatermark = false;
- KeyedVector<String8, String8> nonCacheSpecificHeaders;
- if (headers != NULL) {
- nonCacheSpecificHeaders = *headers;
- NuCachedSource2::RemoveCacheSpecificHeaders(
- &nonCacheSpecificHeaders,
- &cacheConfig,
- &disconnectAtHighwatermark);
- }
-
- if (httpSource->connect(uri, &nonCacheSpecificHeaders) != OK) {
- ALOGE("Failed to connect http source!");
- return NULL;
- }
-
- if (contentType != NULL) {
- *contentType = httpSource->getMIMEType();
- }
-
- source = NuCachedSource2::Create(
- httpSource,
- cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
- disconnectAtHighwatermark);
- } else if (!strncasecmp("data:", uri, 5)) {
- source = DataURISource::Create(uri);
- } else {
- // Assume it's a filename.
- source = new ClearFileSource(uri);
- }
-
- if (source == NULL || source->initCheck() != OK) {
- return NULL;
- }
-
- return source;
-}
-
-sp<DataSource> ClearDataSourceFactory::CreateFromFd(int fd, int64_t offset, int64_t length) {
- sp<ClearFileSource> source = new ClearFileSource(fd, offset, length);
- return source->initCheck() != OK ? nullptr : source;
-}
-
-sp<DataSource> ClearDataSourceFactory::CreateMediaHTTP(const sp<MediaHTTPService> &httpService) {
- if (httpService == NULL) {
- return NULL;
- }
-
- sp<MediaHTTPConnection> conn = httpService->makeHTTPConnection();
- if (conn == NULL) {
- return NULL;
- } else {
- return new ClearMediaHTTP(conn);
- }
-}
-
-} // namespace android
diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp
index 0f24329..03e0d12 100644
--- a/media/libstagefright/HTTPBase.cpp
+++ b/media/libstagefright/HTTPBase.cpp
@@ -114,30 +114,4 @@
mMaxBandwidthHistoryItems = numHistoryItems;
}
-// static
-void HTTPBase::RegisterSocketUserTag(int sockfd, uid_t uid, uint32_t kTag) {
- int res = qtaguid_tagSocket(sockfd, kTag, uid);
- if (res != 0) {
- ALOGE("Failed tagging socket %d for uid %d (My UID=%d)", sockfd, uid, geteuid());
- }
-}
-
-// static
-void HTTPBase::UnRegisterSocketUserTag(int sockfd) {
- int res = qtaguid_untagSocket(sockfd);
- if (res != 0) {
- ALOGE("Failed untagging socket %d (My UID=%d)", sockfd, geteuid());
- }
-}
-
-// static
-void HTTPBase::RegisterSocketUserMark(int sockfd, uid_t uid) {
- setNetworkForUser(uid, sockfd);
-}
-
-// static
-void HTTPBase::UnRegisterSocketUserMark(int sockfd) {
- RegisterSocketUserMark(sockfd, geteuid());
-}
-
} // namespace android
diff --git a/media/libstagefright/MetaDataUtils.cpp b/media/libstagefright/MetaDataUtils.cpp
index 2cf79c3..a3259fd 100644
--- a/media/libstagefright/MetaDataUtils.cpp
+++ b/media/libstagefright/MetaDataUtils.cpp
@@ -56,6 +56,32 @@
return true;
}
+bool MakeAVCCodecSpecificData(AMediaFormat *meta, const uint8_t *data, size_t size) {
+ if (meta == nullptr || data == nullptr || size == 0) {
+ return false;
+ }
+
+ int32_t width;
+ int32_t height;
+ int32_t sarWidth;
+ int32_t sarHeight;
+ sp<ABuffer> accessUnit = new ABuffer((void*)data, size);
+ sp<ABuffer> csd = MakeAVCCodecSpecificData(accessUnit, &width, &height, &sarWidth, &sarHeight);
+ if (csd == nullptr) {
+ return false;
+ }
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_VIDEO_AVC);
+
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CSD_AVC, csd->data(), csd->size());
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_WIDTH, width);
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_HEIGHT, height);
+ if (sarWidth > 0 && sarHeight > 0) {
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAR_WIDTH, sarWidth);
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAR_HEIGHT, sarHeight);
+ }
+ return true;
+}
+
bool MakeAACCodecSpecificData(MetaDataBase &meta, const uint8_t *data, size_t size) {
if (data == nullptr || size < 7) {
return false;
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 1a01350..f34d54c 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -276,12 +276,6 @@
return NO_INIT;
}
- int32_t drm = 0;
- if (fileMeta->findInt32(kKeyIsDRM, &drm) && drm != 0) {
- ALOGE("frame grab not allowed.");
- return ERROR_DRM_UNKNOWN;
- }
-
size_t n = mExtractor->countTracks();
size_t i;
for (i = 0; i < n; ++i) {
@@ -551,6 +545,19 @@
if (!trackMeta->findInt32(kKeyBitRate, &audioBitrate)) {
audioBitrate = -1;
}
+
+ int32_t bitsPerSample = -1;
+ int32_t sampleRate = -1;
+ trackMeta->findInt32(kKeyBitsPerSample, &bitsPerSample);
+ trackMeta->findInt32(kKeySampleRate, &sampleRate);
+ if (bitsPerSample >= 0) {
+ sprintf(tmp, "%d", bitsPerSample);
+ mMetaData.add(METADATA_KEY_BITS_PER_SAMPLE, String8(tmp));
+ }
+ if (sampleRate >= 0) {
+ sprintf(tmp, "%d", sampleRate);
+ mMetaData.add(METADATA_KEY_SAMPLERATE, String8(tmp));
+ }
} else if (!hasVideo && !strncasecmp("video/", mime, 6)) {
hasVideo = true;
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 0c6c45b..96993e9 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -787,6 +787,11 @@
msg->setInt32("channel-count", numChannels);
msg->setInt32("sample-rate", sampleRate);
+ int32_t bitsPerSample;
+ if (meta->findInt32(kKeyBitsPerSample, &bitsPerSample)) {
+ msg->setInt32("bits-per-sample", bitsPerSample);
+ }
+
int32_t channelMask;
if (meta->findInt32(kKeyChannelMask, &channelMask)) {
msg->setInt32("channel-mask", channelMask);
@@ -1526,6 +1531,10 @@
if (msg->findInt32("sample-rate", &sampleRate)) {
meta->setInt32(kKeySampleRate, sampleRate);
}
+ int32_t bitsPerSample;
+ if (msg->findInt32("bits-per-sample", &bitsPerSample)) {
+ meta->setInt32(kKeyBitsPerSample, bitsPerSample);
+ }
int32_t channelMask;
if (msg->findInt32("channel-mask", &channelMask)) {
meta->setInt32(kKeyChannelMask, channelMask);
@@ -1584,7 +1593,7 @@
if (msg->findBuffer("csd-1", &csd1)) {
std::vector<char> avcc(csd0size + csd1->size() + 1024);
size_t outsize = reassembleAVCC(csd0, csd1, avcc.data());
- meta->setData(kKeyAVCC, kKeyAVCC, avcc.data(), outsize);
+ meta->setData(kKeyAVCC, kTypeAVCC, avcc.data(), outsize);
}
} else if (mime == MEDIA_MIMETYPE_AUDIO_AAC || mime == MEDIA_MIMETYPE_VIDEO_MPEG4) {
std::vector<char> esds(csd0size + 31);
@@ -1596,7 +1605,7 @@
mime == MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC) {
std::vector<uint8_t> hvcc(csd0size + 1024);
size_t outsize = reassembleHVCC(csd0, hvcc.data(), hvcc.size(), 4);
- meta->setData(kKeyHVCC, kKeyHVCC, hvcc.data(), outsize);
+ meta->setData(kKeyHVCC, kTypeHVCC, hvcc.data(), outsize);
} else if (mime == MEDIA_MIMETYPE_VIDEO_VP9) {
meta->setData(kKeyVp9CodecPrivate, 0, csd0->data(), csd0->size());
} else if (mime == MEDIA_MIMETYPE_AUDIO_OPUS) {
@@ -1613,6 +1622,11 @@
meta->setData(kKeyVorbisBooks, 0, csd1->data(), csd1->size());
}
}
+ } else if (mime == MEDIA_MIMETYPE_VIDEO_AVC && msg->findBuffer("csd-avc", &csd0)) {
+ meta->setData(kKeyAVCC, kTypeAVCC, csd0->data(), csd0->size());
+ } else if ((mime == MEDIA_MIMETYPE_VIDEO_HEVC || mime == MEDIA_MIMETYPE_IMAGE_ANDROID_HEIC)
+ && msg->findBuffer("csd-hevc", &csd0)) {
+ meta->setData(kKeyHVCC, kTypeHVCC, csd0->data(), csd0->size());
}
int32_t timeScale;
diff --git a/media/libstagefright/codecs/amrnb/common/src/l_abs.cpp b/media/libstagefright/codecs/amrnb/common/src/l_abs.cpp
index fd1c90d..7e0ae99 100644
--- a/media/libstagefright/codecs/amrnb/common/src/l_abs.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/l_abs.cpp
@@ -176,7 +176,7 @@
/*----------------------------------------------------------------------------
; FUNCTION CODE
----------------------------------------------------------------------------*/
-Word32 L_abs(register Word32 L_var1)
+Word32 L_abs(Word32 L_var1)
{
/*----------------------------------------------------------------------------
; Define all local variables
diff --git a/media/libstagefright/codecs/amrnb/common/src/l_shr_r.cpp b/media/libstagefright/codecs/amrnb/common/src/l_shr_r.cpp
index f609a73..47e1ee8 100644
--- a/media/libstagefright/codecs/amrnb/common/src/l_shr_r.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/l_shr_r.cpp
@@ -190,7 +190,7 @@
/*----------------------------------------------------------------------------
; FUNCTION CODE
----------------------------------------------------------------------------*/
-Word32 L_shr_r(register Word32 L_var1, register Word16 var2, Flag *pOverflow)
+Word32 L_shr_r(Word32 L_var1, Word16 var2, Flag *pOverflow)
{
Word32 result;
diff --git a/media/libstagefright/codecs/amrnb/common/src/negate.cpp b/media/libstagefright/codecs/amrnb/common/src/negate.cpp
index be58d2b..aa36422 100644
--- a/media/libstagefright/codecs/amrnb/common/src/negate.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/negate.cpp
@@ -161,7 +161,7 @@
/*----------------------------------------------------------------------------
; FUNCTION CODE
----------------------------------------------------------------------------*/
-Word16 negate(register Word16 var1)
+Word16 negate(Word16 var1)
{
/*----------------------------------------------------------------------------
; Define all local variables
diff --git a/media/libstagefright/codecs/amrnb/common/src/round.cpp b/media/libstagefright/codecs/amrnb/common/src/round.cpp
index 71d1702..633a8c9 100644
--- a/media/libstagefright/codecs/amrnb/common/src/round.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/round.cpp
@@ -184,7 +184,7 @@
/*----------------------------------------------------------------------------
; FUNCTION CODE
----------------------------------------------------------------------------*/
-Word16 pv_round(register Word32 L_var1, Flag *pOverflow)
+Word16 pv_round(Word32 L_var1, Flag *pOverflow)
{
Word16 result;
diff --git a/media/libstagefright/codecs/amrnb/common/src/shr_r.cpp b/media/libstagefright/codecs/amrnb/common/src/shr_r.cpp
index 6656f93..cdcc246 100644
--- a/media/libstagefright/codecs/amrnb/common/src/shr_r.cpp
+++ b/media/libstagefright/codecs/amrnb/common/src/shr_r.cpp
@@ -193,7 +193,7 @@
/*----------------------------------------------------------------------------
; FUNCTION CODE
----------------------------------------------------------------------------*/
-Word16 shr_r(register Word16 var1, register Word16 var2, Flag *pOverflow)
+Word16 shr_r(Word16 var1, Word16 var2, Flag *pOverflow)
{
/*----------------------------------------------------------------------------
; Define all local variables
diff --git a/media/libstagefright/foundation/ColorUtils.cpp b/media/libstagefright/foundation/ColorUtils.cpp
index c4eaa27..070e325 100644
--- a/media/libstagefright/foundation/ColorUtils.cpp
+++ b/media/libstagefright/foundation/ColorUtils.cpp
@@ -23,6 +23,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALookup.h>
#include <media/stagefright/foundation/ColorUtils.h>
+#include <media/NdkMediaFormatPriv.h>
namespace android {
@@ -342,6 +343,14 @@
aspects.mRange = fullRange ? ColorAspects::RangeFull : ColorAspects::RangeLimited;
}
+void ColorUtils::convertIsoColorAspectsToPlatformAspects(
+ int32_t primaries, int32_t intransfer, int32_t coeffs, bool fullRange,
+ int32_t *range, int32_t *standard, int32_t *outtransfer) {
+ ColorAspects aspects;
+ convertIsoColorAspectsToCodecAspects(primaries, intransfer, coeffs, fullRange, aspects);
+ convertCodecColorAspectsToPlatformAspects(aspects, range, standard, outtransfer);
+}
+
// static
ColorAspects ColorUtils::unpackToColorAspects(uint32_t packed) {
ColorAspects aspects;
@@ -684,6 +693,13 @@
transfer, asString((ColorTransfer)transfer));
}
+
+// static
+void ColorUtils::setHDRStaticInfoIntoAMediaFormat(
+ const HDRStaticInfo &info, AMediaFormat *format) {
+ setHDRStaticInfoIntoFormat(info, format->mFormat);
+}
+
// static
void ColorUtils::setHDRStaticInfoIntoFormat(
const HDRStaticInfo &info, sp<AMessage> &format) {
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ColorUtils.h b/media/libstagefright/foundation/include/media/stagefright/foundation/ColorUtils.h
index d6c768d..cd0af2b 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/ColorUtils.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/ColorUtils.h
@@ -27,6 +27,8 @@
#include <media/hardware/VideoAPI.h>
#include <system/graphics.h>
+struct AMediaFormat;
+
namespace android {
struct ColorUtils {
@@ -135,6 +137,9 @@
static void convertIsoColorAspectsToCodecAspects(
int32_t primaries, int32_t transfer, int32_t coeffs, bool fullRange,
ColorAspects &aspects);
+ static void convertIsoColorAspectsToPlatformAspects(
+ int32_t primaries, int32_t isotransfer, int32_t coeffs, bool fullRange,
+ int32_t *range, int32_t *standard, int32_t *transfer);
// unpack a uint32_t to a full ColorAspects struct
static ColorAspects unpackToColorAspects(uint32_t packed);
@@ -180,6 +185,8 @@
// writes |info| into format.
static void setHDRStaticInfoIntoFormat(const HDRStaticInfo &info, sp<AMessage> &format);
+ // writes |info| into format.
+ static void setHDRStaticInfoIntoAMediaFormat(const HDRStaticInfo &info, AMediaFormat *format);
};
inline static const char *asString(android::ColorUtils::ColorStandard i, const char *def = "??") {
diff --git a/media/libstagefright/include/HTTPBase.h b/media/libstagefright/include/HTTPBase.h
index a924197..8b20187 100644
--- a/media/libstagefright/include/HTTPBase.h
+++ b/media/libstagefright/include/HTTPBase.h
@@ -51,12 +51,6 @@
virtual void setBandwidthHistorySize(size_t numHistoryItems);
- static void RegisterSocketUserTag(int sockfd, uid_t uid, uint32_t kTag);
- static void UnRegisterSocketUserTag(int sockfd);
-
- static void RegisterSocketUserMark(int sockfd, uid_t uid);
- static void UnRegisterSocketUserMark(int sockfd);
-
virtual String8 toString() {
return mName;
}
diff --git a/media/libstagefright/include/media/stagefright/ClearDataSourceFactory.h b/media/libstagefright/include/media/stagefright/ClearDataSourceFactory.h
deleted file mode 100644
index 12bcdd3..0000000
--- a/media/libstagefright/include/media/stagefright/ClearDataSourceFactory.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef DATA_SOURCE_FACTORY2_H_
-
-#define DATA_SOURCE_FACTORY2_H_
-
-#include <sys/types.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-struct MediaHTTPService;
-class String8;
-struct HTTPBase;
-
-class ClearDataSourceFactory {
-public:
- static sp<DataSource> CreateFromURI(
- const sp<MediaHTTPService> &httpService,
- const char *uri,
- const KeyedVector<String8, String8> *headers = NULL,
- String8 *contentType = NULL,
- HTTPBase *httpSource = NULL);
-
- static sp<DataSource> CreateMediaHTTP(const sp<MediaHTTPService> &httpService);
- static sp<DataSource> CreateFromFd(int fd, int64_t offset, int64_t length);
-};
-
-} // namespace android
-
-#endif // DATA_SOURCE_FACTORY2_H_
diff --git a/media/libstagefright/include/media/stagefright/MetaDataUtils.h b/media/libstagefright/include/media/stagefright/MetaDataUtils.h
index e87c7f9..dcaf27f 100644
--- a/media/libstagefright/include/media/stagefright/MetaDataUtils.h
+++ b/media/libstagefright/include/media/stagefright/MetaDataUtils.h
@@ -26,6 +26,7 @@
struct ABuffer;
bool MakeAVCCodecSpecificData(MetaDataBase &meta, const uint8_t *data, size_t size);
+bool MakeAVCCodecSpecificData(AMediaFormat *meta, const uint8_t *data, size_t size);
bool MakeAACCodecSpecificData(MetaDataBase &meta, const uint8_t *data, size_t size);
bool MakeAACCodecSpecificData(MetaDataBase &meta, unsigned profile, unsigned sampling_freq_index,
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index fb498d4..3debe34 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -552,8 +552,10 @@
hasStreamCA = true;
streamCA.mSystemID = br->getBits(16);
streamCA.mPID = br->getBits(16) & 0x1fff;
- ES_info_length -= 4;
- streamCA.mPrivateData.assign(br->data(), br->data() + descriptor_length - 4);
+ ES_info_length -= descriptor_length;
+ descriptor_length -= 4;
+ streamCA.mPrivateData.assign(br->data(), br->data() + descriptor_length);
+ br->skipBits(descriptor_length * 8);
} else if (info.mType == STREAMTYPE_PES_PRIVATE_DATA &&
descriptor_tag == DESCRIPTOR_DVB_EXTENSION && descriptor_length >= 1) {
unsigned descTagExt = br->getBits(8);
diff --git a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
index 672a37c..f9f7ec2 100644
--- a/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
+++ b/media/libstagefright/omx/SoftVideoDecoderOMXComponent.cpp
@@ -502,7 +502,8 @@
// These values were chosen to prevent integer overflows further down the line, and do
// not indicate support for 32kx32k video.
if (newWidth > 32768 || newHeight > 32768
- || video_def->nStride > 32768 || video_def->nSliceHeight > 32768) {
+ || video_def->nStride > 32768 || video_def->nStride < -32768
+ || video_def->nSliceHeight > 32768) {
ALOGE("b/22885421");
return OMX_ErrorBadParameter;
}
diff --git a/media/libstagefright/rtsp/ARTSPConnection.cpp b/media/libstagefright/rtsp/ARTSPConnection.cpp
index 5620cf8..33c1c18 100644
--- a/media/libstagefright/rtsp/ARTSPConnection.cpp
+++ b/media/libstagefright/rtsp/ARTSPConnection.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include "ARTSPConnection.h"
+#include "NetworkUtils.h"
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -59,8 +60,8 @@
if (mSocket >= 0) {
ALOGE("Connection is still open, closing the socket.");
if (mUIDValid) {
- HTTPBase::UnRegisterSocketUserTag(mSocket);
- HTTPBase::UnRegisterSocketUserMark(mSocket);
+ NetworkUtils::UnRegisterSocketUserTag(mSocket);
+ NetworkUtils::UnRegisterSocketUserMark(mSocket);
}
close(mSocket);
mSocket = -1;
@@ -214,8 +215,8 @@
if (mState != DISCONNECTED) {
if (mUIDValid) {
- HTTPBase::UnRegisterSocketUserTag(mSocket);
- HTTPBase::UnRegisterSocketUserMark(mSocket);
+ NetworkUtils::UnRegisterSocketUserTag(mSocket);
+ NetworkUtils::UnRegisterSocketUserMark(mSocket);
}
close(mSocket);
mSocket = -1;
@@ -266,9 +267,9 @@
mSocket = socket(AF_INET, SOCK_STREAM, 0);
if (mUIDValid) {
- HTTPBase::RegisterSocketUserTag(mSocket, mUID,
+ NetworkUtils::RegisterSocketUserTag(mSocket, mUID,
(uint32_t)*(uint32_t*) "RTSP");
- HTTPBase::RegisterSocketUserMark(mSocket, mUID);
+ NetworkUtils::RegisterSocketUserMark(mSocket, mUID);
}
MakeSocketBlocking(mSocket, false);
@@ -297,8 +298,8 @@
mState = DISCONNECTED;
if (mUIDValid) {
- HTTPBase::UnRegisterSocketUserTag(mSocket);
- HTTPBase::UnRegisterSocketUserMark(mSocket);
+ NetworkUtils::UnRegisterSocketUserTag(mSocket);
+ NetworkUtils::UnRegisterSocketUserMark(mSocket);
}
close(mSocket);
mSocket = -1;
@@ -315,8 +316,8 @@
void ARTSPConnection::performDisconnect() {
if (mUIDValid) {
- HTTPBase::UnRegisterSocketUserTag(mSocket);
- HTTPBase::UnRegisterSocketUserMark(mSocket);
+ NetworkUtils::UnRegisterSocketUserTag(mSocket);
+ NetworkUtils::UnRegisterSocketUserMark(mSocket);
}
close(mSocket);
mSocket = -1;
@@ -389,8 +390,8 @@
mState = DISCONNECTED;
if (mUIDValid) {
- HTTPBase::UnRegisterSocketUserTag(mSocket);
- HTTPBase::UnRegisterSocketUserMark(mSocket);
+ NetworkUtils::UnRegisterSocketUserTag(mSocket);
+ NetworkUtils::UnRegisterSocketUserMark(mSocket);
}
close(mSocket);
mSocket = -1;
diff --git a/media/libstagefright/rtsp/Android.bp b/media/libstagefright/rtsp/Android.bp
index debd07e..d1767d3 100644
--- a/media/libstagefright/rtsp/Android.bp
+++ b/media/libstagefright/rtsp/Android.bp
@@ -1,5 +1,5 @@
-cc_library_static {
- name: "libstagefright_rtsp",
+cc_defaults {
+ name: "libstagefright_rtsp_defaults",
srcs: [
"AAMRAssembler.cpp",
@@ -52,6 +52,21 @@
},
}
+cc_library_static {
+ name: "libstagefright_rtsp",
+
+ srcs: ["NetworkUtils.cpp"],
+ header_libs: ["libnetd_client_headers"],
+ defaults: ["libstagefright_rtsp_defaults"],
+}
+
+cc_library_static {
+ name: "libstagefright_rtsp_player2",
+
+ srcs: ["NetworkUtilsForAppProc.cpp"],
+ defaults: ["libstagefright_rtsp_defaults"],
+}
+
//###############################################################################
cc_test {
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index d183516..5d993db 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -31,6 +31,7 @@
#include "ARTPConnection.h"
#include "ARTSPConnection.h"
#include "ASessionDescription.h"
+#include "NetworkUtils.h"
#include <ctype.h>
#include <cutils/properties.h>
@@ -757,10 +758,10 @@
if (!track->mUsingInterleavedTCP) {
// Clear the tag
if (mUIDValid) {
- HTTPBase::UnRegisterSocketUserTag(track->mRTPSocket);
- HTTPBase::UnRegisterSocketUserMark(track->mRTPSocket);
- HTTPBase::UnRegisterSocketUserTag(track->mRTCPSocket);
- HTTPBase::UnRegisterSocketUserMark(track->mRTCPSocket);
+ NetworkUtils::UnRegisterSocketUserTag(track->mRTPSocket);
+ NetworkUtils::UnRegisterSocketUserMark(track->mRTPSocket);
+ NetworkUtils::UnRegisterSocketUserTag(track->mRTCPSocket);
+ NetworkUtils::UnRegisterSocketUserMark(track->mRTCPSocket);
}
close(track->mRTPSocket);
@@ -886,10 +887,10 @@
// Clear the tag
if (mUIDValid) {
- HTTPBase::UnRegisterSocketUserTag(info->mRTPSocket);
- HTTPBase::UnRegisterSocketUserMark(info->mRTPSocket);
- HTTPBase::UnRegisterSocketUserTag(info->mRTCPSocket);
- HTTPBase::UnRegisterSocketUserMark(info->mRTCPSocket);
+ NetworkUtils::UnRegisterSocketUserTag(info->mRTPSocket);
+ NetworkUtils::UnRegisterSocketUserMark(info->mRTPSocket);
+ NetworkUtils::UnRegisterSocketUserTag(info->mRTCPSocket);
+ NetworkUtils::UnRegisterSocketUserMark(info->mRTCPSocket);
}
close(info->mRTPSocket);
@@ -1665,12 +1666,12 @@
&info->mRTPSocket, &info->mRTCPSocket, &rtpPort);
if (mUIDValid) {
- HTTPBase::RegisterSocketUserTag(info->mRTPSocket, mUID,
- (uint32_t)*(uint32_t*) "RTP_");
- HTTPBase::RegisterSocketUserTag(info->mRTCPSocket, mUID,
- (uint32_t)*(uint32_t*) "RTP_");
- HTTPBase::RegisterSocketUserMark(info->mRTPSocket, mUID);
- HTTPBase::RegisterSocketUserMark(info->mRTCPSocket, mUID);
+ NetworkUtils::RegisterSocketUserTag(info->mRTPSocket, mUID,
+ (uint32_t)*(uint32_t*) "RTP_");
+ NetworkUtils::RegisterSocketUserTag(info->mRTCPSocket, mUID,
+ (uint32_t)*(uint32_t*) "RTP_");
+ NetworkUtils::RegisterSocketUserMark(info->mRTPSocket, mUID);
+ NetworkUtils::RegisterSocketUserMark(info->mRTCPSocket, mUID);
}
request.append("Transport: RTP/AVP/UDP;unicast;client_port=");
diff --git a/media/libstagefright/rtsp/NetworkUtils.cpp b/media/libstagefright/rtsp/NetworkUtils.cpp
new file mode 100644
index 0000000..cc36b78
--- /dev/null
+++ b/media/libstagefright/rtsp/NetworkUtils.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NetworkUtils"
+#include <utils/Log.h>
+
+#include "NetworkUtils.h"
+#include <cutils/qtaguid.h>
+#include <NetdClient.h>
+
+namespace android {
+
+// static
+void NetworkUtils::RegisterSocketUserTag(int sockfd, uid_t uid, uint32_t kTag) {
+ int res = qtaguid_tagSocket(sockfd, kTag, uid);
+ if (res != 0) {
+ ALOGE("Failed tagging socket %d for uid %d (My UID=%d)", sockfd, uid, geteuid());
+ }
+}
+
+// static
+void NetworkUtils::UnRegisterSocketUserTag(int sockfd) {
+ int res = qtaguid_untagSocket(sockfd);
+ if (res != 0) {
+ ALOGE("Failed untagging socket %d (My UID=%d)", sockfd, geteuid());
+ }
+}
+
+// static
+void NetworkUtils::RegisterSocketUserMark(int sockfd, uid_t uid) {
+ setNetworkForUser(uid, sockfd);
+}
+
+// static
+void NetworkUtils::UnRegisterSocketUserMark(int sockfd) {
+ RegisterSocketUserMark(sockfd, geteuid());
+}
+
+} // namespace android
diff --git a/media/libstagefright/rtsp/NetworkUtils.h b/media/libstagefright/rtsp/NetworkUtils.h
new file mode 100644
index 0000000..e25ee46
--- /dev/null
+++ b/media/libstagefright/rtsp/NetworkUtils.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NETWORK_UTILS_H_
+#define NETWORK_UTILS_H_
+
+namespace android {
+
+struct NetworkUtils {
+ static void RegisterSocketUserTag(int sockfd, uid_t uid, uint32_t kTag);
+ static void UnRegisterSocketUserTag(int sockfd);
+
+ static void RegisterSocketUserMark(int sockfd, uid_t uid);
+ static void UnRegisterSocketUserMark(int sockfd);
+};
+
+} // namespace android
+
+#endif // NETWORK_UTILS_H_
diff --git a/media/libstagefright/rtsp/NetworkUtilsForAppProc.cpp b/media/libstagefright/rtsp/NetworkUtilsForAppProc.cpp
new file mode 100644
index 0000000..662159c
--- /dev/null
+++ b/media/libstagefright/rtsp/NetworkUtilsForAppProc.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "NetworkUtils"
+#include <utils/Log.h>
+
+#include "NetworkUtils.h"
+
+// NetworkUtils implementation for application process.
+namespace android {
+
+// static
+void NetworkUtils::RegisterSocketUserTag(int, uid_t, uint32_t) {
+ // No op. Framework already handles the data usage billing for applications.
+}
+
+// static
+void NetworkUtils::UnRegisterSocketUserTag(int) {
+ // No op.
+}
+
+// static
+void NetworkUtils::RegisterSocketUserMark(int, uid_t) {
+ // No op. Framework already handles the data usage billing for applications.
+}
+
+// static
+void NetworkUtils::UnRegisterSocketUserMark(int) {
+ // No op.
+}
+
+} // namespace android
diff --git a/media/ndk/NdkImageReaderPriv.h b/media/ndk/NdkImageReaderPriv.h
index a9b54a8..d9ddfd9 100644
--- a/media/ndk/NdkImageReaderPriv.h
+++ b/media/ndk/NdkImageReaderPriv.h
@@ -170,9 +170,7 @@
};
// Retrieves HGraphicBufferProducer corresponding to the native_handle_t
-// provided. This method also deletes the HalToken corresponding to the
-// native_handle_t. Thus, if it is used twice in succession, the second call
-// returns nullptr;
+// provided (this native handle MUST have been obtained by AImageReader_getWindowNativeHandle()).
sp<HGraphicBufferProducer> AImageReader_getHGBPFromHandle(const native_handle_t *handle);
#endif // _NDK_IMAGE_READER_PRIV_H
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index 22fbb42..6537ad1 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -276,6 +276,7 @@
EXPORT const char* AMEDIAFORMAT_KEY_AUTHOR = "author";
EXPORT const char* AMEDIAFORMAT_KEY_BITRATE_MODE = "bitrate-mode";
EXPORT const char* AMEDIAFORMAT_KEY_BIT_RATE = "bitrate";
+EXPORT const char* AMEDIAFORMAT_KEY_BITS_PER_SAMPLE = "bits-per-sample";
EXPORT const char* AMEDIAFORMAT_KEY_CAPTURE_RATE = "capture-rate";
EXPORT const char* AMEDIAFORMAT_KEY_CDTRACKNUMBER = "cdtracknum";
EXPORT const char* AMEDIAFORMAT_KEY_CHANNEL_COUNT = "channel-count";
@@ -287,10 +288,13 @@
EXPORT const char* AMEDIAFORMAT_KEY_COMPILATION = "compilation";
EXPORT const char* AMEDIAFORMAT_KEY_COMPLEXITY = "complexity";
EXPORT const char* AMEDIAFORMAT_KEY_COMPOSER = "composer";
+EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_KEY = "crypto-key";
EXPORT const char* AMEDIAFORMAT_KEY_CSD = "csd";
EXPORT const char* AMEDIAFORMAT_KEY_CSD_0 = "csd-0";
EXPORT const char* AMEDIAFORMAT_KEY_CSD_1 = "csd-1";
EXPORT const char* AMEDIAFORMAT_KEY_CSD_2 = "csd-2";
+EXPORT const char* AMEDIAFORMAT_KEY_CSD_AVC = "csd-avc";
+EXPORT const char* AMEDIAFORMAT_KEY_CSD_HEVC = "csd-hevc";
EXPORT const char* AMEDIAFORMAT_KEY_DATE = "date";
EXPORT const char* AMEDIAFORMAT_KEY_DISCNUMBER = "discnum";
EXPORT const char* AMEDIAFORMAT_KEY_DISPLAY_CROP = "crop";
@@ -330,11 +334,14 @@
EXPORT const char* AMEDIAFORMAT_KEY_REPEAT_PREVIOUS_FRAME_AFTER = "repeat-previous-frame-after";
EXPORT const char* AMEDIAFORMAT_KEY_ROTATION = "rotation-degrees";
EXPORT const char* AMEDIAFORMAT_KEY_SAMPLE_RATE = "sample-rate";
+EXPORT const char* AMEDIAFORMAT_KEY_SAR_HEIGHT = "sar-height";
+EXPORT const char* AMEDIAFORMAT_KEY_SAR_WIDTH = "sar-width";
EXPORT const char* AMEDIAFORMAT_KEY_SEI = "sei";
EXPORT const char* AMEDIAFORMAT_KEY_SLICE_HEIGHT = "slice-height";
EXPORT const char* AMEDIAFORMAT_KEY_STRIDE = "stride";
EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID = "temporal-layer-id";
EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYERING = "ts-schema";
+EXPORT const char* AMEDIAFORMAT_KEY_THUMBNAIL_TIME = "thumbnail-time";
EXPORT const char* AMEDIAFORMAT_KEY_TILE_HEIGHT = "tile-height";
EXPORT const char* AMEDIAFORMAT_KEY_TILE_WIDTH = "tile-width";
EXPORT const char* AMEDIAFORMAT_KEY_TIME_US = "timeUs";
@@ -344,7 +351,6 @@
EXPORT const char* AMEDIAFORMAT_KEY_WIDTH = "width";
EXPORT const char* AMEDIAFORMAT_KEY_YEAR = "year";
-
} // extern "C"
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 3fc28f3..3a3268c 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -181,16 +181,27 @@
extern const char* AMEDIAFORMAT_KEY_ALBUMARTIST __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_ARTIST __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_AUTHOR __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_BITS_PER_SAMPLE __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_CDTRACKNUMBER __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_COLOR_RANGE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_COLOR_STANDARD __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_COLOR_TRANSFER __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_COMPILATION __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_COMPOSER __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_CRYPTO_KEY __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_CSD_AVC __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_CSD_HEVC __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_DATE __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_DISCNUMBER __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_ENCODER_DELAY __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_ENCODER_PADDING __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_GENRE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_HDR_STATIC_INFO __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_LOOP __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_LYRICIST __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_SAR_HEIGHT __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_SAR_WIDTH __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_THUMBNAIL_TIME __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_TITLE __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_YEAR __INTRODUCED_IN(29);
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 1ce48a9..6ab6369 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -309,8 +309,8 @@
// input and output effect buffers without an intermediary effect process.
// TODO: consider implementing channel conversion.
const size_t safeInputOutputSampleCount =
- inChannelCount != outChannelCount ? 0
- : outChannelCount * std::min(
+ mInChannelCountRequested != mOutChannelCountRequested ? 0
+ : mOutChannelCountRequested * std::min(
mConfig.inputCfg.buffer.frameCount,
mConfig.outputCfg.buffer.frameCount);
const auto accumulateInputToOutput = [this, safeInputOutputSampleCount]() {
@@ -480,7 +480,12 @@
// accumulate input onto output
sp<EffectChain> chain = mChain.promote();
if (chain.get() != nullptr && chain->activeTrackCnt() != 0) {
- accumulateInputToOutput();
+ // similar handling with data_bypass above.
+ if (mConfig.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+ accumulateInputToOutput();
+ } else { // EFFECT_BUFFER_ACCESS_WRITE
+ copyInputToOutput();
+ }
}
}
}
diff --git a/services/audiopolicy/config/msd_audio_policy_configuration.xml b/services/audiopolicy/config/msd_audio_policy_configuration.xml
index a84117e..a811f5e 100644
--- a/services/audiopolicy/config/msd_audio_policy_configuration.xml
+++ b/services/audiopolicy/config/msd_audio_policy_configuration.xml
@@ -36,7 +36,8 @@
samplingRates="32000,44100,48000"
channelMasks="AUDIO_CHANNEL_OUT_MONO,AUDIO_CHANNEL_OUT_STEREO,AUDIO_CHANNEL_OUT_5POINT1,AUDIO_CHANNEL_OUT_7POINT1"/>
</mixPort>
- <mixPort name="ms12 output" role="sink">
+ <!-- The HW AV Sync flag is not required, but is recommended -->
+ <mixPort name="ms12 output" role="sink" flags="AUDIO_INPUT_FLAG_HW_AV_SYNC">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
<profile name="" format="AUDIO_FORMAT_AC3"
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index ab4971d..c9c216b 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -1446,6 +1446,7 @@
if ( (res = checkPid(__FUNCTION__) ) != OK) return res;
int takePictureCounter;
+ bool shouldSyncWithDevice = true;
{
SharedParameters::Lock l(mParameters);
switch (l.mParameters.state) {
@@ -1531,12 +1532,23 @@
__FUNCTION__, mCameraId);
mZslProcessor->clearZslQueue();
}
+
+ // We should always sync with the device in case flash is turned on,
+ // the camera device suggests that flash is needed (AE state FLASH_REQUIRED)
+ // or we are in some other AE state different from CONVERGED that may need
+ // precapture trigger.
+ if (l.mParameters.flashMode != Parameters::FLASH_MODE_ON &&
+ (l.mParameters.aeState == ANDROID_CONTROL_AE_STATE_CONVERGED)) {
+ shouldSyncWithDevice = false;
+ }
}
ATRACE_ASYNC_BEGIN(kTakepictureLabel, takePictureCounter);
- // Need HAL to have correct settings before (possibly) triggering precapture
- syncWithDevice();
+ // Make sure HAL has correct settings in case precapture trigger is needed.
+ if (shouldSyncWithDevice) {
+ syncWithDevice();
+ }
res = mCaptureSequencer->startCapture();
if (res != OK) {
@@ -1905,6 +1917,11 @@
void Camera2Client::notifyAutoExposure(uint8_t newState, int triggerId) {
ALOGV("%s: Autoexposure state now %d, last trigger %d",
__FUNCTION__, newState, triggerId);
+ {
+ SharedParameters::Lock l(mParameters);
+ // Update state
+ l.mParameters.aeState = newState;
+ }
mCaptureSequencer->notifyAutoExposure(newState, triggerId);
}
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp
index 28d186a..7b1454d 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.cpp
+++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp
@@ -757,6 +757,7 @@
focusState = ANDROID_CONTROL_AF_STATE_INACTIVE;
shadowFocusMode = FOCUS_MODE_INVALID;
+ aeState = ANDROID_CONTROL_AE_STATE_INACTIVE;
camera_metadata_ro_entry_t max3aRegions = staticInfo(ANDROID_CONTROL_MAX_REGIONS,
Parameters::NUM_REGION, Parameters::NUM_REGION);
if (max3aRegions.count != Parameters::NUM_REGION) return NO_INIT;
diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h
index 42e7a47..e008648 100644
--- a/services/camera/libcameraservice/api1/client2/Parameters.h
+++ b/services/camera/libcameraservice/api1/client2/Parameters.h
@@ -122,6 +122,7 @@
int32_t high;
};
+ uint8_t aeState; //latest AE state from Hal
int32_t exposureCompensation;
bool autoExposureLock;
bool autoExposureLockAvailable;
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index 8bc208d..6d08842 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -83,8 +83,8 @@
// from input, and attached to the outputs. In this case, the input queue's
// dequeueBuffer can still allocate 1 extra buffer before being blocked by
// the output's attachBuffer().
- mBufferItemConsumer = new BufferItemConsumer(mConsumer, consumerUsage,
- mMaxConsumerBuffers+1);
+ mMaxConsumerBuffers++;
+ mBufferItemConsumer = new BufferItemConsumer(mConsumer, consumerUsage, mMaxConsumerBuffers);
if (mBufferItemConsumer == nullptr) {
return NO_MEMORY;
}
@@ -108,6 +108,7 @@
mHeight = height;
mFormat = format;
mProducerUsage = producerUsage;
+ mAcquiredInputBuffers = 0;
SP_LOGV("%s: connected", __FUNCTION__);
return res;
@@ -147,6 +148,7 @@
mMaxHalBuffers = 0;
mMaxConsumerBuffers = 0;
+ mAcquiredInputBuffers = 0;
SP_LOGV("%s: Disconnected", __FUNCTION__);
}
@@ -165,7 +167,9 @@
return res;
}
- res = mConsumer->setMaxAcquiredBufferCount(mMaxConsumerBuffers+1);
+ if (mMaxConsumerBuffers > mAcquiredInputBuffers) {
+ res = mConsumer->setMaxAcquiredBufferCount(mMaxConsumerBuffers);
+ }
return res;
}
@@ -266,10 +270,12 @@
return res;
}
- res = mConsumer->setMaxAcquiredBufferCount(mMaxConsumerBuffers+1);
- if (res != OK) {
- SP_LOGE("%s: setMaxAcquiredBufferCount failed %d", __FUNCTION__, res);
- return res;
+ if (mAcquiredInputBuffers < mMaxConsumerBuffers) {
+ res = mConsumer->setMaxAcquiredBufferCount(mMaxConsumerBuffers);
+ if (res != OK) {
+ SP_LOGE("%s: setMaxAcquiredBufferCount failed %d", __FUNCTION__, res);
+ return res;
+ }
}
return res;
@@ -497,6 +503,7 @@
return;
}
+ mAcquiredInputBuffers++;
SP_LOGV("acquired buffer %" PRId64 " from input at slot %d",
bufferItem.mGraphicBuffer->getId(), bufferItem.mSlot);
@@ -599,6 +606,12 @@
} else {
SP_LOGE("%s: releaseBuffer returns %d", __FUNCTION__, res);
}
+ } else {
+ if (mAcquiredInputBuffers == 0) {
+ ALOGW("%s: Acquired input buffer count already at zero!", __FUNCTION__);
+ } else {
+ mAcquiredInputBuffers--;
+ }
}
}
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
index fea1bdb..1eaf2bd 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
@@ -269,6 +269,9 @@
// Latest onFrameAvailable return value
std::atomic<status_t> mOnFrameAvailableRes{0};
+ // Currently acquired input buffers
+ size_t mAcquiredInputBuffers;
+
String8 mConsumerName;
};