Merge "In favor of SW patch in AudioPolicyManager::connectAudioSource"
diff --git a/apex/Android.bp b/apex/Android.bp
index 575603f..449d29c 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -24,11 +24,7 @@
"libmkvextractor",
"libmp3extractor",
"libmp4extractor",
- "libmpeg2extractor",
- "liboggextractor",
"libwavextractor",
- // MediaPlayer2
- "libmedia2_jni",
],
key: "com.android.media.key",
}
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 00da54e..657d41f 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -633,7 +633,7 @@
}
std::set<std::pair<ANativeWindow*, OutputConfiguration>> outputSet;
- for (auto outConfig : outputs->mOutputs) {
+ for (const auto& outConfig : outputs->mOutputs) {
ANativeWindow* anw = outConfig.mWindow;
sp<IGraphicBufferProducer> iGBP(nullptr);
ret = getIGBPfromAnw(anw, iGBP);
@@ -706,7 +706,7 @@
}
// add new streams
- for (auto outputPair : addSet) {
+ for (const auto& outputPair : addSet) {
int streamId;
remoteRet = mRemote->createStream(outputPair.second, &streamId);
if (!remoteRet.isOk()) {
@@ -839,7 +839,7 @@
const auto& gbps = outputPairIt->second.second.getGraphicBufferProducers();
for (const auto& outGbp : gbps) {
- for (auto surface : request->mSurfaceList) {
+ for (const auto& surface : request->mSurfaceList) {
if (surface->getIGraphicBufferProducer() == outGbp) {
ANativeWindow* anw = static_cast<ANativeWindow*>(surface.get());
ALOGV("Camera %s Lost output buffer for ANW %p frame %" PRId64,
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index c7619af..7a10302 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -191,7 +191,6 @@
LOCAL_MODULE:= mediafilter
LOCAL_SANITIZE := cfi
-LOCAL_SANITIZE_DIAG := cfi
include $(BUILD_EXECUTABLE)
diff --git a/include/media/MediaMetrics.h b/include/media/MediaMetrics.h
new file mode 120000
index 0000000..5f757e4
--- /dev/null
+++ b/include/media/MediaMetrics.h
@@ -0,0 +1 @@
+../../media/libmediametrics/include/MediaMetrics.h
\ No newline at end of file
diff --git a/media/bufferpool/2.0/AccessorImpl.cpp b/media/bufferpool/2.0/AccessorImpl.cpp
index 0165314..2c734ac 100644
--- a/media/bufferpool/2.0/AccessorImpl.cpp
+++ b/media/bufferpool/2.0/AccessorImpl.cpp
@@ -282,7 +282,7 @@
Accessor::Impl::Impl::BufferPool::~BufferPool() {
std::lock_guard<std::mutex> lock(mMutex);
- ALOGD("Destruction - bufferpool %p "
+ ALOGD("Destruction - bufferpool2 %p "
"cached: %zu/%zuM, %zu/%d%% in use; "
"allocs: %zu, %d%% recycled; "
"transfers: %zu, %d%% unfetced",
@@ -353,12 +353,12 @@
msgId = ++mInvalidationId;
}
}
- ALOGV("bufferpool invalidation requested and queued");
+ ALOGV("bufferpool2 invalidation requested and queued");
if (left == 0) {
channel.postInvalidation(msgId, from, to);
} else {
// TODO: sending hint message?
- ALOGV("bufferpool invalidation requested and pending");
+ ALOGV("bufferpoo2 invalidation requested and pending");
Pending pending(needsAck, from, to, left, impl);
mPendings.push_back(pending);
}
@@ -380,7 +380,7 @@
// lost.
it->second = mInvalidationId;
} else {
- ALOGV("bufferpool observer died %lld", (long long)it->first);
+ ALOGV("bufferpool2 observer died %lld", (long long)it->first);
deads.insert(it->first);
}
}
@@ -682,7 +682,7 @@
mLastCleanUpUs = mTimestampUs;
if (mTimestampUs > mLastLogUs + kLogDurationUs) {
mLastLogUs = mTimestampUs;
- ALOGD("bufferpool %p : %zu(%zu size) total buffers - "
+ ALOGD("bufferpool2 %p : %zu(%zu size) total buffers - "
"%zu(%zu size) used buffers - %zu/%zu (recycle/alloc) - "
"%zu/%zu (fetch/transfer)",
this, mStats.mBuffersCached, mStats.mSizeCached,
@@ -703,7 +703,7 @@
freeIt = mFreeBuffers.erase(freeIt);
} else {
++freeIt;
- ALOGW("bufferpool inconsistent!");
+ ALOGW("bufferpool2 inconsistent!");
}
}
}
@@ -722,7 +722,7 @@
freeIt = mFreeBuffers.erase(freeIt);
continue;
} else {
- ALOGW("bufferpool inconsistent!");
+ ALOGW("bufferpool2 inconsistent!");
}
}
++freeIt;
diff --git a/media/bufferpool/2.0/BufferPoolClient.cpp b/media/bufferpool/2.0/BufferPoolClient.cpp
index 5564a13..f907de5 100644
--- a/media/bufferpool/2.0/BufferPoolClient.cpp
+++ b/media/bufferpool/2.0/BufferPoolClient.cpp
@@ -811,7 +811,7 @@
}
void BufferPoolClient::receiveInvalidation(uint32_t msgId) {
- ALOGV("bufferpool client recv inv %u", msgId);
+ ALOGV("bufferpool2 client recv inv %u", msgId);
if (isValid()) {
mImpl->receiveInvalidation(msgId);
}
diff --git a/media/codec2/hidl/1.0/utils/Android.bp b/media/codec2/hidl/1.0/utils/Android.bp
index 455de50..c5ad6a0 100644
--- a/media/codec2/hidl/1.0/utils/Android.bp
+++ b/media/codec2/hidl/1.0/utils/Android.bp
@@ -24,7 +24,7 @@
"android.hardware.graphics.bufferqueue@1.0",
"android.hardware.graphics.common@1.0",
"android.hardware.media@1.0",
- "android.hardware.media.bufferpool@1.0",
+ "android.hardware.media.bufferpool@2.0",
"android.hardware.media.c2@1.0",
"android.hardware.media.omx@1.0",
"libbase",
@@ -35,7 +35,7 @@
"libhidltransport",
"libhwbinder",
"liblog",
- "libstagefright_bufferpool@1.0",
+ "libstagefright_bufferpool@2.0",
"libstagefright_bufferqueue_helper",
"libui",
"libutils",
@@ -49,7 +49,7 @@
"android.hardware.media.c2@1.0",
"libcodec2",
"libhidlbase",
- "libstagefright_bufferpool@1.0",
+ "libstagefright_bufferpool@2.0",
"libstagefright_bufferqueue_helper",
"libui",
],
diff --git a/media/codec2/hidl/1.0/utils/Component.cpp b/media/codec2/hidl/1.0/utils/Component.cpp
index aa4c6b2..5ae1972 100644
--- a/media/codec2/hidl/1.0/utils/Component.cpp
+++ b/media/codec2/hidl/1.0/utils/Component.cpp
@@ -410,7 +410,7 @@
const std::shared_ptr<C2Component>& component,
const sp<IComponentListener>& listener,
const sp<ComponentStore>& store,
- const sp<::android::hardware::media::bufferpool::V1_0::
+ const sp<::android::hardware::media::bufferpool::V2_0::
IClientManager>& clientPoolManager) :
Configurable(new CachedConfigurable(
std::make_unique<CompIntf>(component->intf()))),
diff --git a/media/codec2/hidl/1.0/utils/ComponentStore.cpp b/media/codec2/hidl/1.0/utils/ComponentStore.cpp
index 1d1bbe0..9c05014 100644
--- a/media/codec2/hidl/1.0/utils/ComponentStore.cpp
+++ b/media/codec2/hidl/1.0/utils/ComponentStore.cpp
@@ -57,7 +57,7 @@
using namespace ::android;
using ::android::GraphicBufferSource;
-using namespace ::android::hardware::media::bufferpool::V1_0::implementation;
+using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
namespace /* unnamed */ {
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h
index 36dec1c..0908226 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/Component.h
@@ -20,7 +20,7 @@
#include <codec2/hidl/1.0/Configurable.h>
#include <codec2/hidl/1.0/types.h>
-#include <android/hardware/media/bufferpool/1.0/IClientManager.h>
+#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
#include <android/hardware/media/c2/1.0/IComponentListener.h>
#include <android/hardware/media/c2/1.0/IComponentStore.h>
#include <android/hardware/media/c2/1.0/IComponent.h>
@@ -71,7 +71,7 @@
const std::shared_ptr<C2Component>&,
const sp<IComponentListener>& listener,
const sp<ComponentStore>& store,
- const sp<::android::hardware::media::bufferpool::V1_0::
+ const sp<::android::hardware::media::bufferpool::V2_0::
IClientManager>& clientPoolManager);
c2_status_t status() const;
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
index 5821e8a..41e1416 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/ComponentStore.h
@@ -20,7 +20,7 @@
#include <codec2/hidl/1.0/Component.h>
#include <codec2/hidl/1.0/Configurable.h>
#include <android/hardware/media/c2/1.0/IComponentStore.h>
-#include <android/hardware/media/bufferpool/1.0/IClientManager.h>
+#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
#include <hidl/Status.h>
#include <C2Component.h>
@@ -40,7 +40,7 @@
namespace V1_0 {
namespace utils {
-using ::android::hardware::media::bufferpool::V1_0::IClientManager;
+using ::android::hardware::media::bufferpool::V2_0::IClientManager;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_handle;
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
index 58f5c96..d8a50b6 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
+++ b/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/types.h
@@ -20,8 +20,8 @@
#include <chrono>
#include <bufferpool/ClientManager.h>
-#include <android/hardware/media/bufferpool/1.0/IClientManager.h>
-#include <android/hardware/media/bufferpool/1.0/types.h>
+#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
+#include <android/hardware/media/bufferpool/2.0/types.h>
#include <android/hardware/media/c2/1.0/IComponentStore.h>
#include <android/hardware/media/c2/1.0/types.h>
#include <gui/IGraphicBufferProducer.h>
@@ -46,7 +46,7 @@
using ::android::hardware::hidl_vec;
using ::android::status_t;
using ::android::sp;
-using ::android::hardware::media::bufferpool::V1_0::implementation::
+using ::android::hardware::media::bufferpool::V2_0::implementation::
ConnectionId;
using ::android::IGraphicBufferProducer;
@@ -131,9 +131,9 @@
// Abstract class to be used in
// objcpy(std::list<std::unique_ptr<C2Work>> -> WorkBundle).
struct BufferPoolSender {
- typedef ::android::hardware::media::bufferpool::V1_0::
+ typedef ::android::hardware::media::bufferpool::V2_0::
ResultStatus ResultStatus;
- typedef ::android::hardware::media::bufferpool::V1_0::
+ typedef ::android::hardware::media::bufferpool::V2_0::
BufferStatusMessage BufferStatusMessage;
typedef ::android::hardware::media::bufferpool::
BufferPoolData BufferPoolData;
@@ -151,7 +151,7 @@
* other means so it can call receive() properly.
* \return ResultStatus value that determines the success of the operation.
* (See the possible values of ResultStatus in
- * hardware/interfaces/media/bufferpool/1.0/types.hal.)
+ * hardware/interfaces/media/bufferpool/2.0/types.hal.)
*/
virtual ResultStatus send(
const std::shared_ptr<BufferPoolData>& bpData,
@@ -168,9 +168,9 @@
// IClientManager::registerSender() to establish the bufferpool connection when
// send() is called.
struct DefaultBufferPoolSender : BufferPoolSender {
- typedef ::android::hardware::media::bufferpool::V1_0::implementation::
+ typedef ::android::hardware::media::bufferpool::V2_0::implementation::
ClientManager ClientManager;
- typedef ::android::hardware::media::bufferpool::V1_0::
+ typedef ::android::hardware::media::bufferpool::V2_0::
IClientManager IClientManager;
// Set the IClientManager instance of the receiving process and the refresh
@@ -278,7 +278,7 @@
* \param BufferPool status
* \return Corresponding c2_status_t
*/
-c2_status_t toC2Status(::android::hardware::media::bufferpool::V1_0::
+c2_status_t toC2Status(::android::hardware::media::bufferpool::V2_0::
ResultStatus rs);
// BufferQueue-Based Block Operations
diff --git a/media/codec2/hidl/1.0/utils/types.cpp b/media/codec2/hidl/1.0/utils/types.cpp
index 5827504..c053bc1 100644
--- a/media/codec2/hidl/1.0/utils/types.cpp
+++ b/media/codec2/hidl/1.0/utils/types.cpp
@@ -49,11 +49,11 @@
using namespace ::android;
using ::android::hardware::Return;
using ::android::hardware::media::bufferpool::BufferPoolData;
-using ::android::hardware::media::bufferpool::V1_0::BufferStatusMessage;
-using ::android::hardware::media::bufferpool::V1_0::ResultStatus;
-using ::android::hardware::media::bufferpool::V1_0::implementation::
+using ::android::hardware::media::bufferpool::V2_0::BufferStatusMessage;
+using ::android::hardware::media::bufferpool::V2_0::ResultStatus;
+using ::android::hardware::media::bufferpool::V2_0::implementation::
ClientManager;
-using ::android::hardware::media::bufferpool::V1_0::implementation::
+using ::android::hardware::media::bufferpool::V2_0::implementation::
TransactionId;
using ::android::TWGraphicBufferProducer;
diff --git a/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp b/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
index 6fd9200..1e87f38 100644
--- a/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioDecTest.cpp
@@ -156,63 +156,31 @@
// callback function to process onWorkDone received by Listener
void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
for (std::unique_ptr<C2Work>& work : workItems) {
- // handle configuration changes in work done
- if (!work->worklets.empty() &&
- (work->worklets.front()->output.configUpdate.size() != 0)) {
- ALOGV("Config Update");
- std::vector<std::unique_ptr<C2Param>> updates =
- std::move(work->worklets.front()->output.configUpdate);
- std::vector<C2Param*> configParam;
- std::vector<std::unique_ptr<C2SettingResult>> failures;
- for (size_t i = 0; i < updates.size(); ++i) {
- C2Param* param = updates[i].get();
- if ((param->index() == C2StreamSampleRateInfo::output::PARAM_TYPE) ||
- (param->index() == C2StreamChannelCountInfo::output::PARAM_TYPE)) {
- configParam.push_back(param);
+ if (!work->worklets.empty()) {
+ // For decoder components current timestamp always exceeds
+ // previous timestamp
+ bool codecConfig = ((work->worklets.front()->output.flags &
+ C2FrameData::FLAG_CODEC_CONFIG) != 0);
+ if (!codecConfig &&
+ !work->worklets.front()->output.buffers.empty()) {
+ EXPECT_GE(work->worklets.front()->output.ordinal.timestamp.peeku(),
+ mTimestampUs);
+ mTimestampUs =
+ work->worklets.front()->output.ordinal.timestamp.peeku();
+ uint32_t rangeLength =
+ work->worklets.front()->output.buffers[0]->data()
+ .linearBlocks().front().map().get().capacity();
+ //List of timestamp values and output size to calculate timestamp
+ if (mTimestampDevTest) {
+ outputMetaData meta = {mTimestampUs, rangeLength};
+ oBufferMetaData.push_back(meta);
}
}
- mComponent->config(configParam, C2_DONT_BLOCK, &failures);
- ASSERT_EQ(failures.size(), 0u);
- }
- mFramesReceived++;
- mEos = (work->worklets.front()->output.flags &
- C2FrameData::FLAG_END_OF_STREAM) != 0;
- auto frameIndexIt =
- std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
- work->input.ordinal.frameIndex.peeku());
- ALOGV("WorkDone: frameID received %d",
- (int)work->worklets.front()->output.ordinal.frameIndex.peeku());
-
- // For decoder components current timestamp always exceeds
- // previous timestamp
- bool codecConfig = ((work->worklets.front()->output.flags &
- C2FrameData::FLAG_CODEC_CONFIG) != 0);
- if (!codecConfig &&
- !work->worklets.front()->output.buffers.empty()) {
- EXPECT_GE(work->worklets.front()->output.ordinal.timestamp.peeku(),
- mTimestampUs);
- mTimestampUs =
- work->worklets.front()->output.ordinal.timestamp.peeku();
- uint32_t rangeLength =
- work->worklets.front()->output.buffers[0]->data()
- .linearBlocks().front().map().get().capacity();
- //List of timestamp values and output size to calculate timestamp
- if (mTimestampDevTest) {
- outputMetaData meta = {mTimestampUs, rangeLength};
- oBufferMetaData.push_back(meta);
- }
- }
-
- work->input.buffers.clear();
- work->worklets.clear();
- {
- typedef std::unique_lock<std::mutex> ULock;
- ULock l(mQueueLock);
- mWorkQueue.push_back(std::move(work));
- if (!mFlushedIndices.empty()) {
- mFlushedIndices.erase(frameIndexIt);
- }
- mQueueCondition.notify_all();
+ bool mCsd = false;
+ workDone(mComponent, work, mFlushedIndices, mQueueLock,
+ mQueueCondition, mWorkQueue, mEos, mCsd,
+ mFramesReceived);
+ (void)mCsd;
}
}
}
@@ -418,11 +386,11 @@
}
}
-void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &component,
- std::mutex &queueLock, std::condition_variable &queueCondition,
- std::list<std::unique_ptr<C2Work>> &workQueue,
- std::list<uint64_t> &flushedIndices,
- std::shared_ptr<C2BlockPool> &linearPool,
+void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
+ std::mutex &queueLock, std::condition_variable& queueCondition,
+ std::list<std::unique_ptr<C2Work>>& workQueue,
+ std::list<uint64_t>& flushedIndices,
+ std::shared_ptr<C2BlockPool>& linearPool,
std::ifstream& eleStream,
android::Vector<FrameInfo>* Info,
int offset, int range, bool signalEOS = true) {
@@ -462,34 +430,37 @@
}
int size = (*Info)[frameID].bytesCount;
char* data = (char*)malloc(size);
+ ASSERT_NE(data, nullptr);
eleStream.read(data, size);
ASSERT_EQ(eleStream.gcount(), size);
- std::shared_ptr<C2LinearBlock> block;
- ASSERT_EQ(C2_OK,
- linearPool->fetchLinearBlock(
- size, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
- &block));
- ASSERT_TRUE(block);
-
- // Write View
- C2WriteView view = block->map().get();
- if (view.error() != C2_OK) {
- fprintf(stderr, "C2LinearBlock::map() failed : %d", view.error());
- break;
- }
- ASSERT_EQ((size_t)size, view.capacity());
- ASSERT_EQ(0u, view.offset());
- ASSERT_EQ((size_t)size, view.size());
-
- memcpy(view.base(), data, size);
-
work->input.buffers.clear();
- work->input.buffers.emplace_back(new LinearBuffer(block));
+ if (size) {
+ std::shared_ptr<C2LinearBlock> block;
+ ASSERT_EQ(C2_OK,
+ linearPool->fetchLinearBlock(
+ size, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
+ &block));
+ ASSERT_TRUE(block);
+
+ // Write View
+ C2WriteView view = block->map().get();
+ if (view.error() != C2_OK) {
+ fprintf(stderr, "C2LinearBlock::map() failed : %d", view.error());
+ break;
+ }
+ ASSERT_EQ((size_t)size, view.capacity());
+ ASSERT_EQ(0u, view.offset());
+ ASSERT_EQ((size_t)size, view.size());
+
+ memcpy(view.base(), data, size);
+
+ work->input.buffers.emplace_back(new LinearBuffer(block));
+ free(data);
+ }
work->worklets.clear();
work->worklets.emplace_back(new C2Worklet);
- free(data);
std::list<std::unique_ptr<C2Work>> items;
items.push_back(std::move(work));
@@ -502,29 +473,6 @@
}
}
-void waitOnInputConsumption(std::mutex& queueLock,
- std::condition_variable& queueCondition,
- std::list<std::unique_ptr<C2Work>>& workQueue,
- size_t bufferCount = MAX_INPUT_BUFFERS) {
- typedef std::unique_lock<std::mutex> ULock;
- uint32_t queueSize;
- uint32_t maxRetry = 0;
- {
- ULock l(queueLock);
- queueSize = workQueue.size();
- }
- while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) {
- ULock l(queueLock);
- if (queueSize != workQueue.size()) {
- queueSize = workQueue.size();
- maxRetry = 0;
- } else {
- queueCondition.wait_for(l, TIME_OUT);
- maxRetry++;
- }
- }
-}
-
TEST_F(Codec2AudioDecHidlTest, validateCompName) {
if (mDisableTest) return;
ALOGV("Checks if the given component is a valid audio component");
@@ -718,7 +666,6 @@
ASSERT_EQ(mComponent->queue(&items), C2_OK);
{
- typedef std::unique_lock<std::mutex> ULock;
ULock l(mQueueLock);
if (mWorkQueue.size() != MAX_INPUT_BUFFERS) {
mQueueCondition.wait_for(l, TIME_OUT);
@@ -729,46 +676,6 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-TEST_F(Codec2AudioDecHidlTest, EmptyBufferTest) {
- description("Tests empty input buffer");
- if (mDisableTest) return;
- typedef std::unique_lock<std::mutex> ULock;
- ASSERT_EQ(mComponent->start(), C2_OK);
- std::unique_ptr<C2Work> work;
- // Prepare C2Work
- {
- ULock l(mQueueLock);
- if (!mWorkQueue.empty()) {
- work.swap(mWorkQueue.front());
- mWorkQueue.pop_front();
- } else {
- ASSERT_TRUE(false) << "mWorkQueue Empty at the start of test";
- }
- }
- ASSERT_NE(work, nullptr);
-
- work->input.flags = (C2FrameData::flags_t)0;
- work->input.ordinal.timestamp = 0;
- work->input.ordinal.frameIndex = 0;
- work->input.buffers.clear();
- work->worklets.clear();
- work->worklets.emplace_back(new C2Worklet);
-
- std::list<std::unique_ptr<C2Work>> items;
- items.push_back(std::move(work));
- ASSERT_EQ(mComponent->queue(&items), C2_OK);
-
- {
- typedef std::unique_lock<std::mutex> ULock;
- ULock l(mQueueLock);
- if (mWorkQueue.size() != MAX_INPUT_BUFFERS) {
- mQueueCondition.wait_for(l, TIME_OUT);
- }
- }
- ASSERT_EQ(mWorkQueue.size(), (size_t)MAX_INPUT_BUFFERS);
- ASSERT_EQ(mComponent->stop(), C2_OK);
-}
-
TEST_F(Codec2AudioDecHidlTest, FlushTest) {
description("Tests Flush calls");
if (mDisableTest) return;
@@ -891,6 +798,72 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
+TEST_F(Codec2AudioDecHidlTest, DecodeTestEmptyBuffersInserted) {
+ description("Decode with multiple empty input frames");
+ if (mDisableTest) return;
+
+ ASSERT_EQ(mComponent->start(), C2_OK);
+
+ char mURL[512], info[512];
+ std::ifstream eleStream, eleInfo;
+
+ strcpy(mURL, gEnv->getRes().c_str());
+ strcpy(info, gEnv->getRes().c_str());
+ GetURLForComponent(mCompName, mURL, info);
+
+ eleInfo.open(info);
+ ASSERT_EQ(eleInfo.is_open(), true) << mURL << " - file not found";
+ android::Vector<FrameInfo> Info;
+ int bytesCount = 0;
+ uint32_t frameId = 0;
+ uint32_t flags = 0;
+ uint32_t timestamp = 0;
+ bool codecConfig = false;
+ // This test introduces empty CSD after every 20th frame
+ // and empty input frames at an interval of 5 frames.
+ while (1) {
+ if (!(frameId % 5)) {
+ if (!(frameId % 20)) flags = 32;
+ else flags = 0;
+ bytesCount = 0;
+ } else {
+ if (!(eleInfo >> bytesCount)) break;
+ eleInfo >> flags;
+ eleInfo >> timestamp;
+ codecConfig = flags ?
+ ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
+ }
+ Info.push_back({bytesCount, flags, timestamp});
+ frameId++;
+ }
+ eleInfo.close();
+
+ ALOGV("mURL : %s", mURL);
+ eleStream.open(mURL, std::ifstream::binary);
+ ASSERT_EQ(eleStream.is_open(), true);
+ ASSERT_NO_FATAL_FAILURE(decodeNFrames(
+ mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices,
+ mLinearPool, eleStream, &Info, 0, (int)Info.size()));
+
+ // blocking call to ensures application to Wait till all the inputs are
+ // consumed
+ if (!mEos) {
+ ALOGV("Waiting for input consumption");
+ ASSERT_NO_FATAL_FAILURE(
+ waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+ }
+
+ eleStream.close();
+ if (mFramesReceived != Info.size()) {
+ ALOGE("Input buffer count and Output buffer count mismatch");
+ ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived,
+ Info.size());
+ ASSERT_TRUE(false);
+ }
+
+ ASSERT_EQ(mComponent->stop(), C2_OK);
+}
+
} // anonymous namespace
int main(int argc, char** argv) {
diff --git a/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioEncTest.cpp b/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioEncTest.cpp
index 4f86aad..5d66ee5 100644
--- a/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/audio/VtsHidlC2V1_0TargetAudioEncTest.cpp
@@ -96,6 +96,7 @@
const StringToName kStringToName[] = {
{"aac", aac},
{"flac", flac},
+ {"opus", opus},
{"amrnb", amrnb},
{"amrwb", amrwb},
};
@@ -135,45 +136,17 @@
// callback function to process onWorkDone received by Listener
void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
for (std::unique_ptr<C2Work>& work : workItems) {
- // handle configuration changes in work done
- if (!work->worklets.empty() &&
- (work->worklets.front()->output.configUpdate.size() != 0)) {
- ALOGV("Config Update");
- std::vector<std::unique_ptr<C2Param>> updates =
- std::move(work->worklets.front()->output.configUpdate);
- std::vector<C2Param*> configParam;
- std::vector<std::unique_ptr<C2SettingResult>> failures;
- for (size_t i = 0; i < updates.size(); ++i) {
- C2Param* param = updates[i].get();
- if (param->index() == C2StreamCsdInfo::output::PARAM_TYPE) {
- mCsd = true;
- }
- }
- }
- mFramesReceived++;
- mEos = (work->worklets.front()->output.flags &
- C2FrameData::FLAG_END_OF_STREAM) != 0;
- auto frameIndexIt =
- std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
- work->input.ordinal.frameIndex.peeku());
- ALOGV("WorkDone: frameID received %d",
- (int)work->worklets.front()->output.ordinal.frameIndex.peeku());
- work->input.buffers.clear();
- work->worklets.clear();
- {
- typedef std::unique_lock<std::mutex> ULock;
- ULock l(mQueueLock);
- mWorkQueue.push_back(std::move(work));
- if (!mFlushedIndices.empty()) {
- mFlushedIndices.erase(frameIndexIt);
- }
- mQueueCondition.notify_all();
+ if (!work->worklets.empty()) {
+ workDone(mComponent, work, mFlushedIndices, mQueueLock,
+ mQueueCondition, mWorkQueue, mEos, mCsd,
+ mFramesReceived);
}
}
}
enum standardComp {
aac,
flac,
+ opus,
amrnb,
amrwb,
unknown_comp,
@@ -275,6 +248,8 @@
"bbb_raw_1ch_16khz_s16le.raw"},
{Codec2AudioEncHidlTest::standardComp::flac,
"bbb_raw_2ch_48khz_s16le.raw"},
+ {Codec2AudioEncHidlTest::standardComp::opus,
+ "bbb_raw_2ch_48khz_s16le.raw"},
};
for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
@@ -285,11 +260,11 @@
}
}
-void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &component,
- std::mutex &queueLock, std::condition_variable &queueCondition,
- std::list<std::unique_ptr<C2Work>> &workQueue,
- std::list<uint64_t> &flushedIndices,
- std::shared_ptr<C2BlockPool> &linearPool,
+void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
+ std::mutex &queueLock, std::condition_variable& queueCondition,
+ std::list<std::unique_ptr<C2Work>>& workQueue,
+ std::list<uint64_t>& flushedIndices,
+ std::shared_ptr<C2BlockPool>& linearPool,
std::ifstream& eleStream, uint32_t nFrames,
int32_t samplesPerFrame, int32_t nChannels,
int32_t nSampleRate, bool flushed = false,
@@ -334,6 +309,7 @@
flushedIndices.emplace_back(frameID);
}
char* data = (char*)malloc(bytesCount);
+ ASSERT_NE(data, nullptr);
eleStream.read(data, bytesCount);
ASSERT_EQ(eleStream.gcount(), bytesCount);
std::shared_ptr<C2LinearBlock> block;
@@ -372,29 +348,6 @@
}
}
-void waitOnInputConsumption(std::mutex& queueLock,
- std::condition_variable& queueCondition,
- std::list<std::unique_ptr<C2Work>>& workQueue,
- size_t bufferCount = MAX_INPUT_BUFFERS) {
- typedef std::unique_lock<std::mutex> ULock;
- uint32_t queueSize;
- uint32_t maxRetry = 0;
- {
- ULock l(queueLock);
- queueSize = workQueue.size();
- }
- while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) {
- ULock l(queueLock);
- if (queueSize != workQueue.size()) {
- queueSize = workQueue.size();
- maxRetry = 0;
- } else {
- queueCondition.wait_for(l, TIME_OUT);
- maxRetry++;
- }
- }
-}
-
TEST_F(Codec2AudioEncHidlTest, validateCompName) {
if (mDisableTest) return;
ALOGV("Checks if the given component is a valid audio component");
@@ -425,6 +378,11 @@
nSampleRate = 48000;
samplesPerFrame = 1152;
break;
+ case opus:
+ nChannels = 2;
+ nSampleRate = 48000;
+ samplesPerFrame = 960;
+ break;
case amrnb:
nChannels = 1;
nSampleRate = 8000;
@@ -458,7 +416,7 @@
ALOGE("framesReceived : %d inputFrames : %u", mFramesReceived, numFrames);
ASSERT_TRUE(false);
}
- if ((mCompName == flac || mCompName == aac)) {
+ if ((mCompName == flac || mCompName == opus || mCompName == aac)) {
if (!mCsd) {
ALOGE("CSD buffer missing");
ASSERT_TRUE(false);
@@ -508,46 +466,6 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-TEST_F(Codec2AudioEncHidlTest, EmptyBufferTest) {
- description("Tests empty input buffer");
- if (mDisableTest) return;
- ASSERT_EQ(mComponent->start(), C2_OK);
-
- typedef std::unique_lock<std::mutex> ULock;
- std::unique_ptr<C2Work> work;
- {
- ULock l(mQueueLock);
- if (!mWorkQueue.empty()) {
- work.swap(mWorkQueue.front());
- mWorkQueue.pop_front();
- } else {
- ALOGE("mWorkQueue Empty is not expected at the start of the test");
- ASSERT_TRUE(false);
- }
- }
- ASSERT_NE(work, nullptr);
- work->input.flags = (C2FrameData::flags_t)0;
- work->input.ordinal.timestamp = 0;
- work->input.ordinal.frameIndex = 0;
- work->input.buffers.clear();
- work->worklets.clear();
- work->worklets.emplace_back(new C2Worklet);
-
- std::list<std::unique_ptr<C2Work>> items;
- items.push_back(std::move(work));
- ASSERT_EQ(mComponent->queue(&items), C2_OK);
- uint32_t queueSize;
- {
- ULock l(mQueueLock);
- queueSize = mWorkQueue.size();
- if (queueSize < MAX_INPUT_BUFFERS) {
- mQueueCondition.wait_for(l, TIME_OUT);
- }
- }
- ASSERT_EQ(mWorkQueue.size(), (uint32_t)MAX_INPUT_BUFFERS);
- ASSERT_EQ(mComponent->stop(), C2_OK);
-}
-
TEST_F(Codec2AudioEncHidlTest, FlushTest) {
description("Test Request for flush");
if (mDisableTest) return;
@@ -574,6 +492,11 @@
nSampleRate = 48000;
samplesPerFrame = 1152;
break;
+ case opus:
+ nChannels = 2;
+ nSampleRate = 48000;
+ samplesPerFrame = 960;
+ break;
case amrnb:
nChannels = 1;
nSampleRate = 8000;
diff --git a/media/codec2/hidl/1.0/vts/audio/media_c2_audio_hidl_test_common.h b/media/codec2/hidl/1.0/vts/audio/media_c2_audio_hidl_test_common.h
index 89eb69e..4d773ce 100644
--- a/media/codec2/hidl/1.0/vts/audio/media_c2_audio_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/audio/media_c2_audio_hidl_test_common.h
@@ -17,8 +17,5 @@
#ifndef MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H
#define MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H
-#define MAX_RETRY 20
-#define TIME_OUT 200ms
-#define MAX_INPUT_BUFFERS 8
#endif // MEDIA_C2_AUDIO_HIDL_TEST_COMMON_H
diff --git a/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.cpp b/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.cpp
index fdccdbb..64a458c 100644
--- a/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.cpp
+++ b/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.cpp
@@ -14,39 +14,115 @@
* limitations under the License.
*/
+// #define LOG_NDEBUG 0
#define LOG_TAG "media_c2_hidl_test_common"
#include <stdio.h>
#include "media_c2_hidl_test_common.h"
-using ::android::hardware::media::c2::V1_0::FieldSupportedValues;
-void dumpFSV(const FieldSupportedValues& sv) {
- ALOGD("Dumping FSV data");
- using namespace std;
- if (sv.type == FieldSupportedValues::Type::EMPTY) {
- ALOGD("FSV Value is Empty");
- }
- if (sv.type == FieldSupportedValues::Type::RANGE) {
- ALOGD("Dumping FSV range");
- cout << ".range(" << sv.range.min;
- if (sv.range.step != 0) {
- cout << ":" << sv.range.step;
+// Test the codecs for NullBuffer, Empty Input Buffer with(out) flags set
+void testInputBuffer(
+ const std::shared_ptr<android::Codec2Client::Component>& component,
+ std::mutex& queueLock, std::list<std::unique_ptr<C2Work>>& workQueue,
+ uint32_t flags, bool isNullBuffer) {
+ std::unique_ptr<C2Work> work;
+ {
+ typedef std::unique_lock<std::mutex> ULock;
+ ULock l(queueLock);
+ if (!workQueue.empty()) {
+ work.swap(workQueue.front());
+ workQueue.pop_front();
+ } else {
+ ASSERT_TRUE(false) << "workQueue Empty at the start of test";
}
- if (sv.range.num != 1 || sv.range.denom != 1) {
- cout << ":" << sv.range.num << "/" << sv.range.denom;
- }
- cout << " " << sv.range.max << ")";
}
- if (sv.values.size()) {
- ALOGD("Dumping FSV value");
- cout << (sv.type == FieldSupportedValues::Type::FLAGS ? ".flags("
- : ".list(");
- const char* sep = "";
- for (const auto& p : sv.values) {
- cout << sep << p;
- sep = ",";
- }
- cout << ")";
+ ASSERT_NE(work, nullptr);
+
+ work->input.flags = (C2FrameData::flags_t)flags;
+ work->input.ordinal.timestamp = 0;
+ work->input.ordinal.frameIndex = 0;
+ work->input.buffers.clear();
+ if (isNullBuffer) {
+ work->input.buffers.emplace_back(nullptr);
}
- cout << endl;
+ work->worklets.clear();
+ work->worklets.emplace_back(new C2Worklet);
+
+ std::list<std::unique_ptr<C2Work>> items;
+ items.push_back(std::move(work));
+ ASSERT_EQ(component->queue(&items), C2_OK);
}
+
+// Wait for all the inputs to be consumed by the plugin.
+void waitOnInputConsumption(std::mutex& queueLock,
+ std::condition_variable& queueCondition,
+ std::list<std::unique_ptr<C2Work>>& workQueue,
+ size_t bufferCount) {
+ typedef std::unique_lock<std::mutex> ULock;
+ uint32_t queueSize;
+ uint32_t maxRetry = 0;
+ {
+ ULock l(queueLock);
+ queueSize = workQueue.size();
+ }
+ while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) {
+ ULock l(queueLock);
+ if (queueSize != workQueue.size()) {
+ queueSize = workQueue.size();
+ maxRetry = 0;
+ } else {
+ queueCondition.wait_for(l, TIME_OUT);
+ maxRetry++;
+ }
+ }
+}
+
+// process onWorkDone received by Listener
+void workDone(
+ const std::shared_ptr<android::Codec2Client::Component>& component,
+ std::unique_ptr<C2Work>& work, std::list<uint64_t>& flushedIndices,
+ std::mutex& queueLock, std::condition_variable& queueCondition,
+ std::list<std::unique_ptr<C2Work>>& workQueue, bool& eos, bool& csd,
+ uint32_t& framesReceived) {
+ // handle configuration changes in work done
+ if (work->worklets.front()->output.configUpdate.size() != 0) {
+ ALOGV("Config Update");
+ std::vector<std::unique_ptr<C2Param>> updates =
+ std::move(work->worklets.front()->output.configUpdate);
+ std::vector<C2Param*> configParam;
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ for (size_t i = 0; i < updates.size(); ++i) {
+ C2Param* param = updates[i].get();
+ if (param->index() == C2StreamCsdInfo::output::PARAM_TYPE) {
+ csd = true;
+ } else if ((param->index() ==
+ C2StreamSampleRateInfo::output::PARAM_TYPE) ||
+ (param->index() ==
+ C2StreamChannelCountInfo::output::PARAM_TYPE) ||
+ (param->index() ==
+ C2VideoSizeStreamInfo::output::PARAM_TYPE)) {
+ configParam.push_back(param);
+ }
+ }
+ component->config(configParam, C2_DONT_BLOCK, &failures);
+ ASSERT_EQ(failures.size(), 0u);
+ }
+ framesReceived++;
+ eos = (work->worklets.front()->output.flags &
+ C2FrameData::FLAG_END_OF_STREAM) != 0;
+ auto frameIndexIt = std::find(flushedIndices.begin(), flushedIndices.end(),
+ work->input.ordinal.frameIndex.peeku());
+ ALOGV("WorkDone: frameID received %d",
+ (int)work->worklets.front()->output.ordinal.frameIndex.peeku());
+ work->input.buffers.clear();
+ work->worklets.clear();
+ {
+ typedef std::unique_lock<std::mutex> ULock;
+ ULock l(queueLock);
+ workQueue.push_back(std::move(work));
+ if (!flushedIndices.empty()) {
+ flushedIndices.erase(frameIndexIt);
+ }
+ queueCondition.notify_all();
+ }
+}
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.h b/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.h
index f765baa..a688530 100644
--- a/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/common/media_c2_hidl_test_common.h
@@ -22,6 +22,7 @@
#include <android/hardware/media/c2/1.0/types.h>
#include <C2Component.h>
+#include <C2Config.h>
#include <getopt.h>
#include <hidl/HidlSupport.h>
#include <media/stagefright/foundation/ALooper.h>
@@ -38,6 +39,10 @@
#include <VtsHalHidlTargetTestEnvBase.h>
+#define MAX_RETRY 20
+#define TIME_OUT 400ms
+#define MAX_INPUT_BUFFERS 8
+
/*
* Handle Callback functions onWorkDone(), onTripped(),
* onError(), onDeath(), onFramesRendered()
@@ -176,5 +181,21 @@
/*
* common functions declarations
*/
-void dumpFSV(const FieldSupportedValues& sv);
+void testInputBuffer(
+ const std::shared_ptr<android::Codec2Client::Component>& component,
+ std::mutex& queueLock, std::list<std::unique_ptr<C2Work>>& workQueue,
+ uint32_t flags, bool isNullBuffer);
+
+void waitOnInputConsumption(std::mutex& queueLock,
+ std::condition_variable& queueCondition,
+ std::list<std::unique_ptr<C2Work>>& workQueue,
+ size_t bufferCount = MAX_INPUT_BUFFERS);
+
+void workDone(
+ const std::shared_ptr<android::Codec2Client::Component>& component,
+ std::unique_ptr<C2Work>& work, std::list<uint64_t>& flushedIndices,
+ std::mutex& queueLock, std::condition_variable& queueCondition,
+ std::list<std::unique_ptr<C2Work>>& workQueue, bool& eos, bool& csd,
+ uint32_t& framesReceived);
+
#endif // MEDIA_C2_HIDL_TEST_COMMON_H
diff --git a/media/codec2/hidl/1.0/vts/component/VtsHidlC2V1_0TargetComponentTest.cpp b/media/codec2/hidl/1.0/vts/component/VtsHidlC2V1_0TargetComponentTest.cpp
index b7fb655..ec803d7 100644
--- a/media/codec2/hidl/1.0/vts/component/VtsHidlC2V1_0TargetComponentTest.cpp
+++ b/media/codec2/hidl/1.0/vts/component/VtsHidlC2V1_0TargetComponentTest.cpp
@@ -38,14 +38,21 @@
public:
virtual void SetUp() override {
Super::SetUp();
+ mEos = false;
mClient = android::Codec2Client::CreateFromService(
gEnv->getInstance().c_str());
ASSERT_NE(mClient, nullptr);
- mListener.reset(new CodecListener());
+ mListener.reset(new CodecListener(
+ [this](std::list<std::unique_ptr<C2Work>>& workItems) {
+ handleWorkDone(workItems);
+ }));
ASSERT_NE(mListener, nullptr);
mClient->createComponent(gEnv->getComponent().c_str(), mListener,
&mComponent);
ASSERT_NE(mComponent, nullptr);
+ for (int i = 0; i < MAX_INPUT_BUFFERS; ++i) {
+ mWorkQueue.emplace_back(new C2Work);
+ }
}
virtual void TearDown() override {
@@ -59,6 +66,23 @@
}
Super::TearDown();
}
+ // callback function to process onWorkDone received by Listener
+ void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
+ for (std::unique_ptr<C2Work>& work : workItems) {
+ if (!work->worklets.empty()) {
+ bool mCsd = false;
+ uint32_t mFramesReceived = 0;
+ std::list<uint64_t> mFlushedIndices;
+ workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition,
+ mWorkQueue, mEos, mCsd, mFramesReceived);
+ }
+ }
+ }
+
+ bool mEos;
+ std::mutex mQueueLock;
+ std::condition_variable mQueueCondition;
+ std::list<std::unique_ptr<C2Work>> mWorkQueue;
std::shared_ptr<android::Codec2Client> mClient;
std::shared_ptr<android::Codec2Client::Listener> mListener;
@@ -135,8 +159,6 @@
ALOGV("Multiple Start Stop and Reset Test");
c2_status_t err = C2_OK;
-#define MAX_RETRY 16
-
for (size_t i = 0; i < MAX_RETRY; i++) {
err = mComponent->start();
ASSERT_EQ(err, C2_OK);
@@ -184,13 +206,44 @@
ASSERT_EQ(err, C2_OK);
ASSERT_EQ(failures.size(), 0u);
-#define MAX_RETRY 16
for (size_t i = 0; i < MAX_RETRY; i++) {
err = mComponent->release();
ASSERT_EQ(err, C2_OK);
}
}
+class Codec2ComponentInputTests : public Codec2ComponentHidlTest,
+ public ::testing::WithParamInterface<std::pair<uint32_t, bool> > {
+};
+
+TEST_P(Codec2ComponentInputTests, InputBufferTest) {
+ description("Tests for different inputs");
+
+ uint32_t flags = GetParam().first;
+ bool isNullBuffer = GetParam().second;
+ if (isNullBuffer) ALOGD("Testing for null input buffer with flag : %u", flags);
+ else ALOGD("Testing for empty input buffer with flag : %u", flags);
+ mEos = false;
+ ASSERT_EQ(mComponent->start(), C2_OK);
+ ASSERT_NO_FATAL_FAILURE(testInputBuffer(
+ mComponent, mQueueLock, mWorkQueue, flags, isNullBuffer));
+
+ ALOGD("Waiting for input consumption");
+ ASSERT_NO_FATAL_FAILURE(
+ waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+
+ if (flags == C2FrameData::FLAG_END_OF_STREAM) ASSERT_EQ(mEos, true);
+ ASSERT_EQ(mComponent->stop(), C2_OK);
+ ASSERT_EQ(mComponent->reset(), C2_OK);
+}
+
+INSTANTIATE_TEST_CASE_P(NonStdInputs, Codec2ComponentInputTests, ::testing::Values(
+ std::make_pair(0, true),
+ std::make_pair(C2FrameData::FLAG_END_OF_STREAM, true),
+ std::make_pair(0, false),
+ std::make_pair(C2FrameData::FLAG_CODEC_CONFIG, false),
+ std::make_pair(C2FrameData::FLAG_END_OF_STREAM, false)));
+
} // anonymous namespace
// TODO: Add test for Invalid work,
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_av1_176_144.av1 b/media/codec2/hidl/1.0/vts/res/bbb_av1_176_144.av1
new file mode 100644
index 0000000..1d67af9
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_av1_176_144.av1
Binary files differ
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_av1_176_144.info b/media/codec2/hidl/1.0/vts/res/bbb_av1_176_144.info
new file mode 100644
index 0000000..cc51168
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_av1_176_144.info
@@ -0,0 +1,300 @@
+6027 1 0
+6879 0 33000
+5 0 66000
+532 0 100000
+5 0 133000
+2458 0 166000
+5 0 200000
+475 0 233000
+5 0 266000
+1262 0 300000
+5 0 333000
+554 0 366000
+27 0 400000
+6971 0 433000
+5 0 466000
+601 0 500000
+5 0 533000
+3276 0 566000
+5 0 600000
+658 0 633000
+5 0 666000
+1680 0 700000
+5 0 733000
+610 0 766000
+24 0 800000
+6728 0 833000
+5 0 866000
+764 0 900000
+5 0 933000
+2656 0 966000
+5 0 1000000
+462 0 1033000
+5 0 1066000
+1459 0 1100000
+5 0 1133000
+608 0 1166000
+24 0 1200000
+7038 0 1233000
+5 0 1266000
+721 0 1300000
+5 0 1333000
+3102 0 1366000
+5 0 1400000
+752 0 1433000
+5 0 1466000
+1815 0 1500000
+5 0 1533000
+755 0 1566000
+25 0 1600000
+7657 0 1633000
+5 0 1666000
+852 0 1700000
+5 0 1733000
+3537 0 1766000
+5 0 1800000
+673 0 1833000
+5 0 1866000
+1774 0 1900000
+5 0 1933000
+554 0 1966000
+24 0 2000000
+8028 0 2033000
+5 0 2066000
+715 0 2100000
+5 0 2133000
+3395 0 2166000
+5 0 2200000
+736 0 2233000
+5 0 2266000
+1759 0 2300000
+5 0 2333000
+605 0 2366000
+23 0 2400000
+7651 0 2433000
+5 0 2466000
+619 0 2500000
+5 0 2533000
+2788 0 2566000
+5 0 2600000
+556 0 2633000
+5 0 2666000
+1335 0 2700000
+5 0 2733000
+521 0 2766000
+24 0 2800000
+2274 0 2833000
+676 0 2866000
+25 0 2900000
+6224 0 2933000
+5798 0 2966000
+5 0 3000000
+448 0 3033000
+5 0 3066000
+1950 0 3100000
+5 0 3133000
+386 0 3166000
+5 0 3200000
+1218 0 3233000
+5 0 3266000
+1316 0 3300000
+5 0 3333000
+580 0 3366000
+26 0 3400000
+6673 0 3433000
+5 0 3466000
+473 0 3500000
+5 0 3533000
+2467 0 3566000
+5 0 3600000
+429 0 3633000
+5 0 3666000
+1420 0 3700000
+5 0 3733000
+583 0 3766000
+29 0 3800000
+8492 0 3833000
+5 0 3866000
+720 0 3900000
+5 0 3933000
+3635 0 3966000
+5 0 4000000
+621 0 4033000
+5 0 4066000
+1969 0 4100000
+5 0 4133000
+49 0 4166000
+25 0 4200000
+7416 0 4233000
+5 0 4266000
+947 0 4300000
+5 0 4333000
+3713 0 4366000
+5 0 4400000
+714 0 4433000
+5 0 4466000
+2003 0 4500000
+5 0 4533000
+750 0 4566000
+25 0 4600000
+8470 0 4633000
+5 0 4666000
+737 0 4700000
+5 0 4733000
+4094 0 4766000
+5 0 4800000
+1019 0 4833000
+5 0 4866000
+2160 0 4900000
+5 0 4933000
+828 0 4966000
+24 0 5000000
+9282 0 5033000
+5 0 5066000
+655 0 5100000
+5 0 5133000
+3491 0 5166000
+5 0 5200000
+651 0 5233000
+5 0 5266000
+1906 0 5300000
+5 0 5333000
+662 0 5366000
+24 0 5400000
+9724 0 5433000
+5 0 5466000
+617 0 5500000
+5 0 5533000
+3145 0 5566000
+5 0 5600000
+578 0 5633000
+5 0 5666000
+1592 0 5700000
+5 0 5733000
+569 0 5766000
+25 0 5800000
+10015 0 5833000
+5 0 5866000
+609 0 5900000
+5 0 5933000
+3618 0 5966000
+5 0 6000000
+734 0 6033000
+5 0 6066000
+1748 0 6100000
+5 0 6133000
+550 0 6166000
+24 0 6200000
+8806 0 6233000
+5 0 6266000
+498 0 6300000
+5 0 6333000
+2913 0 6366000
+5 0 6400000
+597 0 6433000
+5 0 6466000
+1235 0 6500000
+5 0 6533000
+362 0 6566000
+24 0 6600000
+6592 0 6633000
+5 0 6666000
+468 0 6700000
+5 0 6733000
+1920 0 6766000
+5 0 6800000
+419 0 6833000
+5 0 6866000
+843 0 6900000
+5 0 6933000
+237 0 6966000
+24 0 7000000
+2687 0 7033000
+5 0 7066000
+399 0 7100000
+5 0 7133000
+200 0 7166000
+143 0 7200000
+25 0 7233000
+12603 0 7266000
+1139 0 7300000
+5 0 7333000
+56 0 7366000
+5 0 7400000
+273 0 7433000
+5 0 7466000
+48 0 7500000
+5 0 7533000
+102 0 7566000
+5 0 7600000
+39 0 7633000
+24 0 7666000
+3635 0 7700000
+5 0 7733000
+46 0 7766000
+5 0 7800000
+647 0 7833000
+5 0 7866000
+61 0 7900000
+5 0 7933000
+824 0 7966000
+5 0 8000000
+691 0 8033000
+27 0 8066000
+4573 0 8100000
+5 0 8133000
+473 0 8166000
+5 0 8200000
+1637 0 8233000
+5 0 8266000
+451 0 8300000
+5 0 8333000
+969 0 8366000
+5 0 8400000
+234 0 8433000
+24 0 8466000
+3361 0 8500000
+5 0 8533000
+168 0 8566000
+5 0 8600000
+662 0 8633000
+5 0 8666000
+129 0 8700000
+5 0 8733000
+443 0 8766000
+5 0 8800000
+183 0 8833000
+23 0 8866000
+2769 0 8900000
+5 0 8933000
+182 0 8966000
+5 0 9000000
+890 0 9033000
+5 0 9066000
+171 0 9100000
+5 0 9133000
+599 0 9166000
+5 0 9200000
+236 0 9233000
+23 0 9266000
+2316 0 9300000
+5 0 9333000
+333 0 9366000
+5 0 9400000
+759 0 9433000
+5 0 9466000
+210 0 9500000
+5 0 9533000
+324 0 9566000
+5 0 9600000
+98 0 9633000
+23 0 9666000
+1107 0 9700000
+5 0 9733000
+42 0 9766000
+5 0 9800000
+145 0 9833000
+5 0 9866000
+109 0 9900000
+89 0 9933000
+24 0 9966000
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_av1_640_360.av1 b/media/codec2/hidl/1.0/vts/res/bbb_av1_640_360.av1
new file mode 100644
index 0000000..529bace
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_av1_640_360.av1
Binary files differ
diff --git a/media/codec2/hidl/1.0/vts/res/bbb_av1_640_360.info b/media/codec2/hidl/1.0/vts/res/bbb_av1_640_360.info
new file mode 100644
index 0000000..fca7833
--- /dev/null
+++ b/media/codec2/hidl/1.0/vts/res/bbb_av1_640_360.info
@@ -0,0 +1,167 @@
+12571 1 0
+9881 0 33000
+5 0 66000
+544 0 100000
+5 0 133000
+2642 0 166000
+5 0 200000
+531 0 233000
+5 0 266000
+1359 0 300000
+5 0 333000
+551 0 366000
+28 0 400000
+10791 0 433000
+5 0 466000
+655 0 500000
+5 0 533000
+3769 0 566000
+5 0 600000
+711 0 633000
+5 0 666000
+2004 0 700000
+5 0 733000
+657 0 766000
+26 0 800000
+8969 0 833000
+5 0 866000
+630 0 900000
+5 0 933000
+2787 0 966000
+5 0 1000000
+404 0 1033000
+5 0 1066000
+1518 0 1100000
+5 0 1133000
+493 0 1166000
+26 0 1200000
+9900 0 1233000
+5 0 1266000
+620 0 1300000
+5 0 1333000
+3072 0 1366000
+5 0 1400000
+668 0 1433000
+5 0 1466000
+1821 0 1500000
+5 0 1533000
+682 0 1566000
+26 0 1600000
+9560 0 1633000
+5 0 1666000
+667 0 1700000
+5 0 1733000
+3249 0 1766000
+5 0 1800000
+589 0 1833000
+5 0 1866000
+1816 0 1900000
+5 0 1933000
+548 0 1966000
+26 0 2000000
+9916 0 2033000
+5 0 2066000
+628 0 2100000
+5 0 2133000
+3034 0 2166000
+5 0 2200000
+590 0 2233000
+5 0 2266000
+1581 0 2300000
+5 0 2333000
+524 0 2366000
+26 0 2400000
+8182 0 2433000
+5 0 2466000
+552 0 2500000
+5 0 2533000
+2412 0 2566000
+5 0 2600000
+489 0 2633000
+5 0 2666000
+1227 0 2700000
+5 0 2733000
+432 0 2766000
+26 0 2800000
+2017 0 2833000
+516 0 2866000
+26 0 2900000
+16619 0 2933000
+6710 0 2966000
+5 0 3000000
+425 0 3033000
+5 0 3066000
+1964 0 3100000
+5 0 3133000
+386 0 3166000
+5 0 3200000
+1129 0 3233000
+5 0 3266000
+1156 0 3300000
+5 0 3333000
+486 0 3366000
+28 0 3400000
+10304 0 3433000
+5 0 3466000
+412 0 3500000
+5 0 3533000
+2608 0 3566000
+5 0 3600000
+397 0 3633000
+5 0 3666000
+1514 0 3700000
+5 0 3733000
+533 0 3766000
+26 0 3800000
+11698 0 3833000
+5 0 3866000
+542 0 3900000
+5 0 3933000
+3334 0 3966000
+5 0 4000000
+547 0 4033000
+5 0 4066000
+1809 0 4100000
+5 0 4133000
+55 0 4166000
+26 0 4200000
+9496 0 4233000
+5 0 4266000
+658 0 4300000
+5 0 4333000
+3232 0 4366000
+5 0 4400000
+600 0 4433000
+5 0 4466000
+1766 0 4500000
+5 0 4533000
+550 0 4566000
+25 0 4600000
+9951 0 4633000
+5 0 4666000
+624 0 4700000
+5 0 4733000
+3617 0 4766000
+5 0 4800000
+644 0 4833000
+5 0 4866000
+1841 0 4900000
+5 0 4933000
+649 0 4966000
+25 0 5000000
+9901 0 5033000
+5 0 5066000
+515 0 5100000
+5 0 5133000
+2814 0 5166000
+5 0 5200000
+511 0 5233000
+5 0 5266000
+1521 0 5300000
+5 0 5333000
+509 0 5366000
+26 0 5400000
+10579 0 5433000
+5 0 5466000
+575 0 5500000
+5 0 5533000
\ No newline at end of file
diff --git a/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
index 8420cab..9a42d72 100644
--- a/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoDecTest.cpp
@@ -101,7 +101,7 @@
const StringToName kStringToName[] = {
{"h263", h263}, {"avc", avc}, {"mpeg2", mpeg2}, {"mpeg4", mpeg4},
- {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9},
+ {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9}, {"av1", av1},
};
const size_t kNumStringToName =
@@ -142,79 +142,48 @@
// callback function to process onWorkDone received by Listener
void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
for (std::unique_ptr<C2Work>& work : workItems) {
- // handle configuration changes in work done
- if (!work->worklets.empty() &&
- (work->worklets.front()->output.configUpdate.size() != 0)) {
- ALOGV("Config Update");
- std::vector<std::unique_ptr<C2Param>> updates =
- std::move(work->worklets.front()->output.configUpdate);
- std::vector<C2Param*> configParam;
- std::vector<std::unique_ptr<C2SettingResult>> failures;
- for (size_t i = 0; i < updates.size(); ++i) {
- C2Param* param = updates[i].get();
- if (param->index() ==
- C2VideoSizeStreamInfo::output::PARAM_TYPE) {
- ALOGV("Received C2VideoSizeStreamInfo");
- configParam.push_back(param);
- }
- }
- mComponent->config(configParam, C2_DONT_BLOCK, &failures);
- ASSERT_EQ(failures.size(), 0u);
- }
+ if (!work->worklets.empty()) {
+ // For decoder components current timestamp always exceeds
+ // previous timestamp
+ typedef std::unique_lock<std::mutex> ULock;
+ bool codecConfig = ((work->worklets.front()->output.flags &
+ C2FrameData::FLAG_CODEC_CONFIG) != 0);
+ if (!codecConfig &&
+ !work->worklets.front()->output.buffers.empty()) {
+ EXPECT_GE(
+ (work->worklets.front()->output.ordinal.timestamp.peeku()),
+ mTimestampUs);
+ mTimestampUs =
+ work->worklets.front()->output.ordinal.timestamp.peeku();
- mFramesReceived++;
- mEos = (work->worklets.front()->output.flags &
- C2FrameData::FLAG_END_OF_STREAM) != 0;
- auto frameIndexIt =
- std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
- work->input.ordinal.frameIndex.peeku());
-
- // For decoder components current timestamp always exceeds
- // previous timestamp
- typedef std::unique_lock<std::mutex> ULock;
- bool codecConfig = ((work->worklets.front()->output.flags &
- C2FrameData::FLAG_CODEC_CONFIG) != 0);
- if (!codecConfig &&
- !work->worklets.front()->output.buffers.empty()) {
- EXPECT_GE(
- (work->worklets.front()->output.ordinal.timestamp.peeku()),
- mTimestampUs);
- mTimestampUs =
- work->worklets.front()->output.ordinal.timestamp.peeku();
-
- ULock l(mQueueLock);
- if (mTimestampDevTest) {
- bool tsHit = false;
- std::list<uint64_t>::iterator it = mTimestampUslist.begin();
- while (it != mTimestampUslist.end()) {
- if (*it == mTimestampUs) {
- mTimestampUslist.erase(it);
- tsHit = true;
- break;
+ ULock l(mQueueLock);
+ if (mTimestampDevTest) {
+ bool tsHit = false;
+ std::list<uint64_t>::iterator it = mTimestampUslist.begin();
+ while (it != mTimestampUslist.end()) {
+ if (*it == mTimestampUs) {
+ mTimestampUslist.erase(it);
+ tsHit = true;
+ break;
+ }
+ it++;
}
- it++;
- }
- if (tsHit == false) {
- if (mTimestampUslist.empty() == false) {
- EXPECT_EQ(tsHit, true)
- << "TimeStamp not recognized";
- } else {
- std::cout << "[ INFO ] Received non-zero "
- "output / TimeStamp not recognized \n";
+ if (tsHit == false) {
+ if (mTimestampUslist.empty() == false) {
+ EXPECT_EQ(tsHit, true)
+ << "TimeStamp not recognized";
+ } else {
+ std::cout << "[ INFO ] Received non-zero "
+ "output / TimeStamp not recognized \n";
+ }
}
}
}
- }
-
- work->input.buffers.clear();
- work->worklets.clear();
- {
- ULock l(mQueueLock);
- mWorkQueue.push_back(std::move(work));
- if (!mFlushedIndices.empty()) {
- mFlushedIndices.erase(frameIndexIt);
- }
- mQueueCondition.notify_all();
+ bool mCsd;
+ workDone(mComponent, work, mFlushedIndices, mQueueLock,
+ mQueueCondition, mWorkQueue, mEos, mCsd,
+ mFramesReceived);
+ (void)mCsd;
}
}
}
@@ -227,6 +196,7 @@
hevc,
vp8,
vp9,
+ av1,
unknown_comp,
};
@@ -341,6 +311,11 @@
"bbb_vp9_640x360_1600kbps_30fps.vp9"},
{"bbb_vp9_176x144_285kbps_60fps.info",
"bbb_vp9_640x360_1600kbps_30fps.info"}},
+ {Codec2VideoDecHidlTest::standardComp::av1,
+ {"bbb_av1_640_360.av1",
+ "bbb_av1_176_144.av1"},
+ {"bbb_av1_640_360.info",
+ "bbb_av1_176_144.info"}},
};
for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
@@ -352,11 +327,11 @@
}
}
-void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &component,
- std::mutex &queueLock, std::condition_variable &queueCondition,
- std::list<std::unique_ptr<C2Work>> &workQueue,
- std::list<uint64_t> &flushedIndices,
- std::shared_ptr<C2BlockPool> &linearPool,
+void decodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
+ std::mutex &queueLock, std::condition_variable& queueCondition,
+ std::list<std::unique_ptr<C2Work>>& workQueue,
+ std::list<uint64_t>& flushedIndices,
+ std::shared_ptr<C2BlockPool>& linearPool,
std::ifstream& eleStream,
android::Vector<FrameInfo>* Info,
int offset, int range, bool signalEOS = true) {
@@ -397,35 +372,37 @@
int size = (*Info)[frameID].bytesCount;
char* data = (char*)malloc(size);
+ ASSERT_NE(data, nullptr);
eleStream.read(data, size);
ASSERT_EQ(eleStream.gcount(), size);
- std::shared_ptr<C2LinearBlock> block;
- ASSERT_EQ(C2_OK,
- linearPool->fetchLinearBlock(
- size, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
- &block));
- ASSERT_TRUE(block);
-
- // Write View
- C2WriteView view = block->map().get();
- if (view.error() != C2_OK) {
- fprintf(stderr, "C2LinearBlock::map() failed : %d", view.error());
- break;
- }
- ASSERT_EQ((size_t)size, view.capacity());
- ASSERT_EQ(0u, view.offset());
- ASSERT_EQ((size_t)size, view.size());
-
- memcpy(view.base(), data, size);
-
work->input.buffers.clear();
- work->input.buffers.emplace_back(new LinearBuffer(block));
+ if (size) {
+ std::shared_ptr<C2LinearBlock> block;
+ ASSERT_EQ(C2_OK,
+ linearPool->fetchLinearBlock(
+ size, {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE},
+ &block));
+ ASSERT_TRUE(block);
+
+ // Write View
+ C2WriteView view = block->map().get();
+ if (view.error() != C2_OK) {
+ fprintf(stderr, "C2LinearBlock::map() failed : %d", view.error());
+ break;
+ }
+ ASSERT_EQ((size_t)size, view.capacity());
+ ASSERT_EQ(0u, view.offset());
+ ASSERT_EQ((size_t)size, view.size());
+
+ memcpy(view.base(), data, size);
+
+ work->input.buffers.emplace_back(new LinearBuffer(block));
+ free(data);
+ }
work->worklets.clear();
work->worklets.emplace_back(new C2Worklet);
- free(data);
-
std::list<std::unique_ptr<C2Work>> items;
items.push_back(std::move(work));
@@ -437,29 +414,6 @@
}
}
-void waitOnInputConsumption(std::mutex& queueLock,
- std::condition_variable& queueCondition,
- std::list<std::unique_ptr<C2Work>>& workQueue,
- size_t bufferCount = MAX_INPUT_BUFFERS) {
- typedef std::unique_lock<std::mutex> ULock;
- uint32_t queueSize;
- uint32_t maxRetry = 0;
- {
- ULock l(queueLock);
- queueSize = workQueue.size();
- }
- while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) {
- ULock l(queueLock);
- if (queueSize != workQueue.size()) {
- queueSize = workQueue.size();
- maxRetry = 0;
- } else {
- queueCondition.wait_for(l, TIME_OUT);
- maxRetry++;
- }
- }
-}
-
TEST_F(Codec2VideoDecHidlTest, validateCompName) {
if (mDisableTest) return;
ALOGV("Checks if the given component is a valid video component");
@@ -678,8 +632,8 @@
EXPECT_GE(mFramesReceived, 1U);
ASSERT_EQ(mEos, true);
ASSERT_EQ(mComponent->stop(), C2_OK);
- ASSERT_EQ(mComponent->release(), C2_OK);
}
+ ASSERT_EQ(mComponent->release(), C2_OK);
}
TEST_F(Codec2VideoDecHidlTest, EOSTest) {
@@ -712,7 +666,6 @@
ASSERT_EQ(mComponent->queue(&items), C2_OK);
{
- typedef std::unique_lock<std::mutex> ULock;
ULock l(mQueueLock);
if (mWorkQueue.size() != MAX_INPUT_BUFFERS) {
mQueueCondition.wait_for(l, TIME_OUT);
@@ -723,46 +676,6 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-TEST_F(Codec2VideoDecHidlTest, EmptyBufferTest) {
- description("Tests empty input buffer");
- if (mDisableTest) return;
- typedef std::unique_lock<std::mutex> ULock;
- ASSERT_EQ(mComponent->start(), C2_OK);
- std::unique_ptr<C2Work> work;
- // Prepare C2Work
- {
- ULock l(mQueueLock);
- if (!mWorkQueue.empty()) {
- work.swap(mWorkQueue.front());
- mWorkQueue.pop_front();
- } else {
- ASSERT_TRUE(false) << "mWorkQueue Empty at the start of test";
- }
- }
- ASSERT_NE(work, nullptr);
-
- work->input.flags = (C2FrameData::flags_t)0;
- work->input.ordinal.timestamp = 0;
- work->input.ordinal.frameIndex = 0;
- work->input.buffers.clear();
- work->worklets.clear();
- work->worklets.emplace_back(new C2Worklet);
-
- std::list<std::unique_ptr<C2Work>> items;
- items.push_back(std::move(work));
- ASSERT_EQ(mComponent->queue(&items), C2_OK);
-
- {
- typedef std::unique_lock<std::mutex> ULock;
- ULock l(mQueueLock);
- if (mWorkQueue.size() != MAX_INPUT_BUFFERS) {
- mQueueCondition.wait_for(l, TIME_OUT);
- }
- }
- ASSERT_EQ(mWorkQueue.size(), (size_t)MAX_INPUT_BUFFERS);
- ASSERT_EQ(mComponent->stop(), C2_OK);
-}
-
TEST_F(Codec2VideoDecHidlTest, FlushTest) {
description("Tests Flush calls");
if (mDisableTest) return;
@@ -874,6 +787,69 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
+TEST_F(Codec2VideoDecHidlTest, DecodeTestEmptyBuffersInserted) {
+ description("Decode with multiple empty input frames");
+ if (mDisableTest) return;
+
+ char mURL[512], info[512];
+ std::ifstream eleStream, eleInfo;
+
+ strcpy(mURL, gEnv->getRes().c_str());
+ strcpy(info, gEnv->getRes().c_str());
+ GetURLForComponent(mCompName, mURL, info);
+
+ eleInfo.open(info);
+ ASSERT_EQ(eleInfo.is_open(), true) << mURL << " - file not found";
+ android::Vector<FrameInfo> Info;
+ int bytesCount = 0;
+ uint32_t frameId = 0;
+ uint32_t flags = 0;
+ uint32_t timestamp = 0;
+ bool codecConfig = false;
+ // This test introduces empty CSD after every 20th frame
+ // and empty input frames at an interval of 5 frames.
+ while (1) {
+ if (!(frameId % 5)) {
+ if (!(frameId % 20)) flags = 32;
+ else flags = 0;
+ bytesCount = 0;
+ } else {
+ if (!(eleInfo >> bytesCount)) break;
+ eleInfo >> flags;
+ eleInfo >> timestamp;
+ codecConfig = flags ?
+ ((1 << (flags - 1)) & C2FrameData::FLAG_CODEC_CONFIG) != 0 : 0;
+ }
+ Info.push_back({bytesCount, flags, timestamp});
+ frameId++;
+ }
+ eleInfo.close();
+
+ ASSERT_EQ(mComponent->start(), C2_OK);
+ ALOGV("mURL : %s", mURL);
+ eleStream.open(mURL, std::ifstream::binary);
+ ASSERT_EQ(eleStream.is_open(), true);
+ ASSERT_NO_FATAL_FAILURE(decodeNFrames(
+ mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices,
+ mLinearPool, eleStream, &Info, 0, (int)Info.size()));
+
+ // blocking call to ensures application to Wait till all the inputs are
+ // consumed
+ if (!mEos) {
+ ALOGV("Waiting for input consumption");
+ ASSERT_NO_FATAL_FAILURE(
+ waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue));
+ }
+
+ eleStream.close();
+ if (mFramesReceived != Info.size()) {
+ ALOGE("Input buffer count and Output buffer count mismatch");
+ ALOGV("framesReceived : %d inputFrames : %zu", mFramesReceived,
+ Info.size());
+ ASSERT_TRUE(false);
+ }
+}
+
} // anonymous namespace
// TODO : Video specific configuration Test
diff --git a/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoEncTest.cpp b/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoEncTest.cpp
index 87b7902..8585c87 100644
--- a/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/video/VtsHidlC2V1_0TargetVideoEncTest.cpp
@@ -139,40 +139,11 @@
// callback function to process onWorkDone received by Listener
void handleWorkDone(std::list<std::unique_ptr<C2Work>>& workItems) {
for (std::unique_ptr<C2Work>& work : workItems) {
- // handle configuration changes in work done
- if (!work->worklets.empty() &&
- (work->worklets.front()->output.configUpdate.size() != 0)) {
- ALOGV("Config Update");
- std::vector<std::unique_ptr<C2Param>> updates =
- std::move(work->worklets.front()->output.configUpdate);
- std::vector<C2Param*> configParam;
- std::vector<std::unique_ptr<C2SettingResult>> failures;
- for (size_t i = 0; i < updates.size(); ++i) {
- C2Param* param = updates[i].get();
- if (param->index() == C2StreamCsdInfo::output::PARAM_TYPE) {
- mCsd = true;
- }
- }
- }
- mFramesReceived++;
- if (work->result != C2_OK) mFailedWorkReceived++;
- mEos = (work->worklets.front()->output.flags &
- C2FrameData::FLAG_END_OF_STREAM) != 0;
- auto frameIndexIt =
- std::find(mFlushedIndices.begin(), mFlushedIndices.end(),
- work->input.ordinal.frameIndex.peeku());
- ALOGV("WorkDone: frameID received %d",
- (int)work->worklets.front()->output.ordinal.frameIndex.peeku());
- work->input.buffers.clear();
- work->worklets.clear();
- {
- typedef std::unique_lock<std::mutex> ULock;
- ULock l(mQueueLock);
- mWorkQueue.push_back(std::move(work));
- if (!mFlushedIndices.empty()) {
- mFlushedIndices.erase(frameIndexIt);
- }
- mQueueCondition.notify_all();
+ if (!work->worklets.empty()) {
+ if (work->result != C2_OK) mFailedWorkReceived++;
+ workDone(mComponent, work, mFlushedIndices, mQueueLock,
+ mQueueCondition, mWorkQueue, mEos, mCsd,
+ mFramesReceived);
}
}
}
@@ -272,11 +243,11 @@
strcat(URL, "bbb_352x288_420p_30fps_32frames.yuv");
}
-void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component> &component,
- std::mutex &queueLock, std::condition_variable &queueCondition,
- std::list<std::unique_ptr<C2Work>> &workQueue,
- std::list<uint64_t> &flushedIndices,
- std::shared_ptr<C2BlockPool> &graphicPool,
+void encodeNFrames(const std::shared_ptr<android::Codec2Client::Component>& component,
+ std::mutex &queueLock, std::condition_variable& queueCondition,
+ std::list<std::unique_ptr<C2Work>>& workQueue,
+ std::list<uint64_t>& flushedIndices,
+ std::shared_ptr<C2BlockPool>& graphicPool,
std::ifstream& eleStream, uint32_t frameID,
uint32_t nFrames, uint32_t nWidth, int32_t nHeight,
bool flushed = false,bool signalEOS = true) {
@@ -319,6 +290,7 @@
flushedIndices.emplace_back(frameID);
}
char* data = (char*)malloc(bytesCount);
+ ASSERT_NE(data, nullptr);
memset(data, 0, bytesCount);
if (eleStream.is_open()) {
eleStream.read(data, bytesCount);
@@ -365,30 +337,6 @@
}
}
-void waitOnInputConsumption(std::mutex &queueLock,
- std::condition_variable &queueCondition,
- std::list<std::unique_ptr<C2Work>> &workQueue,
- size_t bufferCount = MAX_INPUT_BUFFERS) {
- typedef std::unique_lock<std::mutex> ULock;
- uint32_t queueSize;
- int maxRetry = 0;
- {
- ULock l(queueLock);
- queueSize = workQueue.size();
- }
- while ((maxRetry < MAX_RETRY) && (queueSize < bufferCount)) {
- ULock l(queueLock);
- if (queueSize != workQueue.size()) {
- queueSize = workQueue.size();
- maxRetry = 0;
- } else {
- queueCondition.wait_for(l, TIME_OUT);
- maxRetry++;
- }
- }
-}
-
-
TEST_F(Codec2VideoEncHidlTest, validateCompName) {
if (mDisableTest) return;
ALOGV("Checks if the given component is a valid video component");
@@ -488,46 +436,6 @@
ASSERT_EQ(mComponent->stop(), C2_OK);
}
-TEST_F(Codec2VideoEncHidlTest, EmptyBufferTest) {
- description("Tests empty input buffer");
- if (mDisableTest) return;
- ASSERT_EQ(mComponent->start(), C2_OK);
-
- typedef std::unique_lock<std::mutex> ULock;
- std::unique_ptr<C2Work> work;
- {
- ULock l(mQueueLock);
- if (!mWorkQueue.empty()) {
- work.swap(mWorkQueue.front());
- mWorkQueue.pop_front();
- } else {
- ALOGE("mWorkQueue Empty is not expected at the start of the test");
- ASSERT_TRUE(false);
- }
- }
- ASSERT_NE(work, nullptr);
- work->input.flags = (C2FrameData::flags_t)0;
- work->input.ordinal.timestamp = 0;
- work->input.ordinal.frameIndex = 0;
- work->input.buffers.clear();
- work->worklets.clear();
- work->worklets.emplace_back(new C2Worklet);
-
- std::list<std::unique_ptr<C2Work>> items;
- items.push_back(std::move(work));
- ASSERT_EQ(mComponent->queue(&items), C2_OK);
- uint32_t queueSize;
- {
- ULock l(mQueueLock);
- queueSize = mWorkQueue.size();
- if (queueSize < MAX_INPUT_BUFFERS) {
- mQueueCondition.wait_for(l, TIME_OUT);
- }
- }
- ASSERT_EQ(mWorkQueue.size(), (uint32_t)MAX_INPUT_BUFFERS);
- ASSERT_EQ(mComponent->stop(), C2_OK);
-}
-
TEST_F(Codec2VideoEncHidlTest, FlushTest) {
description("Test Request for flush");
if (mDisableTest) return;
diff --git a/media/codec2/hidl/1.0/vts/video/media_c2_video_hidl_test_common.h b/media/codec2/hidl/1.0/vts/video/media_c2_video_hidl_test_common.h
index 1215b13..dd45557 100644
--- a/media/codec2/hidl/1.0/vts/video/media_c2_video_hidl_test_common.h
+++ b/media/codec2/hidl/1.0/vts/video/media_c2_video_hidl_test_common.h
@@ -17,9 +17,6 @@
#ifndef MEDIA_C2_VIDEO_HIDL_TEST_COMMON_H
#define MEDIA_C2_VIDEO_HIDL_TEST_COMMON_H
-#define MAX_RETRY 20
-#define TIME_OUT 400ms
-#define MAX_INPUT_BUFFERS 8
#define ENCODER_TIMESTAMP_INCREMENT 40000
#define ENC_NUM_FRAMES 32
#define ENC_DEFAULT_FRAME_WIDTH 352
diff --git a/media/codec2/hidl/client/Android.bp b/media/codec2/hidl/client/Android.bp
index bdc02d2..a2a498d 100644
--- a/media/codec2/hidl/client/Android.bp
+++ b/media/codec2/hidl/client/Android.bp
@@ -7,7 +7,7 @@
shared_libs: [
"android.hardware.graphics.bufferqueue@1.0",
- "android.hardware.media.bufferpool@1.0",
+ "android.hardware.media.bufferpool@2.0",
"android.hardware.media.c2@1.0",
"libbase",
"libbinder",
@@ -19,7 +19,7 @@
"libhidlbase",
"libhidltransport",
"liblog",
- "libstagefright_bufferpool@1.0",
+ "libstagefright_bufferpool@2.0",
"libstagefright_bufferqueue_helper",
"libui",
"libutils",
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index 26bd96c..ff3e534 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -34,7 +34,7 @@
#include <media/stagefright/bqhelper/WGraphicBufferProducer.h>
#undef LOG
-#include <android/hardware/media/bufferpool/1.0/IClientManager.h>
+#include <android/hardware/media/bufferpool/2.0/IClientManager.h>
#include <android/hardware/media/c2/1.0/IComponent.h>
#include <android/hardware/media/c2/1.0/IComponentInterface.h>
#include <android/hardware/media/c2/1.0/IComponentListener.h>
@@ -55,8 +55,8 @@
using namespace ::android::hardware::media::c2::V1_0;
using namespace ::android::hardware::media::c2::V1_0::utils;
-using namespace ::android::hardware::media::bufferpool::V1_0;
-using namespace ::android::hardware::media::bufferpool::V1_0::implementation;
+using namespace ::android::hardware::media::bufferpool::V2_0;
+using namespace ::android::hardware::media::bufferpool::V2_0::implementation;
namespace /* unnamed */ {
diff --git a/media/codec2/hidl/client/include/codec2/hidl/client.h b/media/codec2/hidl/client/include/codec2/hidl/client.h
index 3ab3967..c48bf0c 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/client.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/client.h
@@ -85,9 +85,9 @@
namespace hardware {
namespace media {
namespace bufferpool {
-namespace V1_0 {
+namespace V2_0 {
struct IClientManager;
-} // namespace V1_0
+} // namespace V2_0
} // namespace bufferpool
} // namespace media
} // namespace hardware
@@ -237,7 +237,7 @@
mutable std::vector<std::unique_ptr<std::vector<std::string>>>
mAliasesBuffer;
- sp<::android::hardware::media::bufferpool::V1_0::IClientManager>
+ sp<::android::hardware::media::bufferpool::V2_0::IClientManager>
mHostPoolManager;
};
diff --git a/media/codec2/vndk/Android.bp b/media/codec2/vndk/Android.bp
index 0eb90be..e0b1355 100644
--- a/media/codec2/vndk/Android.bp
+++ b/media/codec2/vndk/Android.bp
@@ -35,7 +35,7 @@
export_shared_lib_headers: [
"libbase",
- "android.hardware.media.bufferpool@1.0",
+ "android.hardware.media.bufferpool@2.0",
],
local_include_dirs: [
@@ -51,7 +51,7 @@
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.bufferqueue@1.0",
"android.hardware.graphics.mapper@2.0",
- "android.hardware.media.bufferpool@1.0",
+ "android.hardware.media.bufferpool@2.0",
"libbase",
"libbinder",
"libcutils",
@@ -63,7 +63,7 @@
"liblog",
"libstagefright_bufferqueue_helper",
"libstagefright_foundation",
- "libstagefright_bufferpool@1.0",
+ "libstagefright_bufferpool@2.0",
"libui",
"libutils",
],
diff --git a/media/codec2/vndk/C2Buffer.cpp b/media/codec2/vndk/C2Buffer.cpp
index 47366ca..710b536 100644
--- a/media/codec2/vndk/C2Buffer.cpp
+++ b/media/codec2/vndk/C2Buffer.cpp
@@ -33,12 +33,12 @@
using android::C2AllocatorGralloc;
using android::C2AllocatorIon;
using android::hardware::media::bufferpool::BufferPoolData;
-using android::hardware::media::bufferpool::V1_0::ResultStatus;
-using android::hardware::media::bufferpool::V1_0::implementation::BufferPoolAllocation;
-using android::hardware::media::bufferpool::V1_0::implementation::BufferPoolAllocator;
-using android::hardware::media::bufferpool::V1_0::implementation::ClientManager;
-using android::hardware::media::bufferpool::V1_0::implementation::ConnectionId;
-using android::hardware::media::bufferpool::V1_0::implementation::INVALID_CONNECTIONID;
+using android::hardware::media::bufferpool::V2_0::ResultStatus;
+using android::hardware::media::bufferpool::V2_0::implementation::BufferPoolAllocation;
+using android::hardware::media::bufferpool::V2_0::implementation::BufferPoolAllocator;
+using android::hardware::media::bufferpool::V2_0::implementation::ClientManager;
+using android::hardware::media::bufferpool::V2_0::implementation::ConnectionId;
+using android::hardware::media::bufferpool::V2_0::implementation::INVALID_CONNECTIONID;
// This anonymous namespace contains the helper classes that allow our implementation to create
// block/buffer objects.
diff --git a/media/codec2/vndk/include/C2BufferPriv.h b/media/codec2/vndk/include/C2BufferPriv.h
index d0b9152..be5f69c 100644
--- a/media/codec2/vndk/include/C2BufferPriv.h
+++ b/media/codec2/vndk/include/C2BufferPriv.h
@@ -20,7 +20,7 @@
#include <functional>
#include <C2Buffer.h>
-#include <android/hardware/media/bufferpool/1.0/IAccessor.h>
+#include <android/hardware/media/bufferpool/2.0/IAccessor.h>
class C2BasicLinearBlockPool : public C2BlockPool {
public:
@@ -112,7 +112,7 @@
* \return true IAcessor is writen successfully.
* \return false IAccessor is not written.
*/
- bool getAccessor(android::sp<android::hardware::media::bufferpool::V1_0::IAccessor> *accessor);
+ bool getAccessor(android::sp<android::hardware::media::bufferpool::V2_0::IAccessor> *accessor);
private:
const std::shared_ptr<C2Allocator> mAllocator;
diff --git a/media/extractors/mkv/Android.bp b/media/extractors/mkv/Android.bp
index 8d028e1..1744d3d 100644
--- a/media/extractors/mkv/Android.bp
+++ b/media/extractors/mkv/Android.bp
@@ -11,7 +11,6 @@
shared_libs: [
"liblog",
- "libmediaextractor",
"libmediandk",
],
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 1fdac05..4a30740 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -29,10 +29,8 @@
#include <media/stagefright/foundation/ByteUtils.h>
#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/MediaBufferBase.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
#include <media/stagefright/MetaDataUtils.h>
#include <utils/String8.h>
@@ -127,7 +125,7 @@
BlockIterator &operator=(const BlockIterator &);
};
-struct MatroskaSource : public MediaTrackHelperV2 {
+struct MatroskaSource : public MediaTrackHelperV3 {
MatroskaSource(MatroskaExtractor *extractor, size_t index);
virtual media_status_t start();
@@ -136,7 +134,7 @@
virtual media_status_t getFormat(AMediaFormat *);
virtual media_status_t read(
- MediaBufferBase **buffer, const ReadOptions *options);
+ MediaBufferHelperV3 **buffer, const ReadOptions *options);
protected:
virtual ~MatroskaSource();
@@ -156,11 +154,11 @@
BlockIterator mBlockIter;
ssize_t mNALSizeLen; // for type AVC or HEVC
- List<MediaBufferBase *> mPendingFrames;
+ List<MediaBufferHelperV3 *> mPendingFrames;
status_t advance();
- status_t setWebmBlockCryptoInfo(MediaBufferBase *mbuf);
+ status_t setWebmBlockCryptoInfo(MediaBufferHelperV3 *mbuf);
media_status_t readBlock();
void clearPendingFrames();
@@ -265,6 +263,8 @@
return AMEDIA_ERROR_MALFORMED;
}
+ // allocate one small initial buffer, but leave plenty of room to grow
+ mBufferGroup->init(1 /* number of buffers */, 1024 /* buffer size */, 64 /* growth limit */);
mBlockIter.reset();
return AMEDIA_OK;
@@ -569,7 +569,7 @@
void MatroskaSource::clearPendingFrames() {
while (!mPendingFrames.empty()) {
- MediaBufferBase *frame = *mPendingFrames.begin();
+ MediaBufferHelperV3 *frame = *mPendingFrames.begin();
mPendingFrames.erase(mPendingFrames.begin());
frame->release();
@@ -577,7 +577,7 @@
}
}
-status_t MatroskaSource::setWebmBlockCryptoInfo(MediaBufferBase *mbuf) {
+status_t MatroskaSource::setWebmBlockCryptoInfo(MediaBufferHelperV3 *mbuf) {
if (mbuf->range_length() < 1 || mbuf->range_length() - 1 > INT32_MAX) {
// 1-byte signal
return ERROR_MALFORMED;
@@ -591,7 +591,7 @@
return ERROR_MALFORMED;
}
- MetaDataBase &meta = mbuf->meta_data();
+ AMediaFormat *meta = mbuf->meta_data();
if (encrypted) {
uint8_t ctrCounter[16] = { 0 };
const uint8_t *keyId;
@@ -599,9 +599,9 @@
AMediaFormat *trackMeta = mExtractor->mTracks.itemAt(mTrackIndex).mMeta;
AMediaFormat_getBuffer(trackMeta, AMEDIAFORMAT_KEY_CRYPTO_KEY,
(void**)&keyId, &keyIdSize);
- meta.setData(kKeyCryptoKey, 0, keyId, keyIdSize);
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_KEY, keyId, keyIdSize);
memcpy(ctrCounter, data + 1, 8);
- meta.setData(kKeyCryptoIV, 0, ctrCounter, 16);
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_IV, ctrCounter, 16);
if (partitioned) {
/* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@@ -654,8 +654,10 @@
}
uint32_t sizeofPlainSizes = sizeof(uint32_t) * plainSizes.size();
uint32_t sizeofEncryptedSizes = sizeof(uint32_t) * encryptedSizes.size();
- meta.setData(kKeyPlainSizes, 0, plainSizes.data(), sizeofPlainSizes);
- meta.setData(kKeyEncryptedSizes, 0, encryptedSizes.data(), sizeofEncryptedSizes);
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES,
+ plainSizes.data(), sizeofPlainSizes);
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES,
+ encryptedSizes.data(), sizeofEncryptedSizes);
mbuf->set_range(frameOffset, mbuf->range_length() - frameOffset);
} else {
/*
@@ -675,8 +677,10 @@
*/
int32_t plainSizes[] = { 0 };
int32_t encryptedSizes[] = { static_cast<int32_t>(mbuf->range_length() - 9) };
- meta.setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
- meta.setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES,
+ plainSizes, sizeof(plainSizes));
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES,
+ encryptedSizes, sizeof(encryptedSizes));
mbuf->set_range(9, mbuf->range_length() - 9);
}
} else {
@@ -693,8 +697,10 @@
*/
int32_t plainSizes[] = { static_cast<int32_t>(mbuf->range_length() - 1) };
int32_t encryptedSizes[] = { 0 };
- meta.setData(kKeyPlainSizes, 0, plainSizes, sizeof(plainSizes));
- meta.setData(kKeyEncryptedSizes, 0, encryptedSizes, sizeof(encryptedSizes));
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES,
+ plainSizes, sizeof(plainSizes));
+ AMediaFormat_setBuffer(meta, AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES,
+ encryptedSizes, sizeof(encryptedSizes));
mbuf->set_range(1, mbuf->range_length() - 1);
}
@@ -721,14 +727,17 @@
}
len += trackInfo->mHeaderLen;
- MediaBufferBase *mbuf = MediaBufferBase::Create(len);
+ MediaBufferHelperV3 *mbuf;
+ mBufferGroup->acquire_buffer(&mbuf, false /* nonblocking */, len /* requested size */);
+ mbuf->set_range(0, len);
uint8_t *data = static_cast<uint8_t *>(mbuf->data());
if (trackInfo->mHeader) {
memcpy(data, trackInfo->mHeader, trackInfo->mHeaderLen);
}
- mbuf->meta_data().setInt64(kKeyTime, timeUs);
- mbuf->meta_data().setInt32(kKeyIsSyncFrame, block->IsKey());
+ AMediaFormat *meta = mbuf->meta_data();
+ AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, timeUs);
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, block->IsKey());
status_t err = frame.Read(mExtractor->mReader, data + trackInfo->mHeaderLen);
if (err == OK
@@ -754,7 +763,7 @@
}
media_status_t MatroskaSource::read(
- MediaBufferBase **out, const ReadOptions *options) {
+ MediaBufferHelperV3 **out, const ReadOptions *options) {
*out = NULL;
int64_t targetSampleTimeUs = -1ll;
@@ -790,13 +799,13 @@
}
}
- MediaBufferBase *frame = *mPendingFrames.begin();
+ MediaBufferHelperV3 *frame = *mPendingFrames.begin();
mPendingFrames.erase(mPendingFrames.begin());
if ((mType != AVC && mType != HEVC) || mNALSizeLen == 0) {
if (targetSampleTimeUs >= 0ll) {
- frame->meta_data().setInt64(
- kKeyTargetTime, targetSampleTimeUs);
+ AMediaFormat_setInt64(frame->meta_data(),
+ AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
}
*out = frame;
@@ -819,7 +828,7 @@
size_t srcSize = frame->range_length();
size_t dstSize = 0;
- MediaBufferBase *buffer = NULL;
+ MediaBufferHelperV3 *buffer = NULL;
uint8_t *dstPtr = NULL;
for (int32_t pass = 0; pass < 2; ++pass) {
@@ -879,16 +888,20 @@
// each 4-byte nal size with a 4-byte start code
buffer = frame;
} else {
- buffer = MediaBufferBase::Create(dstSize);
+ mBufferGroup->acquire_buffer(
+ &buffer, false /* nonblocking */, dstSize /* requested size */);
+ buffer->set_range(0, dstSize);
}
+ AMediaFormat *frameMeta = frame->meta_data();
int64_t timeUs;
- CHECK(frame->meta_data().findInt64(kKeyTime, &timeUs));
+ CHECK(AMediaFormat_getInt64(frameMeta, AMEDIAFORMAT_KEY_TIME_US, &timeUs));
int32_t isSync;
- CHECK(frame->meta_data().findInt32(kKeyIsSyncFrame, &isSync));
+ CHECK(AMediaFormat_getInt32(frameMeta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, &isSync));
- buffer->meta_data().setInt64(kKeyTime, timeUs);
- buffer->meta_data().setInt32(kKeyIsSyncFrame, isSync);
+ AMediaFormat *bufMeta = buffer->meta_data();
+ AMediaFormat_setInt64(bufMeta, AMEDIAFORMAT_KEY_TIME_US, timeUs);
+ AMediaFormat_setInt32(bufMeta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, isSync);
dstPtr = (uint8_t *)buffer->data();
}
@@ -900,8 +913,8 @@
}
if (targetSampleTimeUs >= 0ll) {
- buffer->meta_data().setInt64(
- kKeyTargetTime, targetSampleTimeUs);
+ AMediaFormat_setInt64(buffer->meta_data(),
+ AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
}
*out = buffer;
@@ -992,7 +1005,7 @@
return mTracks.size();
}
-MediaTrackHelperV2 *MatroskaExtractor::getTrack(size_t index) {
+MediaTrackHelperV3 *MatroskaExtractor::getTrack(size_t index) {
if (index >= mTracks.size()) {
return NULL;
}
@@ -1660,22 +1673,22 @@
__attribute__ ((visibility ("default")))
ExtractorDef GETEXTRACTORDEF() {
return {
- EXTRACTORDEF_VERSION_CURRENT,
+ EXTRACTORDEF_VERSION_CURRENT + 1,
UUID("abbedd92-38c4-4904-a4c1-b3f45f899980"),
1,
"Matroska Extractor",
{
- .v2 = [](
+ .v3 = [](
CDataSource *source,
float *confidence,
void **,
- FreeMetaFunc *) -> CreatorFuncV2 {
+ FreeMetaFunc *) -> CreatorFuncV3 {
DataSourceHelper helper(source);
if (SniffMatroska(&helper, confidence)) {
return [](
CDataSource *source,
- void *) -> CMediaExtractorV2* {
- return wrapV2(new MatroskaExtractor(new DataSourceHelper(source)));};
+ void *) -> CMediaExtractorV3* {
+ return wrapV3(new MatroskaExtractor(new DataSourceHelper(source)));};
}
return NULL;
}
diff --git a/media/extractors/mkv/MatroskaExtractor.h b/media/extractors/mkv/MatroskaExtractor.h
index 2fa8881..a09256a 100644
--- a/media/extractors/mkv/MatroskaExtractor.h
+++ b/media/extractors/mkv/MatroskaExtractor.h
@@ -35,12 +35,12 @@
struct DataSourceBaseReader;
struct MatroskaSource;
-struct MatroskaExtractor : public MediaExtractorPluginHelperV2 {
+struct MatroskaExtractor : public MediaExtractorPluginHelperV3 {
explicit MatroskaExtractor(DataSourceHelper *source);
virtual size_t countTracks();
- virtual MediaTrackHelperV2 *getTrack(size_t index);
+ virtual MediaTrackHelperV3 *getTrack(size_t index);
virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
diff --git a/media/extractors/mp4/Android.bp b/media/extractors/mp4/Android.bp
index 91de353..1b308aa 100644
--- a/media/extractors/mp4/Android.bp
+++ b/media/extractors/mp4/Android.bp
@@ -15,7 +15,6 @@
shared_libs: [
"liblog",
- "libmediaextractor",
"libmediandk"
],
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 9fb2e35..c4b539d 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -44,10 +44,9 @@
#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/foundation/avc_utils.h>
#include <media/stagefright/foundation/hexdump.h>
-#include <media/stagefright/MediaBufferBase.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
-#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MetaDataBase.h>
#include <utils/String8.h>
#include <byteswap.h>
@@ -70,7 +69,7 @@
kMaxAtomSize = 64 * 1024 * 1024,
};
-class MPEG4Source : public MediaTrackHelperV2 {
+class MPEG4Source : public MediaTrackHelperV3 {
static const size_t kMaxPcmFrameSize = 8192;
public:
// Caller retains ownership of both "dataSource" and "sampleTable".
@@ -89,10 +88,10 @@
virtual media_status_t getFormat(AMediaFormat *);
- virtual media_status_t read(MediaBufferBase **buffer, const ReadOptions *options = NULL);
+ virtual media_status_t read(MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
virtual bool supportNonblockingRead() { return true; }
virtual media_status_t fragmentedRead(
- MediaBufferBase **buffer, const ReadOptions *options = NULL);
+ MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
virtual ~MPEG4Source();
@@ -137,9 +136,7 @@
bool mStarted;
- MediaBufferGroup *mGroup;
-
- MediaBufferBase *mBuffer;
+ MediaBufferHelperV3 *mBuffer;
uint8_t *mSrcBuffer;
@@ -3827,7 +3824,7 @@
}
}
-MediaTrackHelperV2 *MPEG4Extractor::getTrack(size_t index) {
+MediaTrackHelperV3 *MPEG4Extractor::getTrack(size_t index) {
status_t err;
if ((err = readMetaData()) != OK) {
return NULL;
@@ -4329,7 +4326,6 @@
mIsPcm(false),
mNALLengthSize(0),
mStarted(false),
- mGroup(NULL),
mBuffer(NULL),
mSrcBuffer(NULL),
mIsHeif(itemTable != NULL),
@@ -4458,12 +4454,10 @@
const size_t kInitialBuffers = 2;
const size_t kMaxBuffers = 8;
const size_t realMaxBuffers = min(kMaxBufferSize / max_size, kMaxBuffers);
- mGroup = new MediaBufferGroup(kInitialBuffers, max_size, realMaxBuffers);
+ mBufferGroup->init(kInitialBuffers, max_size, realMaxBuffers);
mSrcBuffer = new (std::nothrow) uint8_t[max_size];
if (mSrcBuffer == NULL) {
// file probably specified a bad max size
- delete mGroup;
- mGroup = NULL;
return AMEDIA_ERROR_MALFORMED;
}
@@ -4485,9 +4479,6 @@
delete[] mSrcBuffer;
mSrcBuffer = NULL;
- delete mGroup;
- mGroup = NULL;
-
mStarted = false;
mCurrentSampleIndex = 0;
@@ -5184,12 +5175,12 @@
}
media_status_t MPEG4Source::read(
- MediaBufferBase **out, const ReadOptions *options) {
+ MediaBufferHelperV3 **out, const ReadOptions *options) {
Mutex::Autolock autoLock(mLock);
CHECK(mStarted);
- if (options != nullptr && options->getNonBlocking() && !mGroup->has_buffers()) {
+ if (options != nullptr && options->getNonBlocking() && !mBufferGroup->has_buffers()) {
*out = nullptr;
return AMEDIA_ERROR_WOULD_BLOCK;
}
@@ -5338,7 +5329,7 @@
return AMEDIA_ERROR_UNKNOWN;
}
- err = mGroup->acquire_buffer(&mBuffer);
+ err = mBufferGroup->acquire_buffer(&mBuffer);
if (err != OK) {
CHECK(mBuffer == NULL);
@@ -5352,7 +5343,7 @@
}
}
- if ((!mIsAVC && !mIsHEVC && !mIsAC4)) {
+ if (!mIsAVC && !mIsHEVC && !mIsAC4) {
if (newBuffer) {
if (mIsPcm) {
// The twos' PCM block reader assumes that all samples has the same size.
@@ -5377,9 +5368,11 @@
return AMEDIA_ERROR_IO;
}
- mBuffer->meta_data().clear();
- mBuffer->meta_data().setInt64(kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
- mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+ AMediaFormat *meta = mBuffer->meta_data();
+ AMediaFormat_clear(meta);
+ AMediaFormat_setInt64(
+ meta, AMEDIAFORMAT_KEY_TIME_US, ((int64_t)cts * 1000000) / mTimescale);
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
int32_t byteOrder;
AMediaFormat_getInt32(mFormat,
@@ -5410,77 +5403,31 @@
CHECK(mBuffer != NULL);
mBuffer->set_range(0, size);
- mBuffer->meta_data().clear();
- mBuffer->meta_data().setInt64(
- kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
- mBuffer->meta_data().setInt64(
- kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
+ AMediaFormat *meta = mBuffer->meta_data();
+ AMediaFormat_clear(meta);
+ AMediaFormat_setInt64(
+ meta, AMEDIAFORMAT_KEY_TIME_US, ((int64_t)cts * 1000000) / mTimescale);
+ AMediaFormat_setInt64(
+ meta, AMEDIAFORMAT_KEY_DURATION, ((int64_t)stts * 1000000) / mTimescale);
if (targetSampleTimeUs >= 0) {
- mBuffer->meta_data().setInt64(
- kKeyTargetTime, targetSampleTimeUs);
+ AMediaFormat_setInt64(
+ meta, AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
}
if (isSyncSample) {
- mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
}
++mCurrentSampleIndex;
}
}
- if (!mIsAVC && !mIsHEVC && !mIsAC4) {
- *out = mBuffer;
- mBuffer = NULL;
-
- return AMEDIA_OK;
- }
-
- if (mIsAC4) {
- mBuffer->release();
- mBuffer = NULL;
-
- return AMEDIA_ERROR_IO;
- }
-
- // Each NAL unit is split up into its constituent fragments and
- // each one of them returned in its own buffer.
-
- CHECK(mBuffer->range_length() >= mNALLengthSize);
-
- const uint8_t *src =
- (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
-
- size_t nal_size = parseNALSize(src);
- if (mNALLengthSize > SIZE_MAX - nal_size) {
- ALOGE("b/24441553, b/24445122");
- }
- if (mBuffer->range_length() - mNALLengthSize < nal_size) {
- ALOGE("incomplete NAL unit.");
-
- mBuffer->release();
- mBuffer = NULL;
-
- return AMEDIA_ERROR_MALFORMED;
- }
-
- MediaBufferBase *clone = mBuffer->clone();
- CHECK(clone != NULL);
- clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
-
- CHECK(mBuffer != NULL);
- mBuffer->set_range(
- mBuffer->range_offset() + mNALLengthSize + nal_size,
- mBuffer->range_length() - mNALLengthSize - nal_size);
-
- if (mBuffer->range_length() == 0) {
- mBuffer->release();
- mBuffer = NULL;
- }
-
- *out = clone;
+ *out = mBuffer;
+ mBuffer = NULL;
return AMEDIA_OK;
+
} else if (mIsAC4) {
CHECK(mBuffer != NULL);
// Make sure there is enough space to write the sync header and the raw frame
@@ -5512,19 +5459,20 @@
}
mBuffer->set_range(0, dstOffset + size);
- mBuffer->meta_data().clear();
- mBuffer->meta_data().setInt64(
- kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
- mBuffer->meta_data().setInt64(
- kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
+ AMediaFormat *meta = mBuffer->meta_data();
+ AMediaFormat_clear(meta);
+ AMediaFormat_setInt64(
+ meta, AMEDIAFORMAT_KEY_TIME_US, ((int64_t)cts * 1000000) / mTimescale);
+ AMediaFormat_setInt64(
+ meta, AMEDIAFORMAT_KEY_DURATION, ((int64_t)stts * 1000000) / mTimescale);
if (targetSampleTimeUs >= 0) {
- mBuffer->meta_data().setInt64(
- kKeyTargetTime, targetSampleTimeUs);
+ AMediaFormat_setInt64(
+ meta, AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
}
if (isSyncSample) {
- mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
}
++mCurrentSampleIndex;
@@ -5592,31 +5540,32 @@
CHECK(mBuffer != NULL);
mBuffer->set_range(0, dstOffset);
- mBuffer->meta_data().clear();
- mBuffer->meta_data().setInt64(
- kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
- mBuffer->meta_data().setInt64(
- kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
+ AMediaFormat *meta = mBuffer->meta_data();
+ AMediaFormat_clear(meta);
+ AMediaFormat_setInt64(
+ meta, AMEDIAFORMAT_KEY_TIME_US, ((int64_t)cts * 1000000) / mTimescale);
+ AMediaFormat_setInt64(
+ meta, AMEDIAFORMAT_KEY_DURATION, ((int64_t)stts * 1000000) / mTimescale);
if (targetSampleTimeUs >= 0) {
- mBuffer->meta_data().setInt64(
- kKeyTargetTime, targetSampleTimeUs);
+ AMediaFormat_setInt64(
+ meta, AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
}
if (mIsAVC) {
uint32_t layerId = FindAVCLayerId(
(const uint8_t *)mBuffer->data(), mBuffer->range_length());
- mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID, layerId);
} else if (mIsHEVC) {
int32_t layerId = parseHEVCLayerId(
(const uint8_t *)mBuffer->data(), mBuffer->range_length());
if (layerId >= 0) {
- mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID, layerId);
}
}
if (isSyncSample) {
- mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
}
++mCurrentSampleIndex;
@@ -5629,7 +5578,7 @@
}
media_status_t MPEG4Source::fragmentedRead(
- MediaBufferBase **out, const ReadOptions *options) {
+ MediaBufferHelperV3 **out, const ReadOptions *options) {
ALOGV("MPEG4Source::fragmentedRead");
@@ -5732,7 +5681,7 @@
mCurrentTime += smpl->duration;
isSyncSample = (mCurrentSampleIndex == 0);
- status_t err = mGroup->acquire_buffer(&mBuffer);
+ status_t err = mBufferGroup->acquire_buffer(&mBuffer);
if (err != OK) {
CHECK(mBuffer == NULL);
@@ -5748,19 +5697,21 @@
}
const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
- MetaDataBase &bufmeta = mBuffer->meta_data();
- bufmeta.clear();
+ AMediaFormat *bufmeta = mBuffer->meta_data();
+ AMediaFormat_clear(bufmeta);
if (smpl->encryptedsizes.size()) {
// store clear/encrypted lengths in metadata
- bufmeta.setData(kKeyPlainSizes, 0,
+ AMediaFormat_setBuffer(bufmeta, AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES,
smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
- bufmeta.setData(kKeyEncryptedSizes, 0,
+ AMediaFormat_setBuffer(bufmeta, AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES,
smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
- bufmeta.setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
- bufmeta.setInt32(kKeyCryptoMode, mCryptoMode);
- bufmeta.setData(kKeyCryptoKey, 0, mCryptoKey, 16);
- bufmeta.setInt32(kKeyEncryptedByteBlock, mDefaultEncryptedByteBlock);
- bufmeta.setInt32(kKeySkipByteBlock, mDefaultSkipByteBlock);
+ AMediaFormat_setInt32(bufmeta, AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE, mDefaultIVSize);
+ AMediaFormat_setInt32(bufmeta, AMEDIAFORMAT_KEY_CRYPTO_MODE, mCryptoMode);
+ AMediaFormat_setBuffer(bufmeta, AMEDIAFORMAT_KEY_CRYPTO_KEY, mCryptoKey, 16);
+ AMediaFormat_setInt32(bufmeta,
+ AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK, mDefaultEncryptedByteBlock);
+ AMediaFormat_setInt32(bufmeta,
+ AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK, mDefaultSkipByteBlock);
void *iv = NULL;
size_t ivlength = 0;
@@ -5769,11 +5720,10 @@
iv = (void *) smpl->iv;
ivlength = 16; // use 16 or the actual size?
}
- bufmeta.setData(kKeyCryptoIV, 0, iv, ivlength);
-
+ AMediaFormat_setBuffer(bufmeta, AMEDIAFORMAT_KEY_CRYPTO_IV, iv, ivlength);
}
- if ((!mIsAVC && !mIsHEVC)) {
+ if (!mIsAVC && !mIsHEVC) {
if (newBuffer) {
if (!isInRange((size_t)0u, mBuffer->size(), size)) {
mBuffer->release();
@@ -5796,81 +5746,39 @@
CHECK(mBuffer != NULL);
mBuffer->set_range(0, size);
- mBuffer->meta_data().setInt64(
- kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
- mBuffer->meta_data().setInt64(
- kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
+ AMediaFormat_setInt64(bufmeta,
+ AMEDIAFORMAT_KEY_TIME_US, ((int64_t)cts * 1000000) / mTimescale);
+ AMediaFormat_setInt64(bufmeta,
+ AMEDIAFORMAT_KEY_DURATION, ((int64_t)smpl->duration * 1000000) / mTimescale);
if (targetSampleTimeUs >= 0) {
- mBuffer->meta_data().setInt64(
- kKeyTargetTime, targetSampleTimeUs);
+ AMediaFormat_setInt64(bufmeta, AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
}
if (mIsAVC) {
uint32_t layerId = FindAVCLayerId(
(const uint8_t *)mBuffer->data(), mBuffer->range_length());
- mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
+ AMediaFormat_setInt32(bufmeta, AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID, layerId);
} else if (mIsHEVC) {
int32_t layerId = parseHEVCLayerId(
(const uint8_t *)mBuffer->data(), mBuffer->range_length());
if (layerId >= 0) {
- mBuffer->meta_data().setInt32(kKeyTemporalLayerId, layerId);
+ AMediaFormat_setInt32(bufmeta, AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID, layerId);
}
}
if (isSyncSample) {
- mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+ AMediaFormat_setInt32(bufmeta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
}
++mCurrentSampleIndex;
}
- if (!mIsAVC && !mIsHEVC) {
- *out = mBuffer;
- mBuffer = NULL;
-
- return AMEDIA_OK;
- }
-
- // Each NAL unit is split up into its constituent fragments and
- // each one of them returned in its own buffer.
-
- CHECK(mBuffer->range_length() >= mNALLengthSize);
-
- const uint8_t *src =
- (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
-
- size_t nal_size = parseNALSize(src);
- if (mNALLengthSize > SIZE_MAX - nal_size) {
- ALOGE("b/24441553, b/24445122");
- }
-
- if (mBuffer->range_length() - mNALLengthSize < nal_size) {
- ALOGE("incomplete NAL unit.");
-
- mBuffer->release();
- mBuffer = NULL;
-
- return AMEDIA_ERROR_MALFORMED;
- }
-
- MediaBufferBase *clone = mBuffer->clone();
- CHECK(clone != NULL);
- clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
-
- CHECK(mBuffer != NULL);
- mBuffer->set_range(
- mBuffer->range_offset() + mNALLengthSize + nal_size,
- mBuffer->range_length() - mNALLengthSize - nal_size);
-
- if (mBuffer->range_length() == 0) {
- mBuffer->release();
- mBuffer = NULL;
- }
-
- *out = clone;
+ *out = mBuffer;
+ mBuffer = NULL;
return AMEDIA_OK;
+
} else {
ALOGV("whole NAL");
// Whole NAL units are returned but each fragment is prefixed by
@@ -5952,18 +5860,18 @@
CHECK(mBuffer != NULL);
mBuffer->set_range(0, dstOffset);
- mBuffer->meta_data().setInt64(
- kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
- mBuffer->meta_data().setInt64(
- kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
+ AMediaFormat *bufmeta = mBuffer->meta_data();
+ AMediaFormat_setInt64(bufmeta,
+ AMEDIAFORMAT_KEY_TIME_US, ((int64_t)cts * 1000000) / mTimescale);
+ AMediaFormat_setInt64(bufmeta,
+ AMEDIAFORMAT_KEY_DURATION, ((int64_t)smpl->duration * 1000000) / mTimescale);
if (targetSampleTimeUs >= 0) {
- mBuffer->meta_data().setInt64(
- kKeyTargetTime, targetSampleTimeUs);
+ AMediaFormat_setInt64(bufmeta, AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
}
if (isSyncSample) {
- mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+ AMediaFormat_setInt32(bufmeta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
}
++mCurrentSampleIndex;
@@ -6163,11 +6071,11 @@
return true;
}
-static CMediaExtractorV2* CreateExtractor(CDataSource *source, void *) {
- return wrapV2(new MPEG4Extractor(new DataSourceHelper(source)));
+static CMediaExtractorV3* CreateExtractor(CDataSource *source, void *) {
+ return wrapV3(new MPEG4Extractor(new DataSourceHelper(source)));
}
-static CreatorFuncV2 Sniff(
+static CreatorFuncV3 Sniff(
CDataSource *source, float *confidence, void **,
FreeMetaFunc *) {
DataSourceHelper helper(source);
@@ -6188,11 +6096,11 @@
__attribute__ ((visibility ("default")))
ExtractorDef GETEXTRACTORDEF() {
return {
- EXTRACTORDEF_VERSION_CURRENT,
+ EXTRACTORDEF_VERSION_CURRENT + 1,
UUID("27575c67-4417-4c54-8d3d-8e626985a164"),
2, // version
"MP4 Extractor",
- { .v2 = Sniff }
+ { .v3 = Sniff }
};
}
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index 56b641d..a9a4635 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -53,12 +53,12 @@
uint32_t default_sample_flags;
};
-class MPEG4Extractor : public MediaExtractorPluginHelperV2 {
+class MPEG4Extractor : public MediaExtractorPluginHelperV3 {
public:
explicit MPEG4Extractor(DataSourceHelper *source, const char *mime = NULL);
virtual size_t countTracks();
- virtual MediaTrackHelperV2 *getTrack(size_t index);
+ virtual MediaTrackHelperV3 *getTrack(size_t index);
virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
virtual media_status_t getMetaData(AMediaFormat *meta);
diff --git a/media/libaaudio/tests/Android.bp b/media/libaaudio/tests/Android.bp
index 319467e..cb243a0 100644
--- a/media/libaaudio/tests/Android.bp
+++ b/media/libaaudio/tests/Android.bp
@@ -184,3 +184,15 @@
"libutils",
],
}
+
+cc_test {
+ name: "test_return_stop",
+ defaults: ["libaaudio_tests_defaults"],
+ srcs: ["test_return_stop.cpp"],
+ shared_libs: [
+ "libaaudio",
+ "libbinder",
+ "libcutils",
+ "libutils",
+ ],
+}
diff --git a/media/libaaudio/tests/test_return_stop.cpp b/media/libaaudio/tests/test_return_stop.cpp
new file mode 100644
index 0000000..f34c3c8
--- /dev/null
+++ b/media/libaaudio/tests/test_return_stop.cpp
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+/**
+ * Return stop from the callback.
+ * Expect the callback to cease.
+ * Check the logcat for bad behavior.
+ */
+
+#include <stdio.h>
+#include <thread>
+#include <unistd.h>
+
+#include <aaudio/AAudio.h>
+
+#define DEFAULT_TIMEOUT_NANOS ((int64_t)1000000000)
+#define STOP_AT_MSEC 1000
+#define LOOP_DURATION_MSEC 4000
+#define SLEEP_DURATION_MSEC 200
+
+static void s_myErrorCallbackProc(
+ AAudioStream *stream,
+ void *userData,
+ aaudio_result_t error);
+
+struct AudioEngine {
+ AAudioStreamBuilder *builder = nullptr;
+ AAudioStream *stream = nullptr;
+ std::thread *thread = nullptr;
+ int32_t stopAtFrame = 0;
+ bool stopped = false;
+ // These counters are read and written by the callback and the main thread.
+ std::atomic<int32_t> framesRead{};
+ std::atomic<int32_t> startingFramesRead{};
+ std::atomic<int32_t> framesCalled{};
+ std::atomic<int32_t> callbackCount{};
+ std::atomic<int32_t> callbackCountAfterStop{};
+
+ void reset() {
+ framesRead.store(0);
+ startingFramesRead.store(0);
+ framesCalled.store(0);
+ callbackCount.store(0);
+ callbackCountAfterStop.store(0);
+ stopped = false;
+ }
+};
+
+// Callback function that fills the audio output buffer.
+static aaudio_data_callback_result_t s_myDataCallbackProc(
+ AAudioStream *stream,
+ void *userData,
+ void *audioData,
+ int32_t numFrames
+) {
+ (void) audioData;
+ (void) numFrames;
+ AudioEngine *engine = (struct AudioEngine *)userData;
+ engine->callbackCount++;
+ if (engine->stopped) {
+ engine->callbackCountAfterStop++;
+ }
+
+ engine->framesRead = (int32_t)AAudioStream_getFramesRead(stream);
+ if (engine->startingFramesRead == 0) {
+ engine->startingFramesRead.store(engine->framesRead.load());
+ }
+ engine->framesCalled += numFrames;
+ if (engine->framesCalled >= engine->stopAtFrame) {
+ engine->stopped = true;
+ return AAUDIO_CALLBACK_RESULT_STOP;
+ } else {
+ return AAUDIO_CALLBACK_RESULT_CONTINUE;
+ }
+}
+
+static aaudio_result_t s_OpenAudioStream(struct AudioEngine *engine,
+ aaudio_direction_t direction,
+ aaudio_sharing_mode_t sharingMode,
+ aaudio_performance_mode_t perfMode) {
+ // Use an AAudioStreamBuilder to contain requested parameters.
+ aaudio_result_t result = AAudio_createStreamBuilder(&engine->builder);
+ if (result != AAUDIO_OK) {
+ printf("AAudio_createStreamBuilder returned %s",
+ AAudio_convertResultToText(result));
+ return result;
+ }
+
+ // Request stream properties.
+ AAudioStreamBuilder_setFormat(engine->builder, AAUDIO_FORMAT_PCM_FLOAT);
+ AAudioStreamBuilder_setPerformanceMode(engine->builder, perfMode);
+ AAudioStreamBuilder_setSharingMode(engine->builder, sharingMode);
+ AAudioStreamBuilder_setDirection(engine->builder, direction);
+ AAudioStreamBuilder_setDataCallback(engine->builder, s_myDataCallbackProc, engine);
+ AAudioStreamBuilder_setErrorCallback(engine->builder, s_myErrorCallbackProc, engine);
+
+ // Create an AAudioStream using the Builder.
+ result = AAudioStreamBuilder_openStream(engine->builder, &engine->stream);
+ if (result != AAUDIO_OK) {
+ printf("AAudioStreamBuilder_openStream returned %s",
+ AAudio_convertResultToText(result));
+ return result;
+ }
+
+ return result;
+}
+
+static aaudio_result_t s_CloseAudioStream(struct AudioEngine *engine) {
+ aaudio_result_t result = AAUDIO_OK;
+ if (engine->stream != nullptr) {
+ result = AAudioStream_close(engine->stream);
+ if (result != AAUDIO_OK) {
+ printf("AAudioStream_close returned %s\n",
+ AAudio_convertResultToText(result));
+ }
+ engine->stream = nullptr;
+ }
+ AAudioStreamBuilder_delete(engine->builder);
+ engine->builder = nullptr;
+ return result;
+}
+
+static void s_myErrorCallbackProc(
+ AAudioStream *stream __unused,
+ void *userData __unused,
+ aaudio_result_t error) {
+ printf("%s() - error = %d\n", __func__, error);
+}
+
+void usage() {
+ printf("test_return_stop [-i] [-x] [-n] [-c]\n");
+ printf(" -i direction INPUT, otherwise OUTPUT\n");
+ printf(" -x sharing mode EXCLUSIVE, otherwise SHARED\n");
+ printf(" -n performance mode NONE, otherwise LOW_LATENCY\n");
+ printf(" -c always return CONTINUE from callback, not STOP\n");
+}
+
+int main(int argc, char **argv) {
+ (void) argc;
+ (void) argv;
+ struct AudioEngine engine;
+ aaudio_sharing_mode_t sharingMode = AAUDIO_SHARING_MODE_SHARED;
+ aaudio_performance_mode_t perfMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
+ aaudio_direction_t direction = AAUDIO_DIRECTION_OUTPUT;
+ aaudio_result_t result = AAUDIO_OK;
+ bool alwaysContinue = false;
+ int errorCount = 0;
+ int callbackResult = EXIT_SUCCESS;
+
+ // Make printf print immediately so that debug info is not stuck
+ // in a buffer if we hang or crash.
+ setvbuf(stdout, nullptr, _IONBF, (size_t) 0);
+
+ printf("Test Return Stop V1.0\n");
+ printf("Wait for a few seconds.\n");
+ printf("You should see callbackCount and framesRead stop advancing\n");
+ printf("when callbackCount reaches %d msec\n", STOP_AT_MSEC);
+ printf("\n");
+
+ for (int i = 1; i < argc; i++) {
+ const char *arg = argv[i];
+ if (arg[0] == '-') {
+ char option = arg[1];
+ switch (option) {
+ case 'c':
+ alwaysContinue = true;
+ break;
+ case 'i':
+ direction = AAUDIO_DIRECTION_INPUT;
+ break;
+ case 'n':
+ perfMode = AAUDIO_PERFORMANCE_MODE_NONE;
+ break;
+ case 'x':
+ sharingMode = AAUDIO_SHARING_MODE_EXCLUSIVE;
+ break;
+ default:
+ usage();
+ exit(EXIT_FAILURE);
+ break;
+ }
+ } else {
+ usage();
+ exit(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ result = s_OpenAudioStream(&engine, direction, sharingMode, perfMode);
+ if (result != AAUDIO_OK) {
+ printf("s_OpenAudioStream returned %s",
+ AAudio_convertResultToText(result));
+ errorCount++;
+ }
+
+ int32_t framesPerBurst = AAudioStream_getFramesPerBurst(engine.stream);
+ // Check to see what kind of stream we actually got.
+ int32_t deviceId = AAudioStream_getDeviceId(engine.stream);
+ aaudio_performance_mode_t actualPerfMode = AAudioStream_getPerformanceMode(engine.stream);
+ printf("-------- opened: deviceId = %3d, framesPerBurst = %3d, perfMode = %d\n",
+ deviceId, framesPerBurst, actualPerfMode);
+
+ // Calculate how many callbacks needed.
+ if (alwaysContinue) {
+ engine.stopAtFrame = INT32_MAX;
+ } else {
+ int32_t sampleRate = AAudioStream_getSampleRate(engine.stream);
+ engine.stopAtFrame = STOP_AT_MSEC * sampleRate / 1000;
+ }
+
+ for (int loops = 0; loops < 2 && result == AAUDIO_OK; loops++) {
+ engine.reset();
+
+ // Start stream.
+ result = AAudioStream_requestStart(engine.stream);
+ printf("AAudioStream_requestStart() returned %d >>>>>>>>>>>>>>>>>>>>>>\n", result);
+ if (result != AAUDIO_OK) {
+ printf("ERROR - AAudioStream_requestStart returned %s",
+ AAudio_convertResultToText(result));
+ errorCount++;
+ break;
+ }
+
+ if (result == AAUDIO_OK) {
+ const int watchLoops = LOOP_DURATION_MSEC / SLEEP_DURATION_MSEC;
+ for (int i = watchLoops; i > 0; i--) {
+ printf("playing silence #%02d, framesRead = %7d, framesWritten = %7d,"
+ " framesCalled = %6d, callbackCount = %4d\n",
+ i,
+ (int32_t) AAudioStream_getFramesRead(engine.stream),
+ (int32_t) AAudioStream_getFramesWritten(engine.stream),
+ engine.framesCalled.load(),
+ engine.callbackCount.load()
+ );
+ usleep(SLEEP_DURATION_MSEC * 1000);
+ }
+ }
+
+ if (engine.stopAtFrame != INT32_MAX) {
+ callbackResult = (engine.callbackCountAfterStop == 0) ? EXIT_SUCCESS
+ : EXIT_FAILURE;
+ if (callbackResult) {
+ printf("ERROR - Callback count after STOP = %d\n",
+ engine.callbackCountAfterStop.load());
+ errorCount++;
+ }
+ }
+
+ if (engine.startingFramesRead.load() == engine.framesRead.load()) {
+ printf("ERROR - framesRead did not advance across callbacks\n");
+ errorCount++;
+ }
+
+ result = AAudioStream_requestStop(engine.stream);
+ printf("AAudioStream_requestStop() returned %d <<<<<<<<<<<<<<<<<<<<<\n", result);
+ if (result != AAUDIO_OK) {
+ errorCount++;
+ }
+ usleep(SLEEP_DURATION_MSEC * 1000);
+ printf("getFramesRead() = %d, getFramesWritten() = %d\n",
+ (int32_t) AAudioStream_getFramesRead(engine.stream),
+ (int32_t) AAudioStream_getFramesWritten(engine.stream));
+ }
+
+ s_CloseAudioStream(&engine);
+
+ printf("aaudio result = %d = %s\n", result, AAudio_convertResultToText(result));
+ printf("test %s\n", errorCount ? "FAILED" : "PASSED");
+
+ return errorCount ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/media/libaudioclient/include/media/AudioMixer.h b/media/libaudioclient/include/media/AudioMixer.h
index aa036a8..3ae7104 100644
--- a/media/libaudioclient/include/media/AudioMixer.h
+++ b/media/libaudioclient/include/media/AudioMixer.h
@@ -78,6 +78,8 @@
DOWNMIX_TYPE = 0X4004,
MIXER_FORMAT = 0x4005, // AUDIO_FORMAT_PCM_(FLOAT|16_BIT)
MIXER_CHANNEL_MASK = 0x4006, // Channel mask for mixer output
+ // for haptic
+ HAPTIC_ENABLED = 0x4007, // Set haptic data from this track should be played or not.
// for target RESAMPLE
SAMPLE_RATE = 0x4100, // Configure sample rate conversion on this track name;
// parameter 'value' is the new sample rate in Hz.
@@ -137,6 +139,13 @@
void setBufferProvider(int name, AudioBufferProvider* bufferProvider);
void process() {
+ for (const auto &pair : mTracks) {
+ // Clear contracted buffer before processing if contracted channels are saved
+ const std::shared_ptr<Track> &t = pair.second;
+ if (t->mKeepContractedChannels) {
+ t->clearContractedBuffer();
+ }
+ }
(this->*mHook)();
}
@@ -235,6 +244,8 @@
mPostDownmixReformatBufferProvider.reset(nullptr);
mDownmixerBufferProvider.reset(nullptr);
mReformatBufferProvider.reset(nullptr);
+ mAdjustChannelsNonDestructiveBufferProvider.reset(nullptr);
+ mAdjustChannelsBufferProvider.reset(nullptr);
}
bool needsRamp() { return (volumeInc[0] | volumeInc[1] | auxInc) != 0; }
@@ -249,6 +260,11 @@
void unprepareForDownmix();
status_t prepareForReformat();
void unprepareForReformat();
+ status_t prepareForAdjustChannels();
+ void unprepareForAdjustChannels();
+ status_t prepareForAdjustChannelsNonDestructive(size_t frames);
+ void unprepareForAdjustChannelsNonDestructive();
+ void clearContractedBuffer();
bool setPlaybackRate(const AudioPlaybackRate &playbackRate);
void reconfigureBufferProviders();
@@ -302,17 +318,22 @@
* all pre-mixer track buffer conversions outside the AudioMixer class.
*
* 1) mInputBufferProvider: The AudioTrack buffer provider.
- * 2) mReformatBufferProvider: If not NULL, performs the audio reformat to
+ * 2) mAdjustChannelsBufferProvider: Expend or contracts data
+ * 3) mAdjustChannelsNonDestructiveBufferProvider: Non-destructively adjust sample data
+ * 4) mReformatBufferProvider: If not NULL, performs the audio reformat to
* match either mMixerInFormat or mDownmixRequiresFormat, if the downmixer
* requires reformat. For example, it may convert floating point input to
* PCM_16_bit if that's required by the downmixer.
- * 3) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match
+ * 5) mDownmixerBufferProvider: If not NULL, performs the channel remixing to match
* the number of channels required by the mixer sink.
- * 4) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from
+ * 6) mPostDownmixReformatBufferProvider: If not NULL, performs reformatting from
* the downmixer requirements to the mixer engine input requirements.
- * 5) mTimestretchBufferProvider: Adds timestretching for playback rate
+ * 7) mTimestretchBufferProvider: Adds timestretching for playback rate
*/
AudioBufferProvider* mInputBufferProvider; // externally provided buffer provider.
+ // TODO: combine AdjustChannelsBufferProvider and AdjustChannelsNonDestructiveBufferProvider
+ std::unique_ptr<PassthruBufferProvider> mAdjustChannelsBufferProvider;
+ std::unique_ptr<PassthruBufferProvider> mAdjustChannelsNonDestructiveBufferProvider;
std::unique_ptr<PassthruBufferProvider> mReformatBufferProvider;
std::unique_ptr<PassthruBufferProvider> mDownmixerBufferProvider;
std::unique_ptr<PassthruBufferProvider> mPostDownmixReformatBufferProvider;
@@ -341,6 +362,18 @@
AudioPlaybackRate mPlaybackRate;
+ // Haptic
+ bool mHapticPlaybackEnabled;
+ audio_channel_mask_t mHapticChannelMask;
+ uint32_t mHapticChannelCount;
+ audio_channel_mask_t mMixerHapticChannelMask;
+ uint32_t mMixerHapticChannelCount;
+ uint32_t mAdjustInChannelCount;
+ uint32_t mAdjustOutChannelCount;
+ uint32_t mAdjustNonDestructiveInChannelCount;
+ uint32_t mAdjustNonDestructiveOutChannelCount;
+ bool mKeepContractedChannels;
+
private:
// hooks
void track__genericResample(int32_t* out, size_t numFrames, int32_t* temp, int32_t* aux);
diff --git a/media/libaudiohal/EffectsFactoryHalInterface.cpp b/media/libaudiohal/EffectsFactoryHalInterface.cpp
index e21c235..bd3ef61 100644
--- a/media/libaudiohal/EffectsFactoryHalInterface.cpp
+++ b/media/libaudiohal/EffectsFactoryHalInterface.cpp
@@ -25,13 +25,13 @@
// static
sp<EffectsFactoryHalInterface> EffectsFactoryHalInterface::create() {
if (hardware::audio::effect::V5_0::IEffectsFactory::getService() != nullptr) {
- return V5_0::createEffectsFactoryHal();
+ return effect::V5_0::createEffectsFactoryHal();
}
if (hardware::audio::effect::V4_0::IEffectsFactory::getService() != nullptr) {
- return V4_0::createEffectsFactoryHal();
+ return effect::V4_0::createEffectsFactoryHal();
}
if (hardware::audio::effect::V2_0::IEffectsFactory::getService() != nullptr) {
- return V2_0::createEffectsFactoryHal();
+ return effect::V2_0::createEffectsFactoryHal();
}
return nullptr;
}
diff --git a/media/libaudiohal/impl/DeviceHalHidl.cpp b/media/libaudiohal/impl/DeviceHalHidl.cpp
index b3ff757..8537608 100644
--- a/media/libaudiohal/impl/DeviceHalHidl.cpp
+++ b/media/libaudiohal/impl/DeviceHalHidl.cpp
@@ -31,33 +31,17 @@
#include "StreamHalHidl.h"
#include "VersionUtils.h"
-using ::android::hardware::audio::common::CPP_VERSION::AudioConfig;
-using ::android::hardware::audio::common::CPP_VERSION::AudioDevice;
-using ::android::hardware::audio::common::CPP_VERSION::AudioInputFlag;
-using ::android::hardware::audio::common::CPP_VERSION::AudioOutputFlag;
-using ::android::hardware::audio::common::CPP_VERSION::AudioPatchHandle;
-using ::android::hardware::audio::common::CPP_VERSION::AudioPort;
-using ::android::hardware::audio::common::CPP_VERSION::AudioPortConfig;
-using ::android::hardware::audio::common::CPP_VERSION::AudioMode;
-using ::android::hardware::audio::common::CPP_VERSION::AudioSource;
-using ::android::hardware::audio::common::CPP_VERSION::HidlUtils;
+using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
using ::android::hardware::audio::common::utils::EnumBitfield;
-using ::android::hardware::audio::CPP_VERSION::DeviceAddress;
-using ::android::hardware::audio::CPP_VERSION::IPrimaryDevice;
-using ::android::hardware::audio::CPP_VERSION::ParameterValue;
-using ::android::hardware::audio::CPP_VERSION::Result;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
-#if MAJOR_VERSION == 4
-using ::android::hardware::audio::CPP_VERSION::SinkMetadata;
-#elif MAJOR_VERSION == 5
-using ::android::hardware::audio::common::CPP_VERSION::SinkMetadata;
-#endif
-
namespace android {
namespace CPP_VERSION {
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::CPP_VERSION;
+
namespace {
status_t deviceAddressFromHal(
diff --git a/media/libaudiohal/impl/EffectBufferHalHidl.cpp b/media/libaudiohal/impl/EffectBufferHalHidl.cpp
index 6ef4e8a..5367972 100644
--- a/media/libaudiohal/impl/EffectBufferHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectBufferHalHidl.cpp
@@ -30,6 +30,7 @@
using ::android::hidl::allocator::V1_0::IAllocator;
namespace android {
+namespace effect {
namespace CPP_VERSION {
// static
@@ -142,5 +143,6 @@
memcpy(mExternalData, mAudioBuffer.raw, size);
}
+} // namespace effect
} // namespace CPP_VERSION
} // namespace android
diff --git a/media/libaudiohal/impl/EffectBufferHalHidl.h b/media/libaudiohal/impl/EffectBufferHalHidl.h
index 0c99a02..4826813 100644
--- a/media/libaudiohal/impl/EffectBufferHalHidl.h
+++ b/media/libaudiohal/impl/EffectBufferHalHidl.h
@@ -23,13 +23,15 @@
#include <media/audiohal/EffectBufferHalInterface.h>
#include <system/audio_effect.h>
-using android::hardware::audio::effect::CPP_VERSION::AudioBuffer;
using android::hardware::hidl_memory;
using android::hidl::memory::V1_0::IMemory;
namespace android {
+namespace effect {
namespace CPP_VERSION {
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
+
class EffectBufferHalHidl : public EffectBufferHalInterface
{
public:
@@ -73,6 +75,7 @@
};
} // namespace CPP_VERSION
+} // namespace effect
} // namespace android
#endif // ANDROID_HARDWARE_EFFECT_BUFFER_HAL_HIDL_H
diff --git a/media/libaudiohal/impl/EffectHalHidl.cpp b/media/libaudiohal/impl/EffectHalHidl.cpp
index 7b867b4..b0597b3 100644
--- a/media/libaudiohal/impl/EffectHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectHalHidl.cpp
@@ -26,22 +26,19 @@
#include "EffectHalHidl.h"
#include "HidlUtils.h"
-using ::android::hardware::audio::effect::CPP_VERSION::AudioBuffer;
-using ::android::hardware::audio::effect::CPP_VERSION::EffectBufferAccess;
-using ::android::hardware::audio::effect::CPP_VERSION::EffectConfigParameters;
-using ::android::hardware::audio::effect::CPP_VERSION::MessageQueueFlagBits;
-using ::android::hardware::audio::effect::CPP_VERSION::Result;
-using ::android::hardware::audio::common::CPP_VERSION::HidlUtils;
-using ::android::hardware::audio::common::CPP_VERSION::AudioChannelMask;
-using ::android::hardware::audio::common::CPP_VERSION::AudioFormat;
+using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
using ::android::hardware::audio::common::utils::EnumBitfield;
using ::android::hardware::hidl_vec;
using ::android::hardware::MQDescriptorSync;
using ::android::hardware::Return;
namespace android {
+namespace effect {
namespace CPP_VERSION {
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
+
EffectHalHidl::EffectHalHidl(const sp<IEffect>& effect, uint64_t effectId)
: mEffect(effect), mEffectId(effectId), mBuffersChanged(true), mEfGroup(nullptr) {
}
@@ -338,4 +335,5 @@
}
} // namespace CPP_VERSION
+} // namespace effect
} // namespace android
diff --git a/media/libaudiohal/impl/EffectHalHidl.h b/media/libaudiohal/impl/EffectHalHidl.h
index cd447ff..9d9f707 100644
--- a/media/libaudiohal/impl/EffectHalHidl.h
+++ b/media/libaudiohal/impl/EffectHalHidl.h
@@ -23,17 +23,15 @@
#include <fmq/MessageQueue.h>
#include <system/audio_effect.h>
-using ::android::hardware::audio::effect::CPP_VERSION::EffectBufferConfig;
-using ::android::hardware::audio::effect::CPP_VERSION::EffectConfig;
-using ::android::hardware::audio::effect::CPP_VERSION::EffectDescriptor;
-using ::android::hardware::audio::effect::CPP_VERSION::IEffect;
-using EffectResult = ::android::hardware::audio::effect::CPP_VERSION::Result;
using ::android::hardware::EventFlag;
using ::android::hardware::MessageQueue;
namespace android {
+namespace effect {
namespace CPP_VERSION {
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
+
class EffectHalHidl : public EffectHalInterface
{
public:
@@ -70,7 +68,7 @@
private:
friend class EffectsFactoryHalHidl;
- typedef MessageQueue<EffectResult, hardware::kSynchronizedReadWrite> StatusMQ;
+ typedef MessageQueue<Result, hardware::kSynchronizedReadWrite> StatusMQ;
sp<IEffect> mEffect;
const uint64_t mEffectId;
@@ -80,7 +78,7 @@
std::unique_ptr<StatusMQ> mStatusMQ;
EventFlag* mEfGroup;
- static status_t analyzeResult(const EffectResult& result);
+ static status_t analyzeResult(const Result& result);
static void effectBufferConfigFromHal(
const buffer_config_t& halConfig, EffectBufferConfig* config);
static void effectBufferConfigToHal(
@@ -105,6 +103,7 @@
};
} // namespace CPP_VERSION
+} // namespace effect
} // namespace android
#endif // ANDROID_HARDWARE_EFFECT_HAL_HIDL_H
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
index b880433..7fd6bde 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.cpp
@@ -25,15 +25,16 @@
#include "EffectHalHidl.h"
#include "HidlUtils.h"
-using ::android::hardware::audio::common::CPP_VERSION::HidlUtils;
-using ::android::hardware::audio::common::CPP_VERSION::Uuid;
-using ::android::hardware::audio::effect::CPP_VERSION::IEffect;
-using ::android::hardware::audio::effect::CPP_VERSION::Result;
+using ::android::hardware::audio::common::CPP_VERSION::implementation::HidlUtils;
using ::android::hardware::Return;
namespace android {
+namespace effect {
namespace CPP_VERSION {
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
+
EffectsFactoryHalHidl::EffectsFactoryHalHidl() : ConversionHelperHidl("EffectsFactory") {
mEffectsFactory = IEffectsFactory::getService();
if (mEffectsFactory == 0) {
@@ -144,6 +145,6 @@
return EffectBufferHalHidl::mirror(external, size, buffer);
}
-
} // namespace CPP_VERSION
+} // namespace effect
} // namespace android
diff --git a/media/libaudiohal/impl/EffectsFactoryHalHidl.h b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
index 7027153..01178ff 100644
--- a/media/libaudiohal/impl/EffectsFactoryHalHidl.h
+++ b/media/libaudiohal/impl/EffectsFactoryHalHidl.h
@@ -24,11 +24,12 @@
#include "ConversionHelperHidl.h"
namespace android {
+namespace effect {
namespace CPP_VERSION {
-using ::android::hardware::audio::effect::CPP_VERSION::EffectDescriptor;
-using ::android::hardware::audio::effect::CPP_VERSION::IEffectsFactory;
using ::android::hardware::hidl_vec;
+using ::android::CPP_VERSION::ConversionHelperHidl;
+using namespace ::android::hardware::audio::effect::CPP_VERSION;
class EffectsFactoryHalHidl : public EffectsFactoryHalInterface, public ConversionHelperHidl
{
@@ -70,6 +71,7 @@
}
} // namespace CPP_VERSION
+} // namespace effect
} // namespace android
#endif // ANDROID_HARDWARE_EFFECTS_FACTORY_HAL_HIDL_H
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 6b59f5c..c12b362 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -28,44 +28,19 @@
#include "StreamHalHidl.h"
#include "VersionUtils.h"
-using ::android::hardware::audio::common::CPP_VERSION::AudioChannelMask;
-using ::android::hardware::audio::common::CPP_VERSION::AudioFormat;
-using ::android::hardware::audio::common::CPP_VERSION::ThreadInfo;
-using ::android::hardware::audio::CPP_VERSION::AudioDrain;
-using ::android::hardware::audio::CPP_VERSION::IStreamOutCallback;
-using ::android::hardware::audio::CPP_VERSION::MessageQueueFlagBits;
-using ::android::hardware::audio::CPP_VERSION::MmapBufferInfo;
-using ::android::hardware::audio::CPP_VERSION::MmapPosition;
-using ::android::hardware::audio::CPP_VERSION::ParameterValue;
-using ::android::hardware::audio::CPP_VERSION::Result;
-using ::android::hardware::audio::CPP_VERSION::TimeSpec;
using ::android::hardware::MQDescriptorSync;
using ::android::hardware::Return;
using ::android::hardware::Void;
-using ReadCommand = ::android::hardware::audio::CPP_VERSION::IStreamIn::ReadCommand;
-
-#if MAJOR_VERSION >= 4
-using ::android::hardware::audio::common::CPP_VERSION::AudioContentType;
-using ::android::hardware::audio::common::CPP_VERSION::AudioSource;
-using ::android::hardware::audio::common::CPP_VERSION::AudioUsage;
-using ::android::hardware::audio::CPP_VERSION::MicrophoneInfo;
-#endif
-
-#if MAJOR_VERSION == 4
-using ::android::hardware::audio::CPP_VERSION::PlaybackTrackMetadata;
-using ::android::hardware::audio::CPP_VERSION::RecordTrackMetadata;
-using HalSinkMetadata = ::android::hardware::audio::CPP_VERSION::SinkMetadata;
-using HalSourceMetadata = ::android::hardware::audio::CPP_VERSION::SourceMetadata;
-#elif MAJOR_VERSION == 5
-using ::android::hardware::audio::common::CPP_VERSION::PlaybackTrackMetadata;
-using ::android::hardware::audio::common::CPP_VERSION::RecordTrackMetadata;
-using HalSinkMetadata = ::android::hardware::audio::common::CPP_VERSION::SinkMetadata;
-using HalSourceMetadata = ::android::hardware::audio::common::CPP_VERSION::SourceMetadata;
-#endif
namespace android {
namespace CPP_VERSION {
+using EffectHalHidl = ::android::effect::CPP_VERSION::EffectHalHidl;
+using ReadCommand = ::android::hardware::audio::CPP_VERSION::IStreamIn::ReadCommand;
+
+using namespace ::android::hardware::audio::common::CPP_VERSION;
+using namespace ::android::hardware::audio::CPP_VERSION;
+
StreamHalHidl::StreamHalHidl(IStream *stream)
: ConversionHelperHidl("Stream"),
mStream(stream),
@@ -609,7 +584,8 @@
}
#if MAJOR_VERSION == 2
-status_t StreamOutHalHidl::updateSourceMetadata(const SourceMetadata& /* sourceMetadata */) {
+status_t StreamOutHalHidl::updateSourceMetadata(
+ const StreamOutHalInterface::SourceMetadata& /* sourceMetadata */) {
// Audio HAL V2.0 does not support propagating source metadata
return INVALID_OPERATION;
}
@@ -623,8 +599,9 @@
return result;
}
-status_t StreamOutHalHidl::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
- HalSourceMetadata halMetadata = {
+status_t StreamOutHalHidl::updateSourceMetadata(
+ const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
+ CPP_VERSION::SourceMetadata halMetadata = {
.tracks = transformToHidlVec(sourceMetadata.tracks,
[](const playback_track_metadata& metadata) -> PlaybackTrackMetadata {
return {
@@ -838,7 +815,8 @@
return INVALID_OPERATION;
}
-status_t StreamInHalHidl::updateSinkMetadata(const SinkMetadata& /* sinkMetadata */) {
+status_t StreamInHalHidl::updateSinkMetadata(
+ const StreamInHalInterface::SinkMetadata& /* sinkMetadata */) {
// Audio HAL V2.0 does not support propagating sink metadata
return INVALID_OPERATION;
}
@@ -862,8 +840,9 @@
return processReturn("getActiveMicrophones", ret, retval);
}
-status_t StreamInHalHidl::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
- HalSinkMetadata halMetadata = {
+status_t StreamInHalHidl::updateSinkMetadata(const
+ StreamInHalInterface::SinkMetadata& sinkMetadata) {
+ CPP_VERSION::SinkMetadata halMetadata = {
.tracks = transformToHidlVec(sinkMetadata.tracks,
[](const record_track_metadata& metadata) -> RecordTrackMetadata {
return {
diff --git a/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h b/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h
index 1d912a0..c7319d0 100644
--- a/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h
+++ b/media/libaudiohal/impl/include/libaudiohal/FactoryHalHidl.h
@@ -25,18 +25,29 @@
namespace android {
+namespace effect {
namespace V2_0 {
sp<EffectsFactoryHalInterface> createEffectsFactoryHal();
-sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
} // namespace V2_0
namespace V4_0 {
sp<EffectsFactoryHalInterface> createEffectsFactoryHal();
-sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
} // namespace V4_0
namespace V5_0 {
sp<EffectsFactoryHalInterface> createEffectsFactoryHal();
+} // namespace V5_0
+} // namespace effect
+
+namespace V2_0 {
+sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
+} // namespace V2_0
+
+namespace V4_0 {
+sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
+} // namespace V4_0
+
+namespace V5_0 {
sp<DevicesFactoryHalInterface> createDevicesFactoryHal();
} // namespace V5_0
diff --git a/media/libaudioprocessing/Android.bp b/media/libaudioprocessing/Android.bp
new file mode 100644
index 0000000..817fb0b
--- /dev/null
+++ b/media/libaudioprocessing/Android.bp
@@ -0,0 +1,54 @@
+cc_defaults {
+ name: "libaudioprocessing_defaults",
+
+ export_include_dirs: ["include"],
+
+ shared_libs: [
+ "libaudiohal",
+ "libaudioutils",
+ "libcutils",
+ "liblog",
+ "libnbaio",
+ "libnblog",
+ "libsonic",
+ "libutils",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+
+ // uncomment to disable NEON on architectures that actually do support NEON, for benchmarking
+ // "-DUSE_NEON=false",
+ ],
+}
+
+cc_library_shared {
+ name: "libaudioprocessing",
+ defaults: ["libaudioprocessing_defaults"],
+
+ srcs: [
+ "BufferProviders.cpp",
+ "RecordBufferConverter.cpp",
+ ],
+ whole_static_libs: ["libaudioprocessing_arm"],
+}
+
+cc_library_static {
+ name: "libaudioprocessing_arm",
+ defaults: ["libaudioprocessing_defaults"],
+
+ srcs: [
+ "AudioMixer.cpp",
+ "AudioResampler.cpp",
+ "AudioResamplerCubic.cpp",
+ "AudioResamplerSinc.cpp",
+ "AudioResamplerDyn.cpp",
+ ],
+
+ arch: {
+ arm: {
+ instruction_set: "arm",
+ },
+ },
+}
diff --git a/media/libaudioprocessing/Android.mk b/media/libaudioprocessing/Android.mk
deleted file mode 100644
index da1ecc2..0000000
--- a/media/libaudioprocessing/Android.mk
+++ /dev/null
@@ -1,40 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- AudioMixer.cpp.arm \
- AudioResampler.cpp.arm \
- AudioResamplerCubic.cpp.arm \
- AudioResamplerSinc.cpp.arm \
- AudioResamplerDyn.cpp.arm \
- BufferProviders.cpp \
- RecordBufferConverter.cpp \
-
-LOCAL_C_INCLUDES := \
- $(TOP) \
- $(call include-path-for, audio-utils) \
- $(LOCAL_PATH)/include \
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-
-LOCAL_SHARED_LIBRARIES := \
- libaudiohal \
- libaudioutils \
- libcutils \
- liblog \
- libnbaio \
- libnblog \
- libsonic \
- libutils \
-
-LOCAL_MODULE := libaudioprocessing
-
-LOCAL_CFLAGS := -Werror -Wall
-
-# uncomment to disable NEON on architectures that actually do support NEON, for benchmarking
-#LOCAL_CFLAGS += -DUSE_NEON=false
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/media/libaudioprocessing/AudioMixer.cpp b/media/libaudioprocessing/AudioMixer.cpp
index af54b21..2567b3b 100644
--- a/media/libaudioprocessing/AudioMixer.cpp
+++ b/media/libaudioprocessing/AudioMixer.cpp
@@ -136,6 +136,9 @@
// no initialization needed
// t->frameCount
+ t->mHapticChannelMask = channelMask & AUDIO_CHANNEL_HAPTIC_ALL;
+ t->mHapticChannelCount = audio_channel_count_from_out_mask(t->mHapticChannelMask);
+ channelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
t->channelCount = audio_channel_count_from_out_mask(channelMask);
t->enabled = false;
ALOGV_IF(audio_channel_mask_get_bits(channelMask) != AUDIO_CHANNEL_OUT_STEREO,
@@ -162,6 +165,15 @@
AUDIO_CHANNEL_REPRESENTATION_POSITION, AUDIO_CHANNEL_OUT_STEREO);
t->mMixerChannelCount = audio_channel_count_from_out_mask(t->mMixerChannelMask);
t->mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT;
+ // haptic
+ t->mHapticPlaybackEnabled = false;
+ t->mMixerHapticChannelMask = AUDIO_CHANNEL_NONE;
+ t->mMixerHapticChannelCount = 0;
+ t->mAdjustInChannelCount = t->channelCount + t->mHapticChannelCount;
+ t->mAdjustOutChannelCount = t->channelCount + t->mMixerHapticChannelCount;
+ t->mAdjustNonDestructiveInChannelCount = t->mAdjustOutChannelCount;
+ t->mAdjustNonDestructiveOutChannelCount = t->channelCount;
+ t->mKeepContractedChannels = false;
// Check the downmixing (or upmixing) requirements.
status_t status = t->prepareForDownmix();
if (status != OK) {
@@ -171,6 +183,8 @@
// prepareForDownmix() may change mDownmixRequiresFormat
ALOGVV("mMixerFormat:%#x mMixerInFormat:%#x\n", t->mMixerFormat, t->mMixerInFormat);
t->prepareForReformat();
+ t->prepareForAdjustChannelsNonDestructive(mFrameCount);
+ t->prepareForAdjustChannels();
mTracks[name] = t;
return OK;
@@ -185,13 +199,20 @@
LOG_ALWAYS_FATAL_IF(!exists(name), "invalid name: %d", name);
const std::shared_ptr<Track> &track = mTracks[name];
- if (trackChannelMask == track->channelMask
- && mixerChannelMask == track->mMixerChannelMask) {
+ if (trackChannelMask == (track->channelMask | track->mHapticChannelMask)
+ && mixerChannelMask == (track->mMixerChannelMask | track->mMixerHapticChannelMask)) {
return false; // no need to change
}
+ const audio_channel_mask_t hapticChannelMask = trackChannelMask & AUDIO_CHANNEL_HAPTIC_ALL;
+ trackChannelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
+ const audio_channel_mask_t mixerHapticChannelMask = mixerChannelMask & AUDIO_CHANNEL_HAPTIC_ALL;
+ mixerChannelMask &= ~AUDIO_CHANNEL_HAPTIC_ALL;
// always recompute for both channel masks even if only one has changed.
const uint32_t trackChannelCount = audio_channel_count_from_out_mask(trackChannelMask);
const uint32_t mixerChannelCount = audio_channel_count_from_out_mask(mixerChannelMask);
+ const uint32_t hapticChannelCount = audio_channel_count_from_out_mask(hapticChannelMask);
+ const uint32_t mixerHapticChannelCount =
+ audio_channel_count_from_out_mask(mixerHapticChannelMask);
ALOG_ASSERT((trackChannelCount <= MAX_NUM_CHANNELS_TO_DOWNMIX)
&& trackChannelCount
@@ -200,6 +221,24 @@
track->channelCount = trackChannelCount;
track->mMixerChannelMask = mixerChannelMask;
track->mMixerChannelCount = mixerChannelCount;
+ track->mHapticChannelMask = hapticChannelMask;
+ track->mHapticChannelCount = hapticChannelCount;
+ track->mMixerHapticChannelMask = mixerHapticChannelMask;
+ track->mMixerHapticChannelCount = mixerHapticChannelCount;
+
+ if (track->mHapticChannelCount > 0) {
+ track->mAdjustInChannelCount = track->channelCount + track->mHapticChannelCount;
+ track->mAdjustOutChannelCount = track->channelCount + track->mMixerHapticChannelCount;
+ track->mAdjustNonDestructiveInChannelCount = track->mAdjustOutChannelCount;
+ track->mAdjustNonDestructiveOutChannelCount = track->channelCount;
+ track->mKeepContractedChannels = track->mHapticPlaybackEnabled;
+ } else {
+ track->mAdjustInChannelCount = 0;
+ track->mAdjustOutChannelCount = 0;
+ track->mAdjustNonDestructiveInChannelCount = 0;
+ track->mAdjustNonDestructiveOutChannelCount = 0;
+ track->mKeepContractedChannels = false;
+ }
// channel masks have changed, does this track need a downmixer?
// update to try using our desired format (if we aren't already using it)
@@ -212,6 +251,9 @@
// do it after downmix since track format may change!
track->prepareForReformat();
+ track->prepareForAdjustChannelsNonDestructive(mFrameCount);
+ track->prepareForAdjustChannels();
+
if (track->mResampler.get() != nullptr) {
// resampler channels may have changed.
const uint32_t resetToSampleRate = track->sampleRate;
@@ -335,10 +377,82 @@
return NO_ERROR;
}
+void AudioMixer::Track::unprepareForAdjustChannels()
+{
+ ALOGV("AUDIOMIXER::unprepareForAdjustChannels");
+ if (mAdjustChannelsBufferProvider.get() != nullptr) {
+ mAdjustChannelsBufferProvider.reset(nullptr);
+ reconfigureBufferProviders();
+ }
+}
+
+status_t AudioMixer::Track::prepareForAdjustChannels()
+{
+ ALOGV("AudioMixer::prepareForAdjustChannels(%p) with inChannelCount: %u, outChannelCount: %u",
+ this, mAdjustInChannelCount, mAdjustOutChannelCount);
+ unprepareForAdjustChannels();
+ if (mAdjustInChannelCount != mAdjustOutChannelCount) {
+ mAdjustChannelsBufferProvider.reset(new AdjustChannelsBufferProvider(
+ mFormat, mAdjustInChannelCount, mAdjustOutChannelCount, kCopyBufferFrameCount));
+ reconfigureBufferProviders();
+ }
+ return NO_ERROR;
+}
+
+void AudioMixer::Track::unprepareForAdjustChannelsNonDestructive()
+{
+ ALOGV("AUDIOMIXER::unprepareForAdjustChannelsNonDestructive");
+ if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
+ mAdjustChannelsNonDestructiveBufferProvider.reset(nullptr);
+ reconfigureBufferProviders();
+ }
+}
+
+status_t AudioMixer::Track::prepareForAdjustChannelsNonDestructive(size_t frames)
+{
+ ALOGV("AudioMixer::prepareForAdjustChannelsNonDestructive(%p) with inChannelCount: %u, "
+ "outChannelCount: %u, keepContractedChannels: %d",
+ this, mAdjustNonDestructiveInChannelCount, mAdjustNonDestructiveOutChannelCount,
+ mKeepContractedChannels);
+ unprepareForAdjustChannelsNonDestructive();
+ if (mAdjustNonDestructiveInChannelCount != mAdjustNonDestructiveOutChannelCount) {
+ uint8_t* buffer = mKeepContractedChannels
+ ? (uint8_t*)mainBuffer + frames * audio_bytes_per_frame(
+ mMixerChannelCount, mMixerFormat)
+ : NULL;
+ mAdjustChannelsNonDestructiveBufferProvider.reset(
+ new AdjustChannelsNonDestructiveBufferProvider(
+ mFormat,
+ mAdjustNonDestructiveInChannelCount,
+ mAdjustNonDestructiveOutChannelCount,
+ mKeepContractedChannels ? mMixerFormat : AUDIO_FORMAT_INVALID,
+ frames,
+ buffer));
+ reconfigureBufferProviders();
+ }
+ return NO_ERROR;
+}
+
+void AudioMixer::Track::clearContractedBuffer()
+{
+ if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
+ static_cast<AdjustChannelsNonDestructiveBufferProvider*>(
+ mAdjustChannelsNonDestructiveBufferProvider.get())->clearContractedFrames();
+ }
+}
+
void AudioMixer::Track::reconfigureBufferProviders()
{
// configure from upstream to downstream buffer providers.
bufferProvider = mInputBufferProvider;
+ if (mAdjustChannelsBufferProvider.get() != nullptr) {
+ mAdjustChannelsBufferProvider->setBufferProvider(bufferProvider);
+ bufferProvider = mAdjustChannelsBufferProvider.get();
+ }
+ if (mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
+ mAdjustChannelsNonDestructiveBufferProvider->setBufferProvider(bufferProvider);
+ bufferProvider = mAdjustChannelsNonDestructiveBufferProvider.get();
+ }
if (mReformatBufferProvider.get() != nullptr) {
mReformatBufferProvider->setBufferProvider(bufferProvider);
bufferProvider = mReformatBufferProvider.get();
@@ -533,7 +647,8 @@
case CHANNEL_MASK: {
const audio_channel_mask_t trackChannelMask =
static_cast<audio_channel_mask_t>(valueInt);
- if (setChannelMasks(name, trackChannelMask, track->mMixerChannelMask)) {
+ if (setChannelMasks(name, trackChannelMask,
+ (track->mMixerChannelMask | track->mMixerHapticChannelMask))) {
ALOGV("setParameter(TRACK, CHANNEL_MASK, %x)", trackChannelMask);
invalidate();
}
@@ -542,6 +657,9 @@
if (track->mainBuffer != valueBuf) {
track->mainBuffer = valueBuf;
ALOGV("setParameter(TRACK, MAIN_BUFFER, %p)", valueBuf);
+ if (track->mKeepContractedChannels) {
+ track->prepareForAdjustChannelsNonDestructive(mFrameCount);
+ }
invalidate();
}
break;
@@ -571,16 +689,29 @@
if (track->mMixerFormat != format) {
track->mMixerFormat = format;
ALOGV("setParameter(TRACK, MIXER_FORMAT, %#x)", format);
+ if (track->mKeepContractedChannels) {
+ track->prepareForAdjustChannelsNonDestructive(mFrameCount);
+ }
}
} break;
case MIXER_CHANNEL_MASK: {
const audio_channel_mask_t mixerChannelMask =
static_cast<audio_channel_mask_t>(valueInt);
- if (setChannelMasks(name, track->channelMask, mixerChannelMask)) {
+ if (setChannelMasks(name, track->channelMask | track->mHapticChannelMask,
+ mixerChannelMask)) {
ALOGV("setParameter(TRACK, MIXER_CHANNEL_MASK, %#x)", mixerChannelMask);
invalidate();
}
} break;
+ case HAPTIC_ENABLED: {
+ const bool hapticPlaybackEnabled = static_cast<bool>(valueInt);
+ if (track->mHapticPlaybackEnabled != hapticPlaybackEnabled) {
+ track->mHapticPlaybackEnabled = hapticPlaybackEnabled;
+ track->mKeepContractedChannels = hapticPlaybackEnabled;
+ track->prepareForAdjustChannelsNonDestructive(mFrameCount);
+ track->prepareForAdjustChannels();
+ }
+ } break;
default:
LOG_ALWAYS_FATAL("setParameter track: bad param %d", param);
}
@@ -823,6 +954,10 @@
track->mDownmixerBufferProvider->reset();
} else if (track->mReformatBufferProvider.get() != nullptr) {
track->mReformatBufferProvider->reset();
+ } else if (track->mAdjustChannelsNonDestructiveBufferProvider.get() != nullptr) {
+ track->mAdjustChannelsNonDestructiveBufferProvider->reset();
+ } else if (track->mAdjustChannelsBufferProvider.get() != nullptr) {
+ track->mAdjustChannelsBufferProvider->reset();
}
track->mInputBufferProvider = bufferProvider;
@@ -1266,8 +1401,8 @@
const std::shared_ptr<Track> &t = mTracks[group[0]];
memset(t->mainBuffer, 0,
- mFrameCount * t->mMixerChannelCount
- * audio_bytes_per_sample(t->mMixerFormat));
+ mFrameCount * audio_bytes_per_frame(
+ t->mMixerChannelCount + t->mMixerHapticChannelCount, t->mMixerFormat));
// now consume data
for (const int name : group) {
diff --git a/media/libaudioprocessing/BufferProviders.cpp b/media/libaudioprocessing/BufferProviders.cpp
index e06a1aa..fe92d43 100644
--- a/media/libaudioprocessing/BufferProviders.cpp
+++ b/media/libaudioprocessing/BufferProviders.cpp
@@ -19,7 +19,8 @@
#include <audio_utils/primitives.h>
#include <audio_utils/format.h>
-#include <external/sonic/sonic.h>
+#include <audio_utils/channels.h>
+#include <sonic.h>
#include <media/audiohal/EffectBufferHalInterface.h>
#include <media/audiohal/EffectHalInterface.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
@@ -630,5 +631,83 @@
}
}
}
+
+AdjustChannelsBufferProvider::AdjustChannelsBufferProvider(audio_format_t format,
+ size_t inChannelCount, size_t outChannelCount, size_t frameCount) :
+ CopyBufferProvider(
+ audio_bytes_per_frame(inChannelCount, format),
+ audio_bytes_per_frame(outChannelCount, format),
+ frameCount),
+ mFormat(format),
+ mInChannelCount(inChannelCount),
+ mOutChannelCount(outChannelCount),
+ mSampleSizeInBytes(audio_bytes_per_sample(format))
+{
+ ALOGV("AdjustBufferProvider(%p)(%#x, %zu, %zu, %zu)",
+ this, format, inChannelCount, outChannelCount, frameCount);
+}
+
+void AdjustChannelsBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
+{
+ adjust_channels(src, mInChannelCount, dst, mOutChannelCount, mSampleSizeInBytes,
+ frames * mInChannelCount * mSampleSizeInBytes);
+}
+
+AdjustChannelsNonDestructiveBufferProvider::AdjustChannelsNonDestructiveBufferProvider(
+ audio_format_t format, size_t inChannelCount, size_t outChannelCount,
+ audio_format_t contractedFormat, size_t contractedFrameCount, void* contractedBuffer) :
+ CopyBufferProvider(
+ audio_bytes_per_frame(inChannelCount, format),
+ audio_bytes_per_frame(outChannelCount, format),
+ 0 /*bufferFrameCount*/),
+ mFormat(format),
+ mInChannelCount(inChannelCount),
+ mOutChannelCount(outChannelCount),
+ mSampleSizeInBytes(audio_bytes_per_sample(format)),
+ mContractedChannelCount(inChannelCount - outChannelCount),
+ mContractedFormat(contractedFormat),
+ mContractedFrameCount(contractedFrameCount),
+ mContractedBuffer(contractedBuffer),
+ mContractedWrittenFrames(0)
+{
+ ALOGV("AdjustChannelsNonDestructiveBufferProvider(%p)(%#x, %zu, %zu, %#x, %p)",
+ this, format, inChannelCount, outChannelCount, contractedFormat, contractedBuffer);
+ if (mContractedFormat != AUDIO_FORMAT_INVALID && mInChannelCount > mOutChannelCount) {
+ mContractedFrameSize = audio_bytes_per_frame(mContractedChannelCount, mContractedFormat);
+ }
+}
+
+status_t AdjustChannelsNonDestructiveBufferProvider::getNextBuffer(
+ AudioBufferProvider::Buffer* pBuffer)
+{
+ const size_t outFramesLeft = mContractedFrameCount - mContractedWrittenFrames;
+ if (outFramesLeft < pBuffer->frameCount) {
+ // Restrict the frame count so that we don't write over the size of the output buffer.
+ pBuffer->frameCount = outFramesLeft;
+ }
+ return CopyBufferProvider::getNextBuffer(pBuffer);
+}
+
+void AdjustChannelsNonDestructiveBufferProvider::copyFrames(
+ void *dst, const void *src, size_t frames)
+{
+ adjust_channels_non_destructive(src, mInChannelCount, dst, mOutChannelCount, mSampleSizeInBytes,
+ frames * mInChannelCount * mSampleSizeInBytes);
+ if (mContractedFormat != AUDIO_FORMAT_INVALID && mContractedBuffer != NULL
+ && mInChannelCount > mOutChannelCount) {
+ const size_t contractedIdx = frames * mOutChannelCount * mSampleSizeInBytes;
+ memcpy_by_audio_format(
+ (uint8_t*)mContractedBuffer + mContractedWrittenFrames * mContractedFrameSize,
+ mContractedFormat, (uint8_t*)dst + contractedIdx, mFormat,
+ mContractedChannelCount * frames);
+ mContractedWrittenFrames += frames;
+ }
+}
+
+void AdjustChannelsNonDestructiveBufferProvider::reset()
+{
+ mContractedWrittenFrames = 0;
+ CopyBufferProvider::reset();
+}
// ----------------------------------------------------------------------------
} // namespace android
diff --git a/media/libaudioprocessing/audio-resampler/Android.bp b/media/libaudioprocessing/audio-resampler/Android.bp
new file mode 100644
index 0000000..dc70310
--- /dev/null
+++ b/media/libaudioprocessing/audio-resampler/Android.bp
@@ -0,0 +1,15 @@
+cc_library_shared {
+ name: "libaudio-resampler",
+
+ srcs: ["AudioResamplerCoefficients.cpp"],
+
+ shared_libs: [
+ "libutils",
+ "liblog",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+}
diff --git a/media/libaudioprocessing/audio-resampler/Android.mk b/media/libaudioprocessing/audio-resampler/Android.mk
deleted file mode 100644
index bb2807c..0000000
--- a/media/libaudioprocessing/audio-resampler/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- AudioResamplerCoefficients.cpp
-
-LOCAL_MODULE := libaudio-resampler
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SHARED_LIBRARIES := libutils liblog
-
-LOCAL_CFLAGS += -Werror -Wall
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/media/libaudioprocessing/tests/Android.bp b/media/libaudioprocessing/tests/Android.bp
new file mode 100644
index 0000000..811c16b
--- /dev/null
+++ b/media/libaudioprocessing/tests/Android.bp
@@ -0,0 +1,51 @@
+// Build the unit tests for libaudioprocessing
+
+cc_defaults {
+ name: "libaudioprocessing_test_defaults",
+
+ header_libs: ["libbase_headers"],
+ shared_libs: [
+ "libaudioutils",
+ "libaudioprocessing",
+ "libcutils",
+ "liblog",
+ "libutils",
+ ],
+
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+}
+
+//
+// resampler unit test
+//
+cc_test {
+ name: "resampler_tests",
+ defaults: ["libaudioprocessing_test_defaults"],
+
+ srcs: ["resampler_tests.cpp"],
+}
+
+//
+// audio mixer test tool
+//
+cc_binary {
+ name: "test-mixer",
+ defaults: ["libaudioprocessing_test_defaults"],
+
+ srcs: ["test-mixer.cpp"],
+ static_libs: ["libsndfile"],
+}
+
+//
+// build audio resampler test tool
+//
+cc_binary {
+ name: "test-resampler",
+ defaults: ["libaudioprocessing_test_defaults"],
+
+ srcs: ["test-resampler.cpp"],
+ static_libs: ["libsndfile"],
+}
diff --git a/media/libaudioprocessing/tests/Android.mk b/media/libaudioprocessing/tests/Android.mk
deleted file mode 100644
index 31ffbdc..0000000
--- a/media/libaudioprocessing/tests/Android.mk
+++ /dev/null
@@ -1,93 +0,0 @@
-# Build the unit tests for libaudioprocessing
-
-LOCAL_PATH := $(call my-dir)
-
-#
-# resampler unit test
-#
-include $(CLEAR_VARS)
-
-LOCAL_SHARED_LIBRARIES := \
- libaudioutils \
- libaudioprocessing \
- libcutils \
- liblog \
- libutils \
-
-LOCAL_C_INCLUDES := \
- $(call include-path-for, audio-utils) \
-
-LOCAL_SRC_FILES := \
- resampler_tests.cpp
-
-LOCAL_HEADER_LIBRARIES := libbase_headers
-
-LOCAL_MODULE := resampler_tests
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_CFLAGS := -Werror -Wall
-
-include $(BUILD_NATIVE_TEST)
-
-#
-# audio mixer test tool
-#
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- test-mixer.cpp \
-
-LOCAL_C_INCLUDES := \
- $(call include-path-for, audio-utils) \
-
-LOCAL_STATIC_LIBRARIES := \
- libsndfile \
-
-LOCAL_SHARED_LIBRARIES := \
- libaudioprocessing \
- libaudioutils \
- libcutils \
- liblog \
- libutils \
-
-LOCAL_HEADER_LIBRARIES := libbase_headers
-
-LOCAL_MODULE := test-mixer
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -Werror -Wall
-
-include $(BUILD_EXECUTABLE)
-
-#
-# build audio resampler test tool
-#
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- test-resampler.cpp \
-
-LOCAL_C_INCLUDES := \
- $(call include-path-for, audio-utils) \
-
-LOCAL_STATIC_LIBRARIES := \
- libsndfile \
-
-LOCAL_SHARED_LIBRARIES := \
- libaudioprocessing \
- libaudioutils \
- libcutils \
- liblog \
- libutils \
-
-LOCAL_HEADER_LIBRARIES := libbase_headers
-
-LOCAL_MODULE := test-resampler
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_CFLAGS := -Werror -Wall
-
-include $(BUILD_EXECUTABLE)
diff --git a/media/libeffects/config/src/EffectsConfig.cpp b/media/libeffects/config/src/EffectsConfig.cpp
index 351b1ee..76b4adc 100644
--- a/media/libeffects/config/src/EffectsConfig.cpp
+++ b/media/libeffects/config/src/EffectsConfig.cpp
@@ -305,7 +305,7 @@
return parseWithPath(path);
}
- for (std::string location : DEFAULT_LOCATIONS) {
+ for (const std::string& location : DEFAULT_LOCATIONS) {
std::string defaultPath = location + '/' + DEFAULT_NAME;
if (access(defaultPath.c_str(), R_OK) != 0) {
continue;
diff --git a/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c
index e3edccc..66d6adb 100644
--- a/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c
+++ b/media/libeffects/lvm/lib/Common/src/Add2_Sat_32x32.c
@@ -43,11 +43,11 @@
{
if(a<0)
{
- c=0x80000000l;
+ c=0x80000000L;
}
else
{
- c=0x7FFFFFFFl;
+ c=0x7FFFFFFFL;
}
}
diff --git a/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.c b/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.c
index 2e20d79..b04e98e 100644
--- a/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.c
+++ b/media/libeffects/lvm/lib/Common/src/DelayAllPass_Sat_32x16To32.c
@@ -53,11 +53,11 @@
{
if(a < 0)
{
- c = 0x80000000l;
+ c = 0x80000000L;
}
else
{
- c = 0x7FFFFFFFl;
+ c = 0x7FFFFFFFL;
}
}
*dst = c;
@@ -72,11 +72,11 @@
{
if(a < 0)
{
- c = 0x80000000l;
+ c = 0x80000000L;
}
else
{
- c = 0x7FFFFFFFl;
+ c = 0x7FFFFFFFL;
}
}
delay[AllPassOffset] = c;
diff --git a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c
index e3fb40d..17fd833 100644
--- a/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c
+++ b/media/libeffects/lvm/lib/Common/src/Mac3s_Sat_32x16.c
@@ -50,11 +50,11 @@
{
if(temp<0)
{
- dOutVal=0x80000000l;
+ dOutVal=0x80000000L;
}
else
{
- dOutVal=0x7FFFFFFFl;
+ dOutVal=0x7FFFFFFFL;
}
}
diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp
index 4984b18..cb8d375 100644
--- a/media/libmedia/Visualizer.cpp
+++ b/media/libmedia/Visualizer.cpp
@@ -56,6 +56,19 @@
setCaptureCallBack(NULL, NULL, 0, 0);
}
+void Visualizer::release()
+{
+ ALOGV("Visualizer::release()");
+ setEnabled(false);
+ Mutex::Autolock _l(mCaptureLock);
+
+ mCaptureThread.clear();
+ mCaptureCallBack = NULL;
+ mCaptureCbkUser = NULL;
+ mCaptureFlags = 0;
+ mCaptureRate = 0;
+}
+
status_t Visualizer::setEnabled(bool enabled)
{
Mutex::Autolock _l(mCaptureLock);
@@ -115,7 +128,7 @@
mCaptureRate = rate;
if (cbk != NULL) {
- mCaptureThread = new CaptureThread(*this, rate, ((flags & CAPTURE_CALL_JAVA) != 0));
+ mCaptureThread = new CaptureThread(this, rate, ((flags & CAPTURE_CALL_JAVA) != 0));
}
ALOGV("setCaptureCallBack() rate: %d thread %p flags 0x%08x",
rate, mCaptureThread.get(), mCaptureFlags);
@@ -402,7 +415,7 @@
//-------------------------------------------------------------------------
-Visualizer::CaptureThread::CaptureThread(Visualizer& receiver, uint32_t captureRate,
+Visualizer::CaptureThread::CaptureThread(Visualizer* receiver, uint32_t captureRate,
bool bCanCallJava)
: Thread(bCanCallJava), mReceiver(receiver)
{
@@ -413,10 +426,14 @@
bool Visualizer::CaptureThread::threadLoop()
{
ALOGV("CaptureThread %p enter", this);
+ sp<Visualizer> receiver = mReceiver.promote();
+ if (receiver == NULL) {
+ return false;
+ }
while (!exitPending())
{
usleep(mSleepTimeUs);
- mReceiver.periodicCapture();
+ receiver->periodicCapture();
}
ALOGV("CaptureThread %p exiting", this);
return false;
diff --git a/media/libmedia/include/media/BufferProviders.h b/media/libmedia/include/media/BufferProviders.h
index 2f1a91c..ea41527 100644
--- a/media/libmedia/include/media/BufferProviders.h
+++ b/media/libmedia/include/media/BufferProviders.h
@@ -218,6 +218,53 @@
bool mAudioPlaybackRateValid; // flag for current parameters validity
};
+// AdjustBufferProvider derives from CopyBufferProvider to adjust sample data.
+// Expands or contracts sample data from one interleaved channel format to another.
+// Expanded channels are filled with zeros and put at the end of each audio frame.
+// Contracted channels are omitted from the end of each audio frame.
+class AdjustChannelsBufferProvider : public CopyBufferProvider {
+public:
+ AdjustChannelsBufferProvider(audio_format_t format, size_t inChannelCount,
+ size_t outChannelCount, size_t frameCount);
+ //Overrides
+ void copyFrames(void *dst, const void *src, size_t frames) override;
+
+protected:
+ const audio_format_t mFormat;
+ const size_t mInChannelCount;
+ const size_t mOutChannelCount;
+ const size_t mSampleSizeInBytes;
+};
+
+// AdjustChannelsNonDestructiveBufferProvider derives from CopyBufferProvider to adjust sample data.
+// Expands or contracts sample data from one interleaved channel format to another.
+// Extra expanded channels are interleaved in from the end of the input buffer.
+// Contracted channels are copied to the end of the output buffer.
+// Contracted channels could be written to output buffer.
+class AdjustChannelsNonDestructiveBufferProvider : public CopyBufferProvider {
+public:
+ AdjustChannelsNonDestructiveBufferProvider(audio_format_t format, size_t inChannelCount,
+ size_t outChannelCount, audio_format_t contractedFormat, size_t contractedFrameCount,
+ void* contractedBuffer);
+ //Overrides
+ status_t getNextBuffer(Buffer* pBuffer) override;
+ void copyFrames(void *dst, const void *src, size_t frames) override;
+ void reset() override;
+
+ void clearContractedFrames() { mContractedWrittenFrames = 0; }
+
+protected:
+ const audio_format_t mFormat;
+ const size_t mInChannelCount;
+ const size_t mOutChannelCount;
+ const size_t mSampleSizeInBytes;
+ const size_t mContractedChannelCount;
+ const audio_format_t mContractedFormat;
+ const size_t mContractedFrameCount;
+ void *mContractedBuffer;
+ size_t mContractedWrittenFrames;
+ size_t mContractedFrameSize;
+};
// ----------------------------------------------------------------------------
} // namespace android
diff --git a/media/libmedia/include/media/Visualizer.h b/media/libmedia/include/media/Visualizer.h
index f8f4f50..8078e36 100644
--- a/media/libmedia/include/media/Visualizer.h
+++ b/media/libmedia/include/media/Visualizer.h
@@ -131,6 +131,7 @@
// getCaptureSize() but the length of the FFT is half of the size (both parts of the spectrum
// are returned
status_t getFft(uint8_t *fft);
+ void release();
protected:
// from IEffectClient
@@ -146,12 +147,12 @@
class CaptureThread : public Thread
{
public:
- CaptureThread(Visualizer& receiver, uint32_t captureRate, bool bCanCallJava = false);
+ CaptureThread(Visualizer* visualizer, uint32_t captureRate, bool bCanCallJava = false);
private:
friend class Visualizer;
virtual bool threadLoop();
- Visualizer& mReceiver;
+ wp<Visualizer> mReceiver;
Mutex mLock;
uint32_t mSleepTimeUs;
};
diff --git a/media/libmediaextractor/MediaBuffer.cpp b/media/libmediaextractor/MediaBuffer.cpp
index d197b3f..26d0bd4 100644
--- a/media/libmediaextractor/MediaBuffer.cpp
+++ b/media/libmediaextractor/MediaBuffer.cpp
@@ -39,8 +39,7 @@
mRangeOffset(0),
mRangeLength(size),
mOwnsData(false),
- mMetaData(new MetaDataBase),
- mOriginal(NULL) {
+ mMetaData(new MetaDataBase) {
}
MediaBuffer::MediaBuffer(size_t size)
@@ -51,8 +50,7 @@
mRangeOffset(0),
mRangeLength(size),
mOwnsData(true),
- mMetaData(new MetaDataBase),
- mOriginal(NULL) {
+ mMetaData(new MetaDataBase) {
if (size < kSharedMemThreshold
|| std::atomic_load_explicit(&mUseSharedMemory, std::memory_order_seq_cst) == 0) {
mData = malloc(size);
@@ -84,8 +82,7 @@
mRangeLength(mSize),
mBuffer(buffer),
mOwnsData(false),
- mMetaData(new MetaDataBase),
- mOriginal(NULL) {
+ mMetaData(new MetaDataBase) {
}
void MediaBuffer::release() {
@@ -162,11 +159,6 @@
mData = NULL;
}
- if (mOriginal != NULL) {
- mOriginal->release();
- mOriginal = NULL;
- }
-
if (mMemory.get() != nullptr) {
getSharedControl()->setDeadObject();
}
@@ -178,15 +170,4 @@
mObserver = observer;
}
-MediaBufferBase *MediaBuffer::clone() {
- MediaBuffer *buffer = new MediaBuffer(mData, mSize);
- buffer->set_range(mRangeOffset, mRangeLength);
- buffer->mMetaData = new MetaDataBase(*mMetaData);
-
- add_ref();
- buffer->mOriginal = this;
-
- return buffer;
-}
-
} // namespace android
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBuffer.h b/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
index 5a25965..5b362a4 100644
--- a/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
+++ b/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
@@ -80,11 +80,6 @@
virtual void setObserver(MediaBufferObserver *group);
- // Returns a clone of this MediaBuffer increasing its reference count.
- // The clone references the same data but has its own range and
- // MetaData.
- virtual MediaBufferBase *clone();
-
// sum of localRefcount() and remoteRefcount()
// Result should be treated as approximate unless the result precludes concurrent accesses.
virtual int refcount() const {
@@ -158,8 +153,6 @@
MetaDataBase* mMetaData;
- MediaBuffer *mOriginal;
-
static std::atomic_int_least32_t mUseSharedMemory;
MediaBuffer(const MediaBuffer &);
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h b/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
index d67ddbd..3682368 100644
--- a/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
+++ b/media/libmediaextractor/include/media/stagefright/MediaBufferBase.h
@@ -70,11 +70,6 @@
virtual void setObserver(MediaBufferObserver *group) = 0;
- // Returns a clone of this MediaBufferBase increasing its reference
- // count. The clone references the same data but has its own range and
- // MetaData.
- virtual MediaBufferBase *clone() = 0;
-
virtual int refcount() const = 0;
virtual int localRefcount() const = 0;
@@ -101,6 +96,14 @@
return ((MediaBufferBase*)handle)->size();
};
+ mWrapper->range_offset = [](void *handle) -> size_t {
+ return ((MediaBufferBase*)handle)->range_offset();
+ };
+
+ mWrapper->range_length = [](void *handle) -> size_t {
+ return ((MediaBufferBase*)handle)->range_length();
+ };
+
mWrapper->set_range = [](void *handle, size_t offset, size_t length) -> void {
return ((MediaBufferBase*)handle)->set_range(offset, length);
};
diff --git a/media/libmediametrics/Android.bp b/media/libmediametrics/Android.bp
index 0a342b8..8f8c478 100644
--- a/media/libmediametrics/Android.bp
+++ b/media/libmediametrics/Android.bp
@@ -6,15 +6,16 @@
srcs: [
"IMediaAnalyticsService.cpp",
"MediaAnalyticsItem.cpp",
+ "MediaMetrics.cpp",
],
shared_libs: [
- "liblog",
- "libcutils",
- "libutils",
- "libbinder",
- "libstagefright_foundation",
"libbase",
+ "libbinder",
+ "libcutils",
+ "liblog",
+ "libstagefright_foundation",
+ "libutils",
],
export_include_dirs: ["include"],
@@ -32,4 +33,13 @@
],
cfi: true,
},
+
+ // enumerate the stable interface
+// this would mean nobody can use the C++ interface. have to rework some things.
+// stubs: {
+// symbol_file: "libmediametrics.map.txt",
+// versions: [
+// "1" ,
+// ]
+// },
}
diff --git a/media/libmediametrics/MediaAnalyticsItem.cpp b/media/libmediametrics/MediaAnalyticsItem.cpp
index d3de01e..448e2d9 100644
--- a/media/libmediametrics/MediaAnalyticsItem.cpp
+++ b/media/libmediametrics/MediaAnalyticsItem.cpp
@@ -487,6 +487,18 @@
return true;
}
+bool MediaAnalyticsItem::getString(MediaAnalyticsItem::Attr name, std::string *value) {
+ Prop *prop = findProp(name);
+ if (prop == NULL || prop->mType != kTypeCString) {
+ return false;
+ }
+ if (value != NULL) {
+ // std::string makes a copy for us
+ *value = prop->u.CStringValue;
+ }
+ return true;
+}
+
// remove indicated keys and their values
// return value is # keys removed
int32_t MediaAnalyticsItem::filter(int n, MediaAnalyticsItem::Attr attrs[]) {
@@ -726,6 +738,15 @@
}
+const char *MediaAnalyticsItem::toCString() {
+ return toCString(PROTO_LAST);
+}
+
+const char * MediaAnalyticsItem::toCString(int version) {
+ std::string val = toString(version);
+ return strdup(val.c_str());
+}
+
std::string MediaAnalyticsItem::toString() {
return toString(PROTO_LAST);
}
diff --git a/media/libmediametrics/MediaMetrics.cpp b/media/libmediametrics/MediaMetrics.cpp
new file mode 100644
index 0000000..9b08aa7
--- /dev/null
+++ b/media/libmediametrics/MediaMetrics.cpp
@@ -0,0 +1,204 @@
+/*
+ * 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_TAG "MediaMetrics"
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <media/MediaAnalyticsItem.h>
+#include <media/MediaMetrics.h>
+
+//
+// provide a C-ish interface that is easier to stabilize than the existing C++
+// interface
+//
+// ALL functions returning a char * give responsibility for the allocated buffer
+// to the caller. The caller is responsible to call free() on that pointer.
+//
+
+// manage the overall record
+mediametrics_handle_t mediametrics_create(mediametricskey_t key) {
+ android::MediaAnalyticsItem *item = new android::MediaAnalyticsItem(key);
+ return (mediametrics_handle_t) item;
+}
+
+void mediametrics_delete(mediametrics_handle_t handle) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item == NULL) return;
+ delete item;
+}
+
+mediametricskey_t mediametrics_getKey(mediametrics_handle_t handle) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item == NULL) return NULL;
+ return strdup(item->getKey().c_str());
+}
+
+// nuplayer, et al use it when acting as proxies
+void mediametrics_setUid(mediametrics_handle_t handle, uid_t uid) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item != NULL) item->setUid(uid);
+}
+
+// set attributes
+//
+
+void mediametrics_setInt32(mediametrics_handle_t handle, attr_t attr,
+ int32_t value) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item != NULL) item->setInt32(attr, value);
+}
+
+void mediametrics_setInt64(mediametrics_handle_t handle, attr_t attr,
+ int64_t value) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item != NULL) item->setInt64(attr, value);
+}
+
+void mediametrics_setDouble(mediametrics_handle_t handle, attr_t attr,
+ double value) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item != NULL) item->setDouble(attr, value);
+}
+
+void mediametrics_setRate(mediametrics_handle_t handle, attr_t attr,
+ int64_t count, int64_t duration) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item != NULL) item->setRate(attr, count, duration);
+}
+
+void mediametrics_setCString(mediametrics_handle_t handle, attr_t attr,
+ const char *value) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item != NULL) item->setCString(attr, value);
+}
+
+// fused get/add/set; if attr wasn't there, it's a simple set.
+//
+
+void mediametrics_addInt32(mediametrics_handle_t handle, attr_t attr,
+ int32_t value) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item != NULL) item->addInt32(attr, value);
+}
+
+void mediametrics_addInt64(mediametrics_handle_t handle, attr_t attr,
+ int64_t value) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item != NULL) item->addInt64(attr, value);
+}
+
+void mediametrics_addDouble(mediametrics_handle_t handle, attr_t attr,
+ double value) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item != NULL) item->addDouble(attr, value);
+}
+
+void mediametrics_addRate(mediametrics_handle_t handle, attr_t attr,
+ int64_t count, int64_t duration) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item != NULL) item->addRate(attr, count, duration);
+}
+
+// find & extract values
+// return indicates whether attr exists (and thus whether value filled in)
+// NULL parameter value suppresses storage of value.
+//
+
+bool mediametrics_getInt32(mediametrics_handle_t handle, attr_t attr,
+ int32_t * value) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item == NULL) return false;
+ return item->getInt32(attr, value);
+}
+
+bool mediametrics_getInt64(mediametrics_handle_t handle, attr_t attr,
+ int64_t * value) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item == NULL) return false;
+ return item->getInt64(attr, value);
+}
+
+bool mediametrics_getDouble(mediametrics_handle_t handle, attr_t attr,
+ double *value) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item == NULL) return false;
+ return item->getDouble(attr, value);
+}
+
+bool mediametrics_getRate(mediametrics_handle_t handle, attr_t attr,
+ int64_t * count, int64_t * duration, double *rate) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item == NULL) return false;
+ return item->getRate(attr, count, duration, rate);
+}
+
+// NB: caller owns the string that comes back, is responsible for freeing it
+bool mediametrics_getCString(mediametrics_handle_t handle, attr_t attr,
+ char **value) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item == NULL) return false;
+
+ return item->getCString(attr, value);
+}
+
+// to release strings returned via getCString()
+void mediametrics_freeCString(char *value) {
+ free(value);
+}
+
+bool mediametrics_selfRecord(mediametrics_handle_t handle) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item == NULL) return false;
+ return item->selfrecord();
+}
+
+
+const char *mediametrics_readable(mediametrics_handle_t handle) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item == NULL) return "";
+ return item->toCString();
+}
+
+int32_t mediametrics_count(mediametrics_handle_t handle) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item == NULL) return 0;
+ return item->count();
+}
+
+bool mediametrics_isEnabled() {
+ // static, so doesn't need an instance
+ return android::MediaAnalyticsItem::isEnabled();
+}
+
+#if 0
+// do not expose this as is.
+// need to revisit (or redefine) how the android::Parcel parameter is handled
+// so that it meets the stable-API criteria for updateable components.
+//
+int32_t mediametrics_writeToParcel(mediametrics_handle_t handle, android::Parcel *parcel) {
+ android::MediaAnalyticsItem *item = (android::MediaAnalyticsItem *) handle;
+ if (item == NULL) {
+ return -1;
+ }
+ return item->writeToParcel(parcel);
+}
+#endif
+
+
diff --git a/media/libmediametrics/include/MediaAnalyticsItem.h b/media/libmediametrics/include/MediaAnalyticsItem.h
index 263cde7..b99cd91 100644
--- a/media/libmediametrics/include/MediaAnalyticsItem.h
+++ b/media/libmediametrics/include/MediaAnalyticsItem.h
@@ -134,6 +134,7 @@
bool getRate(Attr, int64_t *count, int64_t *duration, double *rate);
// Caller owns the returned string
bool getCString(Attr, char **value);
+ bool getString(Attr, std::string *value);
// parameter indicates whether to close any existing open
// record with same key before establishing a new record
@@ -176,6 +177,8 @@
std::string toString();
std::string toString(int version);
+ const char *toCString();
+ const char *toCString(int version);
// are we collecting analytics data
static bool isEnabled();
diff --git a/media/libmediametrics/include/MediaMetrics.h b/media/libmediametrics/include/MediaMetrics.h
new file mode 100644
index 0000000..4d2f352
--- /dev/null
+++ b/media/libmediametrics/include/MediaMetrics.h
@@ -0,0 +1,98 @@
+/*
+ * 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_MEDIA_MEDIAMETRICS_H
+#define ANDROID_MEDIA_MEDIAMETRICS_H
+
+//
+// define a C interface to the media metrics functionality
+//
+// All functions that return a char * or const char * also give responsibility
+// for that string to the caller. The caller is responsible for calling free()
+// on that pointer when done using the value.
+
+__BEGIN_DECLS
+
+// internally re-cast to the behind-the-scenes C++ class instance
+typedef int64_t mediametrics_handle_t;
+typedef const char *mediametricskey_t;
+typedef const char *attr_t;
+
+mediametrics_handle_t mediametrics_create(mediametricskey_t key);
+void mediametrics_delete(mediametrics_handle_t handle);
+
+mediametricskey_t mediametrics_getKey(mediametrics_handle_t handle);
+
+
+// set
+void mediametrics_setInt32(mediametrics_handle_t handle, attr_t attr,
+ int32_t value);
+void mediametrics_setInt64(mediametrics_handle_t handle, attr_t attr,
+ int64_t value);
+void mediametrics_setDouble(mediametrics_handle_t handle, attr_t attr,
+ double value);
+void mediametrics_setRate(mediametrics_handle_t handle, attr_t attr,
+ int64_t count, int64_t duration);
+void mediametrics_setCString(mediametrics_handle_t handle, attr_t attr,
+ const char * value);
+
+// fused get/add/set; if attr wasn't there, it's a simple set.
+// these do not provide atomicity or mutual exclusion, only simpler code sequences.
+void mediametrics_addInt32(mediametrics_handle_t handle, attr_t attr,
+ int32_t value);
+void mediametrics_addInt64(mediametrics_handle_t handle, attr_t attr,
+ int64_t value);
+void mediametrics_addDouble(mediametrics_handle_t handle, attr_t attr,
+ double value);
+void mediametrics_addRate(mediametrics_handle_t handle, attr_t attr,
+ int64_t count, int64_t duration);
+
+// find & extract values
+// return indicates whether attr exists (and thus whether value filled in)
+// NULL parameter value suppresses storage of value.
+bool mediametrics_getInt32(mediametrics_handle_t handle, attr_t attr,
+ int32_t * value);
+bool mediametrics_getInt64(mediametrics_handle_t handle, attr_t attr,
+ int64_t * value);
+bool mediametrics_getDouble(mediametrics_handle_t handle, attr_t attr,
+ double *value);
+bool mediametrics_getRate(mediametrics_handle_t handle, attr_t attr,
+ int64_t * count, int64_t * duration, double *rate);
+bool mediametrics_getCString(mediametrics_handle_t handle, attr_t attr,
+ char **value);
+// to release strings returned via getCString()
+void mediametrics_freeCString(char *value);
+
+// # of attributes set within this record.
+int32_t mediametrics_count(mediametrics_handle_t handle);
+
+bool mediametrics_selfRecord(mediametrics_handle_t handle);
+
+const char *mediametrics_readable(mediametrics_handle_t handle);
+void mediametrics_setUid(mediametrics_handle_t handle, uid_t uid);
+bool mediametrics_isEnabled();
+
+#if 0
+// do not expose this as is.
+// need to revisit (or redefine) how the android::Parcel parameter is handled
+// so that it meets the stable-API criteria for updateable components.
+//
+int32_t mediametrics_writeToParcel(mediametrics_handle_t handle, android::Parcel *parcel);
+#endif
+
+__END_DECLS
+
+#endif
diff --git a/media/libstagefright/MediaTrack.cpp b/media/libstagefright/MediaTrack.cpp
index 6c0f989..5f2e601 100644
--- a/media/libstagefright/MediaTrack.cpp
+++ b/media/libstagefright/MediaTrack.cpp
@@ -16,6 +16,7 @@
#include <mutex>
+#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/Utils.h>
@@ -216,10 +217,51 @@
if (format->mFormat->findInt64("timeUs", &val64)) {
meta.setInt64(kKeyTime, val64);
}
+ if (format->mFormat->findInt64("duration", &val64)) {
+ meta.setInt64(kKeyDuration, val64);
+ }
+ if (format->mFormat->findInt64("target-time", &val64)) {
+ meta.setInt64(kKeyTargetTime, val64);
+ }
int32_t val32;
if (format->mFormat->findInt32("is-sync-frame", &val32)) {
meta.setInt32(kKeyIsSyncFrame, val32);
}
+ if (format->mFormat->findInt32("temporal-layer-id", &val32)) {
+ meta.setInt32(kKeyTemporalLayerId, val32);
+ }
+ if (format->mFormat->findInt32("temporal-layer-count", &val32)) {
+ meta.setInt32(kKeyTemporalLayerCount, val32);
+ }
+ if (format->mFormat->findInt32("crypto-default-iv-size", &val32)) {
+ meta.setInt32(kKeyCryptoDefaultIVSize, val32);
+ }
+ if (format->mFormat->findInt32("crypto-mode", &val32)) {
+ meta.setInt32(kKeyCryptoMode, val32);
+ }
+ if (format->mFormat->findInt32("crypto-encrypted-byte-block", &val32)) {
+ meta.setInt32(kKeyEncryptedByteBlock, val32);
+ }
+ if (format->mFormat->findInt32("crypto-skip-byte-block", &val32)) {
+ meta.setInt32(kKeySkipByteBlock, val32);
+ }
+ sp<ABuffer> valbuf;
+ if (format->mFormat->findBuffer("crypto-plain-sizes", &valbuf)) {
+ meta.setData(kKeyPlainSizes,
+ MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
+ }
+ if (format->mFormat->findBuffer("crypto-encrypted-sizes", &valbuf)) {
+ meta.setData(kKeyEncryptedSizes,
+ MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
+ }
+ if (format->mFormat->findBuffer("crypto-key", &valbuf)) {
+ meta.setData(kKeyCryptoKey,
+ MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
+ }
+ if (format->mFormat->findBuffer("crypto-iv", &valbuf)) {
+ meta.setData(kKeyCryptoIV,
+ MetaDataBase::Type::TYPE_NONE, valbuf->data(), valbuf->size());
+ }
} else {
*buffer = nullptr;
}
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 670b607..cfa9fd9 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -598,7 +598,10 @@
{
{ "exif-offset", kKeyExifOffset },
{ "exif-size", kKeyExifSize },
+ { "target-time", kKeyTargetTime },
{ "thumbnail-time", kKeyThumbnailTime },
+ { "timeUs", kKeyTime },
+ { "durationUs", kKeyDuration },
}
};
@@ -613,6 +616,7 @@
{ "max-bitrate", kKeyMaxBitRate },
{ "pcm-big-endian", kKeyPcmBigEndian },
{ "temporal-layer-count", kKeyTemporalLayerCount },
+ { "temporal-layer-id", kKeyTemporalLayerId },
{ "thumbnail-width", kKeyThumbnailWidth },
{ "thumbnail-height", kKeyThumbnailHeight },
{ "frame-count", kKeyFrameCount },
@@ -626,6 +630,8 @@
{ "pssh", kKeyPssh },
{ "crypto-iv", kKeyCryptoIV },
{ "crypto-key", kKeyCryptoKey },
+ { "crypto-encrypted-sizes", kKeyEncryptedSizes },
+ { "crypto-plain-sizes", kKeyPlainSizes },
{ "icc-profile", kKeyIccProfile },
{ "text-format-data", kKeyTextFormatData },
}
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index cf93fcf..590131e 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -121,6 +121,8 @@
ATSParser *mParser;
unsigned mProgramNumber;
unsigned mProgramMapPID;
+ uint32_t mPMTVersion;
+ uint32_t mPMT_CRC;
KeyedVector<unsigned, sp<Stream> > mStreams;
bool mFirstPTSValid;
uint64_t mFirstPTS;
@@ -143,6 +145,9 @@
unsigned typeExt() const { return mStreamTypeExt; }
unsigned pid() const { return mElementaryPID; }
void setPID(unsigned pid) { mElementaryPID = pid; }
+ void setAudioPresentations(AudioPresentationCollection audioPresentations) {
+ mAudioPresentations = audioPresentations;
+ }
void setCasInfo(
int32_t systemId,
@@ -293,6 +298,8 @@
: mParser(parser),
mProgramNumber(programNumber),
mProgramMapPID(programMapPID),
+ mPMTVersion(0xffffffff),
+ mPMT_CRC(0xffffffff),
mFirstPTSValid(false),
mFirstPTS(0),
mLastRecoveredPTS(lastRecoveredPTS) {
@@ -480,7 +487,13 @@
MY_LOGV(" program_number = %u", br->getBits(16));
MY_LOGV(" reserved = %u", br->getBits(2));
- MY_LOGV(" version_number = %u", br->getBits(5));
+ bool audioPresentationsChanged = false;
+ unsigned pmtVersion = br->getBits(5);
+ if (pmtVersion != mPMTVersion) {
+ audioPresentationsChanged = true;
+ mPMTVersion = pmtVersion;
+ }
+ MY_LOGV(" version_number = %u", pmtVersion);
MY_LOGV(" current_next_indicator = %u", br->getBits(1));
MY_LOGV(" section_number = %u", br->getBits(8));
MY_LOGV(" last_section_number = %u", br->getBits(8));
@@ -661,7 +674,12 @@
if (infoBytesRemaining != 0) {
ALOGW("Section data remains unconsumed");
}
- MY_LOGV(" CRC = 0x%08x", br->getBits(32));
+ unsigned crc = br->getBits(32);
+ if (crc != mPMT_CRC) {
+ audioPresentationsChanged = true;
+ mPMT_CRC = crc;
+ }
+ MY_LOGV(" CRC = 0x%08x", crc);
bool PIDsChanged = false;
for (size_t i = 0; i < infos.size(); ++i) {
@@ -722,6 +740,10 @@
isAddingScrambledStream |= info.mCADescriptor.mSystemID >= 0;
mStreams.add(info.mPID, stream);
}
+ else if (index >= 0 && mStreams.editValueAt(index)->isAudio()
+ && audioPresentationsChanged) {
+ mStreams.editValueAt(index)->setAudioPresentations(info.mAudioPresentations);
+ }
}
if (isAddingScrambledStream) {
@@ -1732,6 +1754,7 @@
mSource->setFormat(mQueue->getFormat());
}
mSource->queueAccessUnit(accessUnit);
+ mSource->convertAudioPresentationInfoToMetadata(mAudioPresentations);
}
// Every access unit has a pesStartOffset queued in |mPesStartOffsets|.
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index e355183..6976950 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -61,7 +61,6 @@
],
cflags: [
- "-fvisibility=hidden",
"-DEXPORT=__attribute__((visibility(\"default\")))",
"-Werror",
"-Wall",
@@ -105,6 +104,10 @@
},
},
version_script: "libmediandk.map.txt",
+ stubs: {
+ symbol_file: "libmediandk.map.txt",
+ versions: ["29"],
+ },
}
llndk_library {
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index e0af80d..8f3a9f3 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -294,9 +294,11 @@
EXPORT const char* AMEDIAFORMAT_KEY_COMPOSER = "composer";
EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE = "crypto-default-iv-size";
EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK = "crypto-encrypted-byte-block";
+EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES = "crypto-encrypted-sizes";
EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_IV = "crypto-iv";
EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_KEY = "crypto-key";
EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_MODE = "crypto-mode";
+EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES = "crypto-encrypted-sizes";
EXPORT const char* AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK = "crypto-skip-byte-block";
EXPORT const char* AMEDIAFORMAT_KEY_CSD = "csd";
EXPORT const char* AMEDIAFORMAT_KEY_CSD_0 = "csd-0";
@@ -361,6 +363,7 @@
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_TARGET_TIME = "target-time";
EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_COUNT = "temporal-layer-count";
EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID = "temporal-layer-id";
EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYERING = "ts-schema";
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 2cd1d04..6e7e0f9 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -190,9 +190,11 @@
extern const char* AMEDIAFORMAT_KEY_COMPOSER __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_CRYPTO_IV __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_CRYPTO_KEY __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_CRYPTO_MODE __INTRODUCED_IN(29);
+extern const char* AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_CSD_AVC __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_CSD_HEVC __INTRODUCED_IN(29);
@@ -217,6 +219,7 @@
extern const char* AMEDIAFORMAT_KEY_PSSH __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_TARGET_TIME __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_COUNT __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_TEXT_FORMAT_DATA __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_THUMBNAIL_HEIGHT __INTRODUCED_IN(29);
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index 3567899..d24cc9b 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -58,9 +58,11 @@
AMEDIAFORMAT_KEY_COMPOSER; # var introduced=29
AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE; # var introduced=29
AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK; # var introduced=29
+ AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_SIZES; # var introduced=29
AMEDIAFORMAT_KEY_CRYPTO_IV; # var introduced=29
AMEDIAFORMAT_KEY_CRYPTO_KEY; # var introduced=29
AMEDIAFORMAT_KEY_CRYPTO_MODE; # var introduced=29
+ AMEDIAFORMAT_KEY_CRYPTO_PLAIN_SIZES; # var introduced=29
AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK; # var introduced=29
AMEDIAFORMAT_KEY_CSD; # var introduced=28
AMEDIAFORMAT_KEY_CSD_0; # var introduced=28
@@ -124,6 +126,7 @@
AMEDIAFORMAT_KEY_SEI; # var introduced=28
AMEDIAFORMAT_KEY_SLICE_HEIGHT; # var introduced=28
AMEDIAFORMAT_KEY_STRIDE; # var introduced=21
+ AMEDIAFORMAT_KEY_TARGET_TIME; # var introduced=29
AMEDIAFORMAT_KEY_TEMPORAL_LAYER_COUNT; # var introduced=29
AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID; # var introduced=28
AMEDIAFORMAT_KEY_TEMPORAL_LAYERING; # var introduced=28
diff --git a/packages/MediaComponents/apex/java/android/media/session/MediaSession.java b/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
index 04dc0b8..1ae1d2c 100644
--- a/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
+++ b/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
@@ -171,10 +171,8 @@
if (TextUtils.isEmpty(tag)) {
throw new IllegalArgumentException("tag cannot be null or empty");
}
- //TODO(b/119749798): Resolve hidden API usage. com.android.internal.R
- //mMaxBitmapSize = context.getResources().getDimensionPixelSize(
- //com.android.internal.R.dimen.config_mediaMetadataBitmapMaxSize);
- mMaxBitmapSize = 1024; //TODO: remove this.
+ mMaxBitmapSize = context.getResources().getDimensionPixelSize(
+ android.R.dimen.config_mediaMetadataBitmapMaxSize);
mCbStub = new CallbackStub(this);
MediaSessionManager manager = (MediaSessionManager) context
.getSystemService(Context.MEDIA_SESSION_SERVICE);
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index d15841f..f328577 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -37,8 +37,9 @@
#include <cpustats/ThreadCpuUsage.h>
#endif
#endif
-#include <audio_utils/mono_blend.h>
+#include <audio_utils/channels.h>
#include <audio_utils/format.h>
+#include <audio_utils/mono_blend.h>
#include <media/AudioMixer.h>
#include "FastMixer.h"
#include "TypedLogger.h"
@@ -159,20 +160,24 @@
if (current->mOutputSinkGen != mOutputSinkGen) {
mOutputSink = current->mOutputSink;
mOutputSinkGen = current->mOutputSinkGen;
+ mSinkChannelMask = current->mSinkChannelMask;
if (mOutputSink == NULL) {
mFormat = Format_Invalid;
mSampleRate = 0;
mSinkChannelCount = 0;
mSinkChannelMask = AUDIO_CHANNEL_NONE;
+ mAudioChannelCount = 0;
} else {
mFormat = mOutputSink->format();
mSampleRate = Format_sampleRate(mFormat);
mSinkChannelCount = Format_channelCount(mFormat);
LOG_ALWAYS_FATAL_IF(mSinkChannelCount > AudioMixer::MAX_NUM_CHANNELS);
- // TODO: Add channel mask to NBAIO_Format
- // We assume that the channel mask must be a valid positional channel mask.
- mSinkChannelMask = audio_channel_out_mask_from_count(mSinkChannelCount);
+ if (mSinkChannelMask == AUDIO_CHANNEL_NONE) {
+ mSinkChannelMask = audio_channel_out_mask_from_count(mSinkChannelCount);
+ }
+ mAudioChannelCount = mSinkChannelCount - audio_channel_count_from_out_mask(
+ mSinkChannelMask & AUDIO_CHANNEL_HAPTIC_ALL);
}
dumpState->mSampleRate = mSampleRate;
}
@@ -288,6 +293,8 @@
(void *)(uintptr_t)fastTrack->mChannelMask);
mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MIXER_CHANNEL_MASK,
(void *)(uintptr_t)mSinkChannelMask);
+ mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::HAPTIC_ENABLED,
+ (void *)(uintptr_t)fastTrack->mHapticPlaybackEnabled);
mMixer->enable(name);
}
mGenerations[i] = fastTrack->mGeneration;
@@ -324,6 +331,8 @@
(void *)(uintptr_t)fastTrack->mChannelMask);
mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::MIXER_CHANNEL_MASK,
(void *)(uintptr_t)mSinkChannelMask);
+ mMixer->setParameter(name, AudioMixer::TRACK, AudioMixer::HAPTIC_ENABLED,
+ (void *)(uintptr_t)fastTrack->mHapticPlaybackEnabled);
// already enabled
}
mGenerations[i] = fastTrack->mGeneration;
@@ -468,6 +477,13 @@
memcpy_by_audio_format(buffer, mFormat.mFormat, mMixerBuffer, mMixerBufferFormat,
frameCount * Format_channelCount(mFormat));
}
+ if (mSinkChannelMask & AUDIO_CHANNEL_HAPTIC_ALL) {
+ // When there are haptic channels, the sample data is partially interleaved.
+ // Make the sample data fully interleaved here.
+ adjust_channels_non_destructive(buffer, mAudioChannelCount, buffer, mSinkChannelCount,
+ audio_bytes_per_sample(mFormat.mFormat),
+ frameCount * audio_bytes_per_frame(mAudioChannelCount, mFormat.mFormat));
+ }
// if non-NULL, then duplicate write() to this non-blocking sink
#ifdef TEE_SINK
mTee.write(buffer, frameCount);
diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/FastMixer.h
index 1c86d9a..1d332e0 100644
--- a/services/audioflinger/FastMixer.h
+++ b/services/audioflinger/FastMixer.h
@@ -76,6 +76,8 @@
size_t mMixerBufferSize;
audio_format_t mMixerBufferFormat; // mixer output format: AUDIO_FORMAT_PCM_(16_BIT|FLOAT).
+ uint32_t mAudioChannelCount; // audio channel count, excludes haptic channels.
+
enum {UNDEFINED, MIXED, ZEROED} mMixerBufferState;
NBAIO_Format mFormat;
unsigned mSampleRate;
diff --git a/services/audioflinger/FastMixerState.h b/services/audioflinger/FastMixerState.h
index c7fcbd8..9d2a733 100644
--- a/services/audioflinger/FastMixerState.h
+++ b/services/audioflinger/FastMixerState.h
@@ -47,6 +47,7 @@
audio_channel_mask_t mChannelMask; // AUDIO_CHANNEL_OUT_MONO or AUDIO_CHANNEL_OUT_STEREO
audio_format_t mFormat; // track format
int mGeneration; // increment when any field is assigned
+ bool mHapticPlaybackEnabled = false; // haptic playback is enabled or not
};
// Represents a single state of the fast mixer
@@ -69,6 +70,9 @@
NBAIO_Sink* mOutputSink; // HAL output device, must already be negotiated
int mOutputSinkGen; // increment when mOutputSink is assigned
size_t mFrameCount; // number of frames per fast mix buffer
+ audio_channel_mask_t mSinkChannelMask; // If not AUDIO_CHANNEL_NONE, specifies sink channel
+ // mask when it cannot be directly calculated from
+ // channel count
// Extends FastThreadState::Command
static const Command
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 971f6a5..d9f570d 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -112,6 +112,14 @@
/** Copy the track metadata in the provided iterator. Thread safe. */
virtual void copyMetadataTo(MetadataInserter& backInserter) const;
+ /** Return haptic playback of the track is enabled or not, used in mixer. */
+ bool getHapticPlaybackEnabled() const { return mHapticPlaybackEnabled; }
+ /** Set haptic playback of the track is enabled or not, should be
+ * set after query or get callback from vibrator service */
+ void setHapticPlaybackEnabled(bool hapticPlaybackEnabled) {
+ mHapticPlaybackEnabled = hapticPlaybackEnabled;
+ }
+
protected:
// for numerous
friend class PlaybackThread;
@@ -188,6 +196,8 @@
sp<media::VolumeHandler> mVolumeHandler; // handles multiple VolumeShaper configs and operations
+ bool mHapticPlaybackEnabled = false; // indicates haptic playback enabled or not
+
private:
// The following fields are only for fast tracks, and should be in a subclass
int mFastIndex; // index within FastMixerState::mFastTracks[];
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 3dae1e9..c6941c0 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -38,6 +38,7 @@
#include <private/media/AudioTrackShared.h>
#include <private/android_filesystem_config.h>
+#include <audio_utils/channels.h>
#include <audio_utils/mono_blend.h>
#include <audio_utils/primitives.h>
#include <audio_utils/format.h>
@@ -751,6 +752,7 @@
audio_channel_mask_get_representation(mask);
switch (representation) {
+ // Travel all single bit channel mask to convert channel mask to string.
case AUDIO_CHANNEL_REPRESENTATION_POSITION: {
if (output) {
if (mask & AUDIO_CHANNEL_OUT_FRONT_LEFT) s.append("front-left, ");
@@ -773,6 +775,8 @@
if (mask & AUDIO_CHANNEL_OUT_TOP_BACK_RIGHT) s.append("top-back-right, " );
if (mask & AUDIO_CHANNEL_OUT_TOP_SIDE_LEFT) s.append("top-side-left, " );
if (mask & AUDIO_CHANNEL_OUT_TOP_SIDE_RIGHT) s.append("top-side-right, " );
+ if (mask & AUDIO_CHANNEL_OUT_HAPTIC_B) s.append("haptic-B, " );
+ if (mask & AUDIO_CHANNEL_OUT_HAPTIC_A) s.append("haptic-A, " );
if (mask & ~AUDIO_CHANNEL_OUT_ALL) s.append("unknown, ");
} else {
if (mask & AUDIO_CHANNEL_IN_LEFT) s.append("left, ");
@@ -1845,6 +1849,10 @@
dumpBase(fd, args);
dprintf(fd, " Master mute: %s\n", mMasterMute ? "on" : "off");
+ if (mHapticChannelMask != AUDIO_CHANNEL_NONE) {
+ dprintf(fd, " Haptic channel mask: %#x (%s)\n", mHapticChannelMask,
+ channelMaskToString(mHapticChannelMask, true /* output */).c_str());
+ }
dprintf(fd, " Normal frame count: %zu\n", mNormalFrameCount);
dprintf(fd, " Last write occurred (msecs): %llu\n",
(unsigned long long) ns2ms(systemTime() - mLastWriteTime));
@@ -1946,7 +1954,7 @@
audio_is_linear_pcm(format) &&
// TODO: extract as a data library function that checks that a computationally
// expensive downmixer is not required: isFastOutputChannelConversion()
- (channelMask == mChannelMask ||
+ (channelMask == (mChannelMask | mHapticChannelMask) ||
mChannelMask != AUDIO_CHANNEL_OUT_STEREO ||
(channelMask == AUDIO_CHANNEL_OUT_MONO
/* && mChannelMask == AUDIO_CHANNEL_OUT_STEREO */)) &&
@@ -2348,6 +2356,17 @@
track->sharedBuffer() != 0 ? Track::FS_FILLED : Track::FS_FILLING;
}
+ // Disable all haptic playback for all other active tracks when haptic playback is supported
+ // and the track contains haptic channels. Enable haptic playback for current track.
+ // TODO: Request actual haptic playback status from vibrator service
+ if ((track->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
+ && mHapticChannelMask != AUDIO_CHANNEL_NONE) {
+ for (auto &t : mActiveTracks) {
+ t->setHapticPlaybackEnabled(false);
+ }
+ track->setHapticPlaybackEnabled(true);
+ }
+
track->mResetDone = false;
track->mPresentationCompleteFrames = 0;
mActiveTracks.add(track);
@@ -2635,6 +2654,11 @@
(void)posix_memalign(&mEffectBuffer, 32, mEffectBufferSize);
}
+ mHapticChannelMask = mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL;
+ mChannelMask &= ~mHapticChannelMask;
+ mHapticChannelCount = audio_channel_count_from_out_mask(mHapticChannelMask);
+ mChannelCount -= mHapticChannelCount;
+
// force reconfiguration of effect chains and engines to take new buffer size and audio
// parameters into account
// Note that mLock is not held when readOutputParameters_l() is called from the constructor
@@ -3007,7 +3031,7 @@
// Only one effect chain can be present in direct output thread and it uses
// the sink buffer as input
if (mType != DIRECT) {
- size_t numSamples = mNormalFrameCount * mChannelCount;
+ size_t numSamples = mNormalFrameCount * (mChannelCount + mHapticChannelCount);
status_t result = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
numSamples * sizeof(effect_buffer_t),
&halInBuffer);
@@ -3506,7 +3530,17 @@
}
memcpy_by_audio_format(buffer, format, mMixerBuffer, mMixerBufferFormat,
- mNormalFrameCount * mChannelCount);
+ mNormalFrameCount * (mChannelCount + mHapticChannelCount));
+
+ // If we're going directly to the sink and there are haptic channels,
+ // we should adjust channels as the sample data is partially interleaved
+ // in this case.
+ if (!mEffectBufferValid && mHapticChannelCount > 0) {
+ adjust_channels_non_destructive(buffer, mChannelCount, buffer,
+ mChannelCount + mHapticChannelCount,
+ audio_bytes_per_sample(format),
+ audio_bytes_per_frame(mChannelCount, format) * mNormalFrameCount);
+ }
}
mBytesRemaining = mCurrentWriteLength;
@@ -3550,7 +3584,15 @@
}
memcpy_by_audio_format(mSinkBuffer, mFormat, mEffectBuffer, mEffectBufferFormat,
- mNormalFrameCount * mChannelCount);
+ mNormalFrameCount * (mChannelCount + mHapticChannelCount));
+ // The sample data is partially interleaved when haptic channels exist,
+ // we need to adjust channels here.
+ if (mHapticChannelCount > 0) {
+ adjust_channels_non_destructive(mSinkBuffer, mChannelCount, mSinkBuffer,
+ mChannelCount + mHapticChannelCount,
+ audio_bytes_per_sample(mFormat),
+ audio_bytes_per_frame(mChannelCount, mFormat) * mNormalFrameCount);
+ }
}
// enable changes in effect chain
@@ -3716,6 +3758,7 @@
// removeTracks_l() must be called with ThreadBase::mLock held
void AudioFlinger::PlaybackThread::removeTracks_l(const Vector< sp<Track> >& tracksToRemove)
{
+ bool enabledHapticTracksRemoved = false;
for (const auto& track : tracksToRemove) {
mActiveTracks.remove(track);
ALOGV("%s(%d): removing track on session %d", __func__, track->id(), track->sessionId());
@@ -3737,6 +3780,18 @@
// remove from our tracks vector
removeTrack_l(track);
}
+ enabledHapticTracksRemoved |= track->getHapticPlaybackEnabled();
+ }
+ // If the thread supports haptic playback and the track playing haptic data was removed,
+ // enable haptic playback on the first active track that contains haptic channels.
+ // TODO: Query vibrator service to know which track should enable haptic playback.
+ if (enabledHapticTracksRemoved && mHapticChannelMask != AUDIO_CHANNEL_NONE) {
+ for (auto &t : mActiveTracks) {
+ if (t->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) {
+ t->setHapticPlaybackEnabled(true);
+ break;
+ }
+ }
}
}
@@ -3942,7 +3997,8 @@
// create an NBAIO sink for the HAL output stream, and negotiate
mOutputSink = new AudioStreamOutSink(output->stream);
size_t numCounterOffers = 0;
- const NBAIO_Format offers[1] = {Format_from_SR_C(mSampleRate, mChannelCount, mFormat)};
+ const NBAIO_Format offers[1] = {Format_from_SR_C(
+ mSampleRate, mChannelCount + mHapticChannelCount, mFormat)};
#if !LOG_NDEBUG
ssize_t index =
#else
@@ -3984,7 +4040,7 @@
// change our Sink format to accept our intermediate precision
mFormat = fastMixerFormat;
free(mSinkBuffer);
- mFrameSize = mChannelCount * audio_bytes_per_sample(mFormat);
+ mFrameSize = audio_bytes_per_frame(mChannelCount + mHapticChannelCount, mFormat);
const size_t sinkBufferSize = mNormalFrameCount * mFrameSize;
(void)posix_memalign(&mSinkBuffer, 32, sinkBufferSize);
}
@@ -4026,8 +4082,10 @@
// wrap the source side of the MonoPipe to make it an AudioBufferProvider
fastTrack->mBufferProvider = new SourceAudioBufferProvider(new MonoPipeReader(monoPipe));
fastTrack->mVolumeProvider = NULL;
- fastTrack->mChannelMask = mChannelMask; // mPipeSink channel mask for audio to FastMixer
+ fastTrack->mChannelMask = mChannelMask | mHapticChannelMask; // mPipeSink channel mask for
+ // audio to FastMixer
fastTrack->mFormat = mFormat; // mPipeSink format for audio to FastMixer
+ fastTrack->mHapticPlaybackEnabled = mHapticChannelMask != AUDIO_CHANNEL_NONE;
fastTrack->mGeneration++;
state->mFastTracksGen++;
state->mTrackMask = 1;
@@ -4035,6 +4093,10 @@
state->mOutputSink = mOutputSink.get();
state->mOutputSinkGen++;
state->mFrameCount = mFrameCount;
+ // specify sink channel mask when haptic channel mask present as it can not
+ // be calculated directly from channel count
+ state->mSinkChannelMask = mHapticChannelMask == AUDIO_CHANNEL_NONE
+ ? AUDIO_CHANNEL_NONE : mChannelMask | mHapticChannelMask;
state->mCommand = FastMixerState::COLD_IDLE;
// already done in constructor initialization list
//mFastMixerFutex = 0;
@@ -4411,6 +4473,7 @@
std::vector<std::pair<sp<Track>, size_t>> mUnderrunFrames;
} deferredOperations(&mixerStatus); // implicit nested scope for variable capture
+ bool noFastHapticTrack = true;
for (size_t i=0 ; i<count ; i++) {
const sp<Track> t = mActiveTracks[i];
@@ -4419,6 +4482,9 @@
// process fast tracks
if (track->isFastTrack()) {
+ if (track->getHapticPlaybackEnabled()) {
+ noFastHapticTrack = false;
+ }
// It's theoretically possible (though unlikely) for a fast track to be created
// and then removed within the same normal mix cycle. This is not a problem, as
@@ -4544,6 +4610,7 @@
fastTrack->mVolumeProvider = vp;
fastTrack->mChannelMask = track->mChannelMask;
fastTrack->mFormat = track->mFormat;
+ fastTrack->mHapticPlaybackEnabled = track->getHapticPlaybackEnabled();
fastTrack->mGeneration++;
state->mTrackMask |= 1 << j;
didModify = true;
@@ -4589,6 +4656,10 @@
// Avoids a misleading display in dumpsys
track->mObservedUnderruns.mBitFields.mMostRecent = UNDERRUN_FULL;
}
+ if (fastTrack->mHapticPlaybackEnabled != track->getHapticPlaybackEnabled()) {
+ fastTrack->mHapticPlaybackEnabled = track->getHapticPlaybackEnabled();
+ didModify = true;
+ }
continue;
}
@@ -4796,7 +4867,8 @@
mAudioMixer->setParameter(
trackId,
AudioMixer::TRACK,
- AudioMixer::MIXER_CHANNEL_MASK, (void *)(uintptr_t)mChannelMask);
+ AudioMixer::MIXER_CHANNEL_MASK,
+ (void *)(uintptr_t)(mChannelMask | mHapticChannelMask));
// limit track sample rate to 2 x output sample rate, which changes at re-configuration
uint32_t maxSampleRate = mSampleRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX;
uint32_t reqSampleRate = track->mAudioTrackServerProxy->getSampleRate();
@@ -4857,6 +4929,10 @@
trackId,
AudioMixer::TRACK,
AudioMixer::AUX_BUFFER, (void *)track->auxBuffer());
+ mAudioMixer->setParameter(
+ trackId,
+ AudioMixer::TRACK,
+ AudioMixer::HAPTIC_ENABLED, (void *)(uintptr_t)track->getHapticPlaybackEnabled());
// reset retry count
track->mRetryCount = kMaxTrackRetries;
@@ -4924,6 +5000,17 @@
}
+ if (mHapticChannelMask != AUDIO_CHANNEL_NONE && sq != NULL) {
+ // When there is no fast track playing haptic and FastMixer exists,
+ // enabling the first FastTrack, which provides mixed data from normal
+ // tracks, to play haptic data.
+ FastTrack *fastTrack = &state->mFastTracks[0];
+ if (fastTrack->mHapticPlaybackEnabled != noFastHapticTrack) {
+ fastTrack->mHapticPlaybackEnabled = noFastHapticTrack;
+ didModify = true;
+ }
+ }
+
// Push the new FastMixer state if necessary
bool pauseAudioWatchdog = false;
if (didModify) {
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 7f3ea0f..e8b2158 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -907,6 +907,11 @@
int64_t mBytesWritten;
int64_t mFramesWritten; // not reset on standby
int64_t mSuspendedFrames; // not reset on standby
+
+ // mHapticChannelMask and mHapticChannelCount will only be valid when the thread support
+ // haptic playback.
+ audio_channel_mask_t mHapticChannelMask = AUDIO_CHANNEL_NONE;
+ uint32_t mHapticChannelCount = 0;
private:
// mMasterMute is in both PlaybackThread and in AudioFlinger. When a
// PlaybackThread needs to find out if master-muted, it checks it's local
diff --git a/services/audiopolicy/config/audio_policy_configuration.xml b/services/audiopolicy/config/audio_policy_configuration.xml
index b5ecbf9..42c52de 100644
--- a/services/audiopolicy/config/audio_policy_configuration.xml
+++ b/services/audiopolicy/config/audio_policy_configuration.xml
@@ -198,27 +198,10 @@
<!-- End of Volume section -->
- <?disabledUntilHalV5_0
- <!-- Surround configuration -->
+ <!-- Surround Sound configuration -->
- <surroundSound>
- <!-- Each of the listed formats gets an entry in Surround Settings dialog.
- There must be a corresponding Java ENCODING_... contant defined in AudioFormat.java,
- and a display name defined in AudioFormat.toDisplayName. For the formats that don't
- need a dedicated Surrond Settings dialog entry, a subformats list should be used. -->
- <formats>
- <format name="AUDIO_FORMAT_AC3" />
- <format name="AUDIO_FORMAT_E_AC3" />
- <format name="AUDIO_FORMAT_E_AC3_JOC" />
- <format name="AUDIO_FORMAT_DOLBY_TRUEHD" />
- <format name="AUDIO_FORMAT_DTS" />
- <format name="AUDIO_FORMAT_DTS_HD" />
- <format name="AUDIO_FORMAT_AAC_LC" subformats="AUDIO_FORMAT_AAC_HE_V1 AUDIO_FORMAT_AAC_HE_V2 AUDIO_FORMAT_AAC_ELD AUDIO_FORMAT_AAC_XHE" />
- <format name="AUDIO_FORMAT_AC4" />
- </formats>
- </surroundSound>
+ <xi:include href="surround_sound_configuration_5_0.xml"/>
- <!-- End of Surround configuration -->
- ?>
+ <!-- End of Surround Sound configuration -->
</audioPolicyConfiguration>
diff --git a/services/audiopolicy/config/surround_sound_configuration_5_0.xml b/services/audiopolicy/config/surround_sound_configuration_5_0.xml
new file mode 100644
index 0000000..590a181
--- /dev/null
+++ b/services/audiopolicy/config/surround_sound_configuration_5_0.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- 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.
+-->
+<surroundSound>
+ <!-- Each of the listed formats gets an entry in Surround Settings dialog on TV devices.
+ There must be a corresponding Java ENCODING_... contant defined in AudioFormat.java,
+ and a display name defined in AudioFormat.toDisplayName. For the formats that don't
+ need a dedicated Surrond Settings dialog entry, a subformats list has to be used. -->
+ <formats>
+ <format name="AUDIO_FORMAT_AC3" />
+ <format name="AUDIO_FORMAT_E_AC3" />
+ <format name="AUDIO_FORMAT_E_AC3_JOC" />
+ <format name="AUDIO_FORMAT_DOLBY_TRUEHD" />
+ <format name="AUDIO_FORMAT_DTS" />
+ <format name="AUDIO_FORMAT_DTS_HD" />
+ <format name="AUDIO_FORMAT_AAC_LC" subformats="AUDIO_FORMAT_AAC_HE_V1 AUDIO_FORMAT_AAC_HE_V2 AUDIO_FORMAT_AAC_ELD AUDIO_FORMAT_AAC_XHE" />
+ <format name="AUDIO_FORMAT_AC4" />
+ </formats>
+</surroundSound>
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index c1a4c11..46fbc3e 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -256,7 +256,7 @@
Vector<int32_t> outputStreamIds;
std::vector<std::string> requestedPhysicalIds;
if (request.mSurfaceList.size() > 0) {
- for (sp<Surface> surface : request.mSurfaceList) {
+ for (const sp<Surface>& surface : request.mSurfaceList) {
if (surface == 0) continue;
int32_t streamId;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 856af13..12fbf82 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -175,7 +175,7 @@
session->interfaceChain([](
::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
ALOGV("Session interface chain:");
- for (auto iface : interfaceChain) {
+ for (const auto& iface : interfaceChain) {
ALOGV(" %s", iface.c_str());
}
});
diff --git a/services/mediaextractor/Android.mk b/services/mediaextractor/Android.mk
index 19ce7e9..dddd960 100644
--- a/services/mediaextractor/Android.mk
+++ b/services/mediaextractor/Android.mk
@@ -40,16 +40,8 @@
# extractor libraries
LOCAL_REQUIRED_MODULES += \
- libaacextractor \
- libamrextractor \
- libflacextractor \
- libmidiextractor \
- libmkvextractor \
- libmp3extractor \
- libmp4extractor \
libmpeg2extractor \
liboggextractor \
- libwavextractor \
LOCAL_SRC_FILES := main_extractorservice.cpp
LOCAL_SHARED_LIBRARIES := libmedia libmediaextractorservice libbinder libutils \
diff --git a/services/oboeservice/AAudioEndpointManager.cpp b/services/oboeservice/AAudioEndpointManager.cpp
index cca1895..a1fc0ea 100644
--- a/services/oboeservice/AAudioEndpointManager.cpp
+++ b/services/oboeservice/AAudioEndpointManager.cpp
@@ -108,7 +108,7 @@
const AAudioStreamConfiguration &configuration) {
sp<AAudioServiceEndpoint> endpoint;
mExclusiveSearchCount++;
- for (const auto ep : mExclusiveStreams) {
+ for (const auto& ep : mExclusiveStreams) {
if (ep->matches(configuration)) {
mExclusiveFoundCount++;
endpoint = ep;
@@ -126,7 +126,7 @@
const AAudioStreamConfiguration &configuration) {
sp<AAudioServiceEndpointShared> endpoint;
mSharedSearchCount++;
- for (const auto ep : mSharedStreams) {
+ for (const auto& ep : mSharedStreams) {
if (ep->matches(configuration)) {
mSharedFoundCount++;
endpoint = ep;
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index 539735a..4dfb62a 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -65,7 +65,7 @@
result << " Connected: " << mConnected.load() << "\n";
result << " Registered Streams:" << "\n";
result << AAudioServiceStreamShared::dumpHeader() << "\n";
- for (const auto stream : mRegisteredStreams) {
+ for (const auto& stream : mRegisteredStreams) {
result << stream->dump() << "\n";
}
@@ -78,7 +78,7 @@
// @return true if stream found
bool AAudioServiceEndpoint::isStreamRegistered(audio_port_handle_t portHandle) {
std::lock_guard<std::mutex> lock(mLockStreams);
- for (const auto stream : mRegisteredStreams) {
+ for (const auto& stream : mRegisteredStreams) {
if (stream->getPortHandle() == portHandle) {
return true;
}
@@ -89,7 +89,7 @@
void AAudioServiceEndpoint::disconnectRegisteredStreams() {
std::lock_guard<std::mutex> lock(mLockStreams);
mConnected.store(false);
- for (const auto stream : mRegisteredStreams) {
+ for (const auto& stream : mRegisteredStreams) {
ALOGD("disconnectRegisteredStreams() stop and disconnect %p", stream.get());
stream->stop();
stream->disconnect();
diff --git a/services/oboeservice/AAudioServiceEndpointCapture.cpp b/services/oboeservice/AAudioServiceEndpointCapture.cpp
index 7ae7f1b..98288e1 100644
--- a/services/oboeservice/AAudioServiceEndpointCapture.cpp
+++ b/services/oboeservice/AAudioServiceEndpointCapture.cpp
@@ -81,7 +81,7 @@
{ // brackets are for lock_guard
std::lock_guard <std::mutex> lock(mLockStreams);
- for (const auto clientStream : mRegisteredStreams) {
+ for (const auto& clientStream : mRegisteredStreams) {
if (clientStream->isRunning()) {
int64_t clientFramesWritten = 0;
sp<AAudioServiceStreamShared> streamShared =
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index e4dbee1..6c28083 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -371,7 +371,7 @@
float volume = values[0];
ALOGD("%s(%p) volume[0] = %f", __func__, this, volume);
std::lock_guard<std::mutex> lock(mLockStreams);
- for(const auto stream : mRegisteredStreams) {
+ for(const auto& stream : mRegisteredStreams) {
stream->onVolumeChanged(volume);
}
};
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.cpp b/services/oboeservice/AAudioServiceEndpointPlay.cpp
index 923a1a4..ac0d61d 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.cpp
+++ b/services/oboeservice/AAudioServiceEndpointPlay.cpp
@@ -80,7 +80,7 @@
int64_t mmapFramesWritten = getStreamInternal()->getFramesWritten();
std::lock_guard <std::mutex> lock(mLockStreams);
- for (const auto clientStream : mRegisteredStreams) {
+ for (const auto& clientStream : mRegisteredStreams) {
int64_t clientFramesRead = 0;
bool allowUnderflow = true;