Merge "Change MediaControlView2 APIs"
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 982b117..e51ec4d 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -227,6 +227,7 @@
DrmHal::DrmHal()
: mDrmSessionClient(new DrmSessionClient(this)),
mFactories(makeDrmFactories()),
+ mOpenSessionCounter("/drm/mediadrm/open_session", "status"),
mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
}
@@ -517,6 +518,8 @@
mDrmSessionClient, sessionId);
mOpenSessions.push(sessionId);
}
+
+ mOpenSessionCounter.Increment(err);
return err;
}
@@ -985,8 +988,25 @@
}
status_t DrmHal::getMetrics(MediaAnalyticsItem* metrics) {
- // TODO: Replace this with real metrics.
- metrics->setCString("/drm/mediadrm/dummymetric", "dummy");
+ // TODO: Move mOpenSessionCounter and suffixes to a separate class
+ // that manages the collection of metrics and exporting them.
+ std::string success_count_name =
+ mOpenSessionCounter.metric_name() + "/ok/count";
+ std::string error_count_name =
+ mOpenSessionCounter.metric_name() + "/error/count";
+ mOpenSessionCounter.ExportValues(
+ [&] (status_t status, int64_t value) {
+ if (status == OK) {
+ metrics->setInt64(success_count_name.c_str(), value);
+ } else {
+ int64_t total_errors(0);
+ metrics->getInt64(error_count_name.c_str(), &total_errors);
+ metrics->setInt64(error_count_name.c_str(),
+ total_errors + value);
+ // TODO: Add support for exporting the list of error values.
+ // This probably needs to be added to MediaAnalyticsItem.
+ }
+ });
return OK;
}
diff --git a/drm/libmediadrm/tests/Android.bp b/drm/libmediadrm/tests/Android.bp
new file mode 100644
index 0000000..674d3eb
--- /dev/null
+++ b/drm/libmediadrm/tests/Android.bp
@@ -0,0 +1,12 @@
+// Build definitions for unit tests.
+
+cc_test {
+ name: "CounterMetric_test",
+ srcs: ["CounterMetric_test.cpp"],
+ shared_libs: ["libmediadrm"],
+ include_dirs: ["frameworks/av/include/media"],
+ cflags: [
+ "-Werror",
+ "-Wall",
+ ],
+}
diff --git a/drm/libmediadrm/tests/CounterMetric_test.cpp b/drm/libmediadrm/tests/CounterMetric_test.cpp
new file mode 100644
index 0000000..6bca0da
--- /dev/null
+++ b/drm/libmediadrm/tests/CounterMetric_test.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "CounterMetric.h"
+
+namespace android {
+
+/**
+ * Unit tests for the CounterMetric class.
+ */
+class CounterMetricTest : public ::testing::Test {
+};
+
+TEST_F(CounterMetricTest, IntDataTypeEmpty) {
+ CounterMetric<int> metric("MyMetricName", "MetricAttributeName");
+
+ std::map<int, int64_t> values;
+
+ metric.ExportValues(
+ [&] (int attribute_value, int64_t value) {
+ values[attribute_value] = value;
+ });
+
+ EXPECT_TRUE(values.empty());
+}
+
+TEST_F(CounterMetricTest, IntDataType) {
+ CounterMetric<int> metric("MyMetricName", "MetricAttributeName");
+
+ std::map<int, int64_t> values;
+
+ metric.Increment(7);
+ metric.Increment(8);
+ metric.Increment(8);
+
+ metric.ExportValues(
+ [&] (int attribute_value, int64_t value) {
+ values[attribute_value] = value;
+ });
+
+ ASSERT_EQ(2u, values.size());
+ EXPECT_EQ(1, values[7]);
+ EXPECT_EQ(2, values[8]);
+}
+
+TEST_F(CounterMetricTest, StringDataType) {
+ CounterMetric<std::string> metric("MyMetricName", "MetricAttributeName");
+
+ std::map<std::string, int64_t> values;
+
+ metric.Increment("a");
+ metric.Increment("b");
+ metric.Increment("b");
+
+ metric.ExportValues(
+ [&] (std::string attribute_value, int64_t value) {
+ values[attribute_value] = value;
+ });
+
+ ASSERT_EQ(2u, values.size());
+ EXPECT_EQ(1, values["a"]);
+ EXPECT_EQ(2, values["b"]);
+}
+
+} // namespace android
diff --git a/include/media/CounterMetric.h b/include/media/CounterMetric.h
new file mode 120000
index 0000000..baba043
--- /dev/null
+++ b/include/media/CounterMetric.h
@@ -0,0 +1 @@
+../../media/libmedia/include/media/CounterMetric.h
\ No newline at end of file
diff --git a/media/libmedia/MediaCodecBuffer.cpp b/media/libmedia/MediaCodecBuffer.cpp
index 59d6164..68ae3ea 100644
--- a/media/libmedia/MediaCodecBuffer.cpp
+++ b/media/libmedia/MediaCodecBuffer.cpp
@@ -21,15 +21,13 @@
#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/MediaBufferBase.h>
namespace android {
MediaCodecBuffer::MediaCodecBuffer(const sp<AMessage> &format, const sp<ABuffer> &buffer)
: mMeta(new AMessage),
mFormat(format),
- mBuffer(buffer),
- mMediaBufferBase(nullptr) {
+ mBuffer(buffer) {
}
// ABuffer-like interface
@@ -58,20 +56,6 @@
return OK;
}
-MediaBufferBase *MediaCodecBuffer::getMediaBufferBase() {
- if (mMediaBufferBase != NULL) {
- mMediaBufferBase->add_ref();
- }
- return mMediaBufferBase;
-}
-
-void MediaCodecBuffer::setMediaBufferBase(MediaBufferBase *mediaBuffer) {
- if (mMediaBufferBase != NULL) {
- mMediaBufferBase->release();
- }
- mMediaBufferBase = mediaBuffer;
-}
-
sp<AMessage> MediaCodecBuffer::meta() {
return mMeta;
}
diff --git a/media/libmedia/include/media/CounterMetric.h b/media/libmedia/include/media/CounterMetric.h
new file mode 100644
index 0000000..f39ca7c
--- /dev/null
+++ b/media/libmedia/include/media/CounterMetric.h
@@ -0,0 +1,90 @@
+/*
+ * 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_COUNTER_METRIC_H_
+#define ANDROID_COUNTER_METRIC_H_
+
+#include <media/MediaAnalyticsItem.h>
+#include <utils/Log.h>
+
+namespace android {
+
+
+// The CounterMetric class is used to hold counts of operations or events.
+// A CounterMetric can break down counts by a dimension specified by the
+// application. E.g. an application may want to track counts broken out by
+// error code or the size of some parameter.
+//
+// Example:
+//
+// CounterMetric<status_t> workCounter;
+// workCounter("workCounterName", "result_status");
+//
+// status_t err = DoWork();
+//
+// // Increments the number of times called with the given error code.
+// workCounter.Increment(err);
+//
+// std::map<int, int64_t> values;
+// metric.ExportValues(
+// [&] (int attribute_value, int64_t value) {
+// values[attribute_value] = value;
+// });
+//
+// // Do something with the exported stat.
+//
+template<typename AttributeType>
+class CounterMetric {
+ public:
+ // Instantiate the counter with the given metric name and
+ // attribute names. |attribute_names| must not be null.
+ CounterMetric(
+ const std::string& metric_name,
+ const std::string& attribute_name)
+ : metric_name_(metric_name),
+ attribute_name_(attribute_name) {}
+
+ // Increment the count of times the operation occurred with this
+ // combination of attributes.
+ void Increment(AttributeType attribute) {
+ if (values_.find(attribute) == values_.end()) {
+ values_[attribute] = 1;
+ } else {
+ values_[attribute] = values_[attribute] + 1;
+ }
+ };
+
+ // Export the metrics to the provided |function|. Each value for Attribute
+ // has a separate count. As such, |function| will be called once per value
+ // of Attribute.
+ void ExportValues(
+ std::function<void (const AttributeType&,
+ const int64_t count)> function) {
+ for (auto it = values_.begin(); it != values_.end(); it++) {
+ function(it->first, it->second);
+ }
+ }
+
+ const std::string& metric_name() { return metric_name_; };
+
+ private:
+ const std::string metric_name_;
+ const std::string attribute_name_;
+ std::map<AttributeType, int64_t> values_;
+};
+
+} // namespace android
+
+#endif // ANDROID_COUNTER_METRIC_H_
diff --git a/media/libmedia/include/media/DrmHal.h b/media/libmedia/include/media/DrmHal.h
index 1a0553e..f2b25cd 100644
--- a/media/libmedia/include/media/DrmHal.h
+++ b/media/libmedia/include/media/DrmHal.h
@@ -23,6 +23,7 @@
#include <android/hardware/drm/1.0/IDrmPluginListener.h>
#include <android/hardware/drm/1.0/IDrmFactory.h>
+#include <media/CounterMetric.h>
#include <media/IDrm.h>
#include <media/IDrmClient.h>
#include <media/MediaAnalyticsItem.h>
@@ -180,6 +181,8 @@
sp<IDrmPlugin> mPlugin;
sp<drm::V1_1::IDrmPlugin> mPluginV1_1;
+ CounterMetric<status_t> mOpenSessionCounter;
+
Vector<Vector<uint8_t>> mOpenSessions;
void closeOpenSessions();
diff --git a/media/libmedia/include/media/MediaBufferHolder.h b/media/libmedia/include/media/MediaBufferHolder.h
new file mode 100644
index 0000000..e8e2c4b
--- /dev/null
+++ b/media/libmedia/include/media/MediaBufferHolder.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 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 MEDIA_BUFFER_HOLDER_H_
+
+#define MEDIA_BUFFER_HOLDER_H_
+
+#include <media/stagefright/MediaBuffer.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct MediaBufferHolder : public RefBase {
+ MediaBufferHolder(MediaBuffer* buffer)
+ : mMediaBuffer(buffer) {
+ if (mMediaBuffer != nullptr) {
+ mMediaBuffer->add_ref();
+ }
+ }
+
+ virtual ~MediaBufferHolder() {
+ if (mMediaBuffer != nullptr) {
+ mMediaBuffer->release();
+ }
+ }
+
+ MediaBuffer* mediaBuffer() { return mMediaBuffer; }
+
+private:
+ MediaBuffer* const mMediaBuffer;
+};
+
+} // android
+
+#endif // MEDIA_BUFFER_HOLDER_H_
diff --git a/media/libmedia/include/media/MediaCodecBuffer.h b/media/libmedia/include/media/MediaCodecBuffer.h
index 501c00b..2c16fba 100644
--- a/media/libmedia/include/media/MediaCodecBuffer.h
+++ b/media/libmedia/include/media/MediaCodecBuffer.h
@@ -50,9 +50,6 @@
size_t offset() const;
// Default implementation calls ABuffer::setRange() and returns OK.
virtual status_t setRange(size_t offset, size_t size);
- // TODO: These can be removed if we finish replacing all MediaBuffer's.
- MediaBufferBase *getMediaBufferBase();
- void setMediaBufferBase(MediaBufferBase *mediaBuffer);
// TODO: Specify each field for meta/format.
sp<AMessage> meta();
@@ -66,7 +63,6 @@
const sp<AMessage> mMeta;
sp<AMessage> mFormat;
const sp<ABuffer> mBuffer;
- MediaBufferBase *mMediaBufferBase;
};
} // namespace android
diff --git a/media/libmedia/nuplayer2/GenericSource.cpp b/media/libmedia/nuplayer2/GenericSource.cpp
index c0b81fb..6d5b14d 100644
--- a/media/libmedia/nuplayer2/GenericSource.cpp
+++ b/media/libmedia/nuplayer2/GenericSource.cpp
@@ -24,6 +24,7 @@
#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <media/DataSource.h>
+#include <media/MediaBufferHolder.h>
#include <media/IMediaExtractorService.h>
#include <media/MediaHTTPService.h>
#include <media/MediaExtractor.h>
@@ -1167,8 +1168,7 @@
// data is already provided in the buffer
ab = new ABuffer(NULL, mb->range_length());
- mb->add_ref();
- ab->setMediaBufferBase(mb);
+ ab->meta()->setObject("mediaBufferHolder", new MediaBufferHolder(mb));
// Modular DRM: Required b/c of the above add_ref.
// If ref>0, there must be an observer, or it'll crash at release().
diff --git a/media/libmedia/nuplayer2/NuPlayer2Decoder.cpp b/media/libmedia/nuplayer2/NuPlayer2Decoder.cpp
index 715d6fc..a436592 100644
--- a/media/libmedia/nuplayer2/NuPlayer2Decoder.cpp
+++ b/media/libmedia/nuplayer2/NuPlayer2Decoder.cpp
@@ -28,6 +28,7 @@
#include "NuPlayer2Source.h"
#include <cutils/properties.h>
+#include <media/MediaBufferHolder.h>
#include <media/MediaCodecBuffer.h>
#include <media/NdkMediaCodec.h>
#include <media/NdkWrapper.h>
@@ -1081,16 +1082,17 @@
memcpy(codecBuffer->data(), buffer->data(), buffer->size());
} else { // No buffer->data()
//Modular DRM
- mediaBuf = (MediaBuffer*)buffer->getMediaBufferBase();
+ sp<RefBase> holder;
+ if (buffer->meta()->findObject("mediaBufferHolder", &holder)) {
+ mediaBuf = (holder != nullptr) ?
+ static_cast<MediaBufferHolder*>(holder.get())->mediaBuffer() : nullptr;
+ }
if (mediaBuf != NULL) {
codecBuffer->setRange(0, mediaBuf->size());
memcpy(codecBuffer->data(), mediaBuf->data(), mediaBuf->size());
sp<MetaData> meta_data = mediaBuf->meta_data();
cryptInfo = AMediaCodecCryptoInfoWrapper::Create(meta_data);
-
- // since getMediaBuffer() has incremented the refCount
- mediaBuf->release();
} else { // No mediaBuf
ALOGE("onInputBufferFetched: buffer->data()/mediaBuf are NULL for %p",
buffer.get());
diff --git a/media/libmediaextractor/Android.bp b/media/libmediaextractor/Android.bp
index 18573db..83fea39 100644
--- a/media/libmediaextractor/Android.bp
+++ b/media/libmediaextractor/Android.bp
@@ -15,6 +15,7 @@
],
shared_libs: [
+ "libbinder",
"libstagefright_foundation",
"libutils",
"libcutils",
@@ -23,6 +24,8 @@
srcs: [
"DataSource.cpp",
+ "MediaBuffer.cpp",
+ "MediaBufferGroup.cpp",
"MediaSource.cpp",
"MediaExtractor.cpp",
],
diff --git a/media/libstagefright/foundation/MediaBuffer.cpp b/media/libmediaextractor/MediaBuffer.cpp
similarity index 98%
rename from media/libstagefright/foundation/MediaBuffer.cpp
rename to media/libmediaextractor/MediaBuffer.cpp
index 95951dd..28fc760 100644
--- a/media/libstagefright/foundation/MediaBuffer.cpp
+++ b/media/libmediaextractor/MediaBuffer.cpp
@@ -26,8 +26,6 @@
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MetaData.h>
-#include <ui/GraphicBuffer.h>
-
namespace android {
/* static */
diff --git a/media/libstagefright/foundation/MediaBufferGroup.cpp b/media/libmediaextractor/MediaBufferGroup.cpp
similarity index 100%
rename from media/libstagefright/foundation/MediaBufferGroup.cpp
rename to media/libmediaextractor/MediaBufferGroup.cpp
diff --git a/media/libstagefright/include/media/stagefright/MediaBuffer.h b/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
similarity index 97%
rename from media/libstagefright/include/media/stagefright/MediaBuffer.h
rename to media/libmediaextractor/include/media/stagefright/MediaBuffer.h
index 367a467..2b51081 100644
--- a/media/libstagefright/include/media/stagefright/MediaBuffer.h
+++ b/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
@@ -20,7 +20,6 @@
#include <atomic>
#include <list>
-#include <media/stagefright/foundation/MediaBufferBase.h>
#include <pthread.h>
@@ -48,7 +47,7 @@
MediaBufferObserver &operator=(const MediaBufferObserver &);
};
-class MediaBuffer : public MediaBufferBase {
+class MediaBuffer {
public:
// allocations larger than or equal to this will use shared memory.
static const size_t kSharedMemThreshold = 64 * 1024;
@@ -72,11 +71,11 @@
//
// If no MediaBufferGroup is set, the local reference count must be zero
// when called, whereupon the MediaBuffer is deleted.
- virtual void release();
+ void release();
// Increments the local reference count.
// Use only when MediaBufferGroup is set.
- virtual void add_ref();
+ void add_ref();
void *data() const;
size_t size() const;
@@ -144,7 +143,7 @@
return mObserver != nullptr;
}
- virtual ~MediaBuffer();
+ ~MediaBuffer();
sp<IMemory> mMemory;
diff --git a/media/libstagefright/include/media/stagefright/MediaBufferGroup.h b/media/libmediaextractor/include/media/stagefright/MediaBufferGroup.h
similarity index 100%
rename from media/libstagefright/include/media/stagefright/MediaBufferGroup.h
rename to media/libmediaextractor/include/media/stagefright/MediaBufferGroup.h
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index 33c3094..511f46f 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -24,6 +24,7 @@
#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <media/DataSource.h>
+#include <media/MediaBufferHolder.h>
#include <media/MediaExtractor.h>
#include <media/MediaSource.h>
#include <media/IMediaHTTPService.h>
@@ -1160,14 +1161,12 @@
// data is already provided in the buffer
ab = new ABuffer(NULL, mb->range_length());
- mb->add_ref();
- ab->setMediaBufferBase(mb);
+ ab->meta()->setObject("mediaBufferHolder", new MediaBufferHolder(mb));
// Modular DRM: Required b/c of the above add_ref.
// If ref>0, there must be an observer, or it'll crash at release().
// TODO: MediaBuffer might need to be revised to ease such need.
mb->setObserver(this);
- // setMediaBufferBase() interestingly doesn't increment the ref count on its own.
// Extra increment (since we want to keep mb alive and attached to ab beyond this function
// call. This is to counter the effect of mb->release() towards the end.
mb->add_ref();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 1b02adb..1aca96c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -29,6 +29,7 @@
#include <cutils/properties.h>
#include <media/ICrypto.h>
+#include <media/MediaBufferHolder.h>
#include <media/MediaCodecBuffer.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -1061,16 +1062,17 @@
memcpy(codecBuffer->data(), buffer->data(), buffer->size());
} else { // No buffer->data()
//Modular DRM
- mediaBuf = (MediaBuffer*)buffer->getMediaBufferBase();
+ sp<RefBase> holder;
+ if (buffer->meta()->findObject("mediaBufferHolder", &holder)) {
+ mediaBuf = (holder != nullptr) ?
+ static_cast<MediaBufferHolder*>(holder.get())->mediaBuffer() : nullptr;
+ }
if (mediaBuf != NULL) {
codecBuffer->setRange(0, mediaBuf->size());
memcpy(codecBuffer->data(), mediaBuf->data(), mediaBuf->size());
sp<MetaData> meta_data = mediaBuf->meta_data();
cryptInfo = NuPlayerDrm::getSampleCryptoInfo(meta_data);
-
- // since getMediaBuffer() has incremented the refCount
- mediaBuf->release();
} else { // No mediaBuf
ALOGE("onInputBufferFetched: buffer->data()/mediaBuf are NULL for %p",
buffer.get());
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 14ea2a8..0ded5be 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -43,6 +43,7 @@
#include <media/stagefright/PersistentSurface.h>
#include <media/stagefright/SurfaceUtils.h>
#include <media/hardware/HardwareAPI.h>
+#include <media/MediaBufferHolder.h>
#include <media/OMXBuffer.h>
#include <media/omx/1.0/WOmxNode.h>
@@ -5606,7 +5607,7 @@
// by this "MediaBuffer" object. Now that the OMX component has
// told us that it's done with the input buffer, we can decrement
// the mediaBuffer's reference count.
- info->mData->setMediaBufferBase(NULL);
+ info->mData->meta()->setObject("mediaBufferHolder", sp<MediaBufferHolder>(nullptr));
PortMode mode = getPortMode(kPortIndexInput);
diff --git a/media/libstagefright/CCodecBufferChannel.cpp b/media/libstagefright/CCodecBufferChannel.cpp
index eea9c78..ebc9b0a 100644
--- a/media/libstagefright/CCodecBufferChannel.cpp
+++ b/media/libstagefright/CCodecBufferChannel.cpp
@@ -665,16 +665,16 @@
int32_t flags = 0;
int32_t tmp = 0;
if (buffer->meta()->findInt32("eos", &tmp) && tmp) {
- flags |= C2BufferPack::FLAG_END_OF_STREAM;
+ flags |= C2FrameData::FLAG_END_OF_STREAM;
ALOGV("input EOS");
}
if (buffer->meta()->findInt32("csd", &tmp) && tmp) {
- flags |= C2BufferPack::FLAG_CODEC_CONFIG;
+ flags |= C2FrameData::FLAG_CODEC_CONFIG;
}
std::unique_ptr<C2Work> work(new C2Work);
- work->input.flags = (C2BufferPack::flags_t)flags;
+ work->input.flags = (C2FrameData::flags_t)flags;
work->input.ordinal.timestamp = timeUs;
- work->input.ordinal.frame_index = mFrameIndex++;
+ work->input.ordinal.frameIndex = mFrameIndex++;
work->input.buffers.clear();
{
Mutexed<std::unique_ptr<InputBuffers>>::Locked buffers(mInputBuffers);
@@ -724,7 +724,7 @@
return OK;
}
- std::list<C2ConstGraphicBlock> blocks = c2Buffer->data().graphicBlocks();
+ std::vector<C2ConstGraphicBlock> blocks = c2Buffer->data().graphicBlocks();
if (blocks.size() != 1u) {
ALOGE("# of graphic blocks expected to be 1, but %zu", blocks.size());
return UNKNOWN_ERROR;
@@ -881,7 +881,7 @@
}
const std::unique_ptr<C2Worklet> &worklet = work->worklets.front();
- if (worklet->output.ordinal.frame_index < mFirstValidFrameIndex) {
+ if ((worklet->output.ordinal.frameIndex - mFirstValidFrameIndex.load()).peek() < 0) {
// Discard frames from previous generation.
continue;
}
@@ -897,7 +897,7 @@
if (buffer) {
// TODO: transfer infos() into buffer metadata
}
- for (const auto &info : worklet->output.infos) {
+ for (const auto &info : worklet->output.configUpdate) {
if (info->coreIndex() == C2StreamCsdInfo::output::CORE_INDEX) {
ALOGV("csd found");
csdInfo = static_cast<const C2StreamCsdInfo::output *>(info.get());
@@ -905,7 +905,7 @@
}
int32_t flags = 0;
- if (worklet->output.flags & C2BufferPack::FLAG_END_OF_STREAM) {
+ if (worklet->output.flags & C2FrameData::FLAG_END_OF_STREAM) {
flags |= MediaCodec::BUFFER_FLAG_EOS;
ALOGV("output EOS");
}
@@ -914,7 +914,7 @@
if (csdInfo != nullptr) {
Mutexed<std::unique_ptr<OutputBuffers>>::Locked buffers(mOutputBuffers);
if ((*buffers)->registerCsd(csdInfo, &index, &outBuffer)) {
- outBuffer->meta()->setInt64("timeUs", worklet->output.ordinal.timestamp);
+ outBuffer->meta()->setInt64("timeUs", worklet->output.ordinal.timestamp.peek());
outBuffer->meta()->setInt32("flags", flags | MediaCodec::BUFFER_FLAG_CODECCONFIG);
ALOGV("csd index = %zu", index);
@@ -947,7 +947,7 @@
}
}
- outBuffer->meta()->setInt64("timeUs", worklet->output.ordinal.timestamp);
+ outBuffer->meta()->setInt64("timeUs", worklet->output.ordinal.timestamp.peek());
outBuffer->meta()->setInt32("flags", flags);
ALOGV("index = %zu", index);
mCallback->onOutputBufferAvailable(index, outBuffer);
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 8bd0a51..04d83af 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -23,6 +23,7 @@
#include <gui/IGraphicBufferProducer.h>
#include <gui/Surface.h>
#include <media/ICrypto.h>
+#include <media/MediaBufferHolder.h>
#include <media/MediaCodecBuffer.h>
#include <media/MediaSource.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -739,7 +740,8 @@
if (mIsVideo) {
// video encoder will release MediaBuffer when done
// with underlying data.
- inbuf->setMediaBufferBase(mbuf);
+ inbuf->meta()->setObject("mediaBufferHolder", new MediaBufferHolder(mbuf));
+ mbuf->release();
} else {
mbuf->release();
}
diff --git a/media/libstagefright/codec2/SimpleC2Component.cpp b/media/libstagefright/codec2/SimpleC2Component.cpp
index 4d75a31..c3ae00e 100644
--- a/media/libstagefright/codec2/SimpleC2Component.cpp
+++ b/media/libstagefright/codec2/SimpleC2Component.cpp
@@ -342,7 +342,7 @@
return;
}
}
- if (work->worklets_processed != 0u) {
+ if (work->workletsProcessed != 0u) {
Mutexed<ExecState>::Locked state(mExecState);
ALOGV("returning this work");
state->mListener->onWorkDone_nb(shared_from_this(), vec(work));
@@ -351,7 +351,7 @@
std::unique_ptr<C2Work> unexpected;
{
Mutexed<PendingWork>::Locked pending(mPendingWork);
- uint64_t frameIndex = work->input.ordinal.frame_index;
+ uint64_t frameIndex = work->input.ordinal.frameIndex.peeku();
if (pending->count(frameIndex) != 0) {
unexpected = std::move(pending->at(frameIndex));
pending->erase(frameIndex);
diff --git a/media/libstagefright/codec2/include/C2Buffer.h b/media/libstagefright/codec2/include/C2Buffer.h
index cd90978..2ca8222 100644
--- a/media/libstagefright/codec2/include/C2Buffer.h
+++ b/media/libstagefright/codec2/include/C2Buffer.h
@@ -679,14 +679,14 @@
*
* \param size number of bytes to share
* \param fence fence to be used for the section
- * \param blocks list where the blocks of the section are appended to
+ * \param blocks vector where the blocks of the section are appended to
*
* \retval C2_OK the portion was successfully shared
* \retval C2_NO_MEMORY not enough memory to share the portion
* \retval C2_TIMED_OUT the operation timed out (unexpected)
* \retval C2_CORRUPTED some unknown error prevented sharing the data (unexpected)
*/
- c2_status_t share(size_t size, C2Fence fence, std::list<C2ConstLinearBlock> &blocks);
+ c2_status_t share(size_t size, C2Fence fence, std::vector<C2ConstLinearBlock> &blocks);
/**
* Returns the beginning offset of this segment from the start of this circular block.
@@ -1203,14 +1203,14 @@
* \return a constant list of const linear blocks of this buffer.
* \retval empty list if this buffer does not contain linear block(s).
*/
- const std::list<C2ConstLinearBlock> linearBlocks() const;
+ const std::vector<C2ConstLinearBlock> linearBlocks() const;
/**
* Gets the graphic blocks of this buffer.
* \return a constant list of const graphic blocks of this buffer.
* \retval empty list if this buffer does not contain graphic block(s).
*/
- const std::list<C2ConstGraphicBlock> graphicBlocks() const;
+ const std::vector<C2ConstGraphicBlock> graphicBlocks() const;
private:
class Impl;
@@ -1218,8 +1218,8 @@
protected:
// no public constructor
- explicit C2BufferData(const std::list<C2ConstLinearBlock> &blocks);
- explicit C2BufferData(const std::list<C2ConstGraphicBlock> &blocks);
+ explicit C2BufferData(const std::vector<C2ConstLinearBlock> &blocks);
+ explicit C2BufferData(const std::vector<C2ConstGraphicBlock> &blocks);
};
/**
@@ -1301,7 +1301,7 @@
*
* \return a constant list of info objects associated with this buffer.
*/
- const std::list<std::shared_ptr<const C2Info>> infos() const;
+ const std::vector<std::shared_ptr<const C2Info>> info() const;
/**
* Attaches (or updates) an (existing) metadata for this buffer.
@@ -1328,8 +1328,8 @@
protected:
// no public constructor
- explicit C2Buffer(const std::list<C2ConstLinearBlock> &blocks);
- explicit C2Buffer(const std::list<C2ConstGraphicBlock> &blocks);
+ explicit C2Buffer(const std::vector<C2ConstLinearBlock> &blocks);
+ explicit C2Buffer(const std::vector<C2ConstGraphicBlock> &blocks);
private:
class Impl;
diff --git a/media/libstagefright/codec2/include/C2Component.h b/media/libstagefright/codec2/include/C2Component.h
index a2168a0..e023db4 100644
--- a/media/libstagefright/codec2/include/C2Component.h
+++ b/media/libstagefright/codec2/include/C2Component.h
@@ -682,7 +682,7 @@
*/
virtual c2_status_t reset() { return C2_OK; }
- virtual c2_status_t parseFrame(C2BufferPack &frame);
+ virtual c2_status_t parseFrame(C2FrameData &frame);
virtual ~C2FrameInfoParser() = default;
};
diff --git a/media/libstagefright/codec2/include/C2Param.h b/media/libstagefright/codec2/include/C2Param.h
index 0540155..e2df62d 100644
--- a/media/libstagefright/codec2/include/C2Param.h
+++ b/media/libstagefright/codec2/include/C2Param.h
@@ -721,6 +721,10 @@
DEFINE_OTHER_COMPARISON_OPERATORS(C2ParamField)
+protected:
+ inline C2ParamField(C2Param::Index index, uint32_t offset, uint32_t size)
+ : _mIndex(index), _mFieldId(offset, size) {}
+
private:
friend struct _C2ParamInspector;
@@ -729,6 +733,17 @@
};
/**
+ * Structure uniquely specifying a field, an array element of a field, or a
+ * parameter in a configuration
+ */
+struct C2ParamOrField : public C2ParamField {
+//public:
+ template<typename S>
+ inline C2ParamOrField(S* param)
+ : C2ParamField(param->index(), 0u, param->size()) {}
+};
+
+/**
* A shared (union) representation of numeric values
*/
class C2Value {
diff --git a/media/libstagefright/codec2/include/C2Work.h b/media/libstagefright/codec2/include/C2Work.h
index 105cf81..58a9174 100644
--- a/media/libstagefright/codec2/include/C2Work.h
+++ b/media/libstagefright/codec2/include/C2Work.h
@@ -83,32 +83,64 @@
kParamIndexWorkOrdinal,
};
+/**
+ * Information for ordering work items on a component port.
+ */
struct C2WorkOrdinalStruct {
- uint64_t timestamp;
- uint64_t frame_index; // submission ordinal on the initial component
- uint64_t custom_ordinal; // can be given by the component, e.g. decode order
+//public:
+ c2_cntr64_t timestamp; /** frame timestamp in microseconds */
+ c2_cntr64_t frameIndex; /** submission ordinal on the initial component */
+ c2_cntr64_t customOrdinal; /** can be given by the component, e.g. decode order */
DEFINE_AND_DESCRIBE_C2STRUCT(WorkOrdinal)
C2FIELD(timestamp, "timestamp")
- C2FIELD(frame_index, "frame-index")
- C2FIELD(custom_ordinal, "custom-ordinal")
+ C2FIELD(frameIndex, "frame-index")
+ C2FIELD(customOrdinal, "custom-ordinal")
};
-struct C2BufferPack {
+/**
+ * This structure represents a Codec 2.0 frame with its metadata.
+ *
+ * A frame basically consists of an ordered sets of buffers, configuration changes and info buffers
+ * along with some non-configuration metadata.
+ */
+struct C2FrameData {
//public:
enum flags_t : uint32_t {
- FLAG_CODEC_CONFIG = (1 << 0),
- FLAG_DROP_FRAME = (1 << 1),
- FLAG_END_OF_STREAM = (1 << 2),
+ /**
+ * For input frames: no output frame shall be generated when processing this frame, but
+ * metadata shall still be processed.
+ * For output frames: this frame shall be discarded and but metadata is still valid.
+ */
+ FLAG_DROP_FRAME = (1 << 0),
+ /**
+ * This frame is the last frame of the current stream. Further frames are part of a new
+ * stream.
+ */
+ FLAG_END_OF_STREAM = (1 << 1),
+ /**
+ * This frame shall be discarded with its metadata.
+ * This flag is only set by components - e.g. as a response to the flush command.
+ */
+ FLAG_DISCARD_FRAME = (1 << 2),
+ /**
+ * This frame contains only codec-specific configuration data, and no actual access unit.
+ *
+ * \deprecated pass codec configuration with using the \todo codec-specific configuration
+ * info together with the access unit.
+ */
+ FLAG_CODEC_CONFIG = (1u << 31),
};
+ /**
+ * Frame flags */
flags_t flags;
C2WorkOrdinalStruct ordinal;
std::vector<std::shared_ptr<C2Buffer>> buffers;
//< for initial work item, these may also come from the parser - if provided
//< for output buffers, these are the responses to requestedInfos
- std::list<std::unique_ptr<C2Info>> infos;
- std::list<std::shared_ptr<C2InfoBuffer>> infoBuffers;
+ std::vector<std::unique_ptr<C2Param>> configUpdate;
+ std::vector<std::shared_ptr<C2InfoBuffer>> infoBuffers;
};
struct C2Worklet {
@@ -116,59 +148,61 @@
// IN
c2_node_id_t component;
- std::list<std::unique_ptr<C2Param>> tunings; //< tunings to be applied before processing this
- // worklet
- std::list<C2Param::Type> requestedInfos;
- std::vector<std::shared_ptr<C2BlockPool>> allocators; //< This vector shall be the same size as
- //< output.buffers. \deprecated
+ /** Configuration changes to be applied before processing this worklet. */
+ std::vector<std::unique_ptr<C2Tuning>> tunings;
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
// OUT
- C2BufferPack output;
- std::list<std::unique_ptr<C2SettingResult>> failures;
+ C2FrameData output;
};
/**
+ * Information about partial work-chains not part of the current work items.
+ *
+ * To be defined later.
+ */
+struct C2WorkChainInfo;
+
+/**
* This structure holds information about all a single work item.
*
* This structure shall be passed by the client to the component for the first worklet. As such,
* worklets must not be empty. The ownership of this object is passed.
- *
- * input:
- * The input data to be processed. This is provided by the client with ownership. When the work
- * is returned, the input buffer-pack's buffer vector shall contain nullptrs.
- *
- * worklets:
- * The chain of components and associated allocators, tunings and info requests that the data
- * must pass through. If this has more than a single element, the tunnels between successive
- * components of the worklet chain must have been (successfully) pre-registered at the time
- * the work is submitted. Allocating the output buffers in the worklets is the responsibility
- * of each component. Upon work submission, each output buffer-pack shall be an appropriately
- * sized vector containing nullptrs. When the work is completed/returned to the client,
- *
- * worklets_processed:
- * It shall be initialized to 0 by the client when the work is submitted.
- * It shall contain the number of worklets that were successfully processed when the work is
- * returned. If this is less then the number of worklets, result must not be success.
- * It must be in the range of [0, worklets.size()].
- *
- * result:
- * The final outcome of the work. If 0 when work is returned, it is assumed that all worklets
- * have been processed.
*/
struct C2Work {
//public:
- // pre-chain infos (for portions of a tunneling chain that happend before this work-chain for
- // this work item - due to framework facilitated (non-tunneled) work-chaining)
- std::list<std::pair<std::unique_ptr<C2PortMimeConfig>, std::unique_ptr<C2Info>>> preChainInfos;
- std::list<std::pair<std::unique_ptr<C2PortMimeConfig>, std::unique_ptr<C2Buffer>>> preChainInfoBlobs;
+ /// additional work chain info not part of this work
+ std::shared_ptr<C2WorkChainInfo> chainInfo;
- C2BufferPack input;
+ /// The input data to be processed as part of this work/work-chain. This is provided by the
+ /// client with ownership. When the work is returned (via onWorkDone), the input buffer-pack's
+ /// buffer vector shall contain nullptrs.
+ C2FrameData input;
+
+ /// The chain of components, tunings (including output buffer pool IDs) and info requests that the
+ /// data must pass through. If this has more than a single element, the tunnels between successive
+ /// components of the worklet chain must have been (successfully) pre-registered at the time that
+ /// the work is submitted. Allocating the output buffers in the worklets is the responsibility of
+ /// each component. Upon work submission, each output buffer-pack shall be an appropriately sized
+ /// vector containing nullptrs. When the work is completed/returned to the client, output buffers
+ /// pointers from all but the final worklet shall be nullptrs.
std::list<std::unique_ptr<C2Worklet>> worklets;
- uint32_t worklets_processed;
+ /// Number of worklets successfully processed in this chain. This shall be initialized to 0 by the
+ /// client when the work is submitted. It shall contain the number of worklets that were
+ /// successfully processed when the work is returned to the client. If this is less then the number
+ /// of worklets, result must not be success. It must be in the range of [0, worklets.size()].
+ uint32_t workletsProcessed;
+
+ /// The final outcome of the work (corresponding to the current workletsProcessed). If 0 when
+ /// work is returned, it is assumed that all worklets have been processed.
c2_status_t result;
};
+/**
+ * Information about a future work to be submitted to the component. The information is used to
+ * reserve the work for work ordering purposes.
+ */
struct C2WorkOutline {
//public:
C2WorkOrdinalStruct ordinal;
diff --git a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
index f6e6478..a310717 100644
--- a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
+++ b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
@@ -359,14 +359,14 @@
class BufferData : public C2BufferData {
public:
- explicit BufferData(const std::list<C2ConstLinearBlock> &blocks) : C2BufferData(blocks) {}
- explicit BufferData(const std::list<C2ConstGraphicBlock> &blocks) : C2BufferData(blocks) {}
+ explicit BufferData(const std::vector<C2ConstLinearBlock> &blocks) : C2BufferData(blocks) {}
+ explicit BufferData(const std::vector<C2ConstGraphicBlock> &blocks) : C2BufferData(blocks) {}
};
class Buffer : public C2Buffer {
public:
- explicit Buffer(const std::list<C2ConstLinearBlock> &blocks) : C2Buffer(blocks) {}
- explicit Buffer(const std::list<C2ConstGraphicBlock> &blocks) : C2Buffer(blocks) {}
+ explicit Buffer(const std::vector<C2ConstLinearBlock> &blocks) : C2Buffer(blocks) {}
+ explicit Buffer(const std::vector<C2ConstGraphicBlock> &blocks) : C2Buffer(blocks) {}
};
TEST_F(C2BufferTest, BufferDataTest) {
@@ -487,45 +487,45 @@
std::shared_ptr<C2Info> info1(new C2Number1Info(1));
std::shared_ptr<C2Info> info2(new C2Number2Info(2));
buffer.reset(new Buffer( { block->share(0, kCapacity, C2Fence()) }));
- EXPECT_TRUE(buffer->infos().empty());
+ EXPECT_TRUE(buffer->info().empty());
EXPECT_FALSE(buffer->hasInfo(info1->type()));
EXPECT_FALSE(buffer->hasInfo(info2->type()));
ASSERT_EQ(C2_OK, buffer->setInfo(info1));
- EXPECT_EQ(1u, buffer->infos().size());
- EXPECT_EQ(*info1, *buffer->infos().front());
+ EXPECT_EQ(1u, buffer->info().size());
+ EXPECT_EQ(*info1, *buffer->info().front());
EXPECT_TRUE(buffer->hasInfo(info1->type()));
EXPECT_FALSE(buffer->hasInfo(info2->type()));
ASSERT_EQ(C2_OK, buffer->setInfo(info2));
- EXPECT_EQ(2u, buffer->infos().size());
+ EXPECT_EQ(2u, buffer->info().size());
EXPECT_TRUE(buffer->hasInfo(info1->type()));
EXPECT_TRUE(buffer->hasInfo(info2->type()));
std::shared_ptr<C2Info> removed = buffer->removeInfo(info1->type());
ASSERT_TRUE(removed);
EXPECT_EQ(*removed, *info1);
- EXPECT_EQ(1u, buffer->infos().size());
- EXPECT_EQ(*info2, *buffer->infos().front());
+ EXPECT_EQ(1u, buffer->info().size());
+ EXPECT_EQ(*info2, *buffer->info().front());
EXPECT_FALSE(buffer->hasInfo(info1->type()));
EXPECT_TRUE(buffer->hasInfo(info2->type()));
removed = buffer->removeInfo(info1->type());
ASSERT_FALSE(removed);
- EXPECT_EQ(1u, buffer->infos().size());
+ EXPECT_EQ(1u, buffer->info().size());
EXPECT_FALSE(buffer->hasInfo(info1->type()));
EXPECT_TRUE(buffer->hasInfo(info2->type()));
std::shared_ptr<C2Info> info3(new C2Number2Info(3));
ASSERT_EQ(C2_OK, buffer->setInfo(info3));
- EXPECT_EQ(1u, buffer->infos().size());
+ EXPECT_EQ(1u, buffer->info().size());
EXPECT_FALSE(buffer->hasInfo(info1->type()));
EXPECT_TRUE(buffer->hasInfo(info2->type()));
removed = buffer->removeInfo(info2->type());
ASSERT_TRUE(removed);
EXPECT_EQ(*info3, *removed);
- EXPECT_TRUE(buffer->infos().empty());
+ EXPECT_TRUE(buffer->info().empty());
EXPECT_FALSE(buffer->hasInfo(info1->type()));
EXPECT_FALSE(buffer->hasInfo(info2->type()));
}
diff --git a/media/libstagefright/codec2/vndk/C2Buffer.cpp b/media/libstagefright/codec2/vndk/C2Buffer.cpp
index 65a271e..4ab3e05 100644
--- a/media/libstagefright/codec2/vndk/C2Buffer.cpp
+++ b/media/libstagefright/codec2/vndk/C2Buffer.cpp
@@ -602,44 +602,44 @@
class C2BufferData::Impl {
public:
- explicit Impl(const std::list<C2ConstLinearBlock> &blocks)
+ explicit Impl(const std::vector<C2ConstLinearBlock> &blocks)
: mType(blocks.size() == 1 ? LINEAR : LINEAR_CHUNKS),
mLinearBlocks(blocks) {
}
- explicit Impl(const std::list<C2ConstGraphicBlock> &blocks)
+ explicit Impl(const std::vector<C2ConstGraphicBlock> &blocks)
: mType(blocks.size() == 1 ? GRAPHIC : GRAPHIC_CHUNKS),
mGraphicBlocks(blocks) {
}
Type type() const { return mType; }
- const std::list<C2ConstLinearBlock> &linearBlocks() const { return mLinearBlocks; }
- const std::list<C2ConstGraphicBlock> &graphicBlocks() const { return mGraphicBlocks; }
+ const std::vector<C2ConstLinearBlock> &linearBlocks() const { return mLinearBlocks; }
+ const std::vector<C2ConstGraphicBlock> &graphicBlocks() const { return mGraphicBlocks; }
private:
Type mType;
- std::list<C2ConstLinearBlock> mLinearBlocks;
- std::list<C2ConstGraphicBlock> mGraphicBlocks;
+ std::vector<C2ConstLinearBlock> mLinearBlocks;
+ std::vector<C2ConstGraphicBlock> mGraphicBlocks;
};
-C2BufferData::C2BufferData(const std::list<C2ConstLinearBlock> &blocks) : mImpl(new Impl(blocks)) {}
-C2BufferData::C2BufferData(const std::list<C2ConstGraphicBlock> &blocks) : mImpl(new Impl(blocks)) {}
+C2BufferData::C2BufferData(const std::vector<C2ConstLinearBlock> &blocks) : mImpl(new Impl(blocks)) {}
+C2BufferData::C2BufferData(const std::vector<C2ConstGraphicBlock> &blocks) : mImpl(new Impl(blocks)) {}
C2BufferData::Type C2BufferData::type() const { return mImpl->type(); }
-const std::list<C2ConstLinearBlock> C2BufferData::linearBlocks() const {
+const std::vector<C2ConstLinearBlock> C2BufferData::linearBlocks() const {
return mImpl->linearBlocks();
}
-const std::list<C2ConstGraphicBlock> C2BufferData::graphicBlocks() const {
+const std::vector<C2ConstGraphicBlock> C2BufferData::graphicBlocks() const {
return mImpl->graphicBlocks();
}
class C2Buffer::Impl {
public:
- Impl(C2Buffer *thiz, const std::list<C2ConstLinearBlock> &blocks)
+ Impl(C2Buffer *thiz, const std::vector<C2ConstLinearBlock> &blocks)
: mThis(thiz), mData(blocks) {}
- Impl(C2Buffer *thiz, const std::list<C2ConstGraphicBlock> &blocks)
+ Impl(C2Buffer *thiz, const std::vector<C2ConstGraphicBlock> &blocks)
: mThis(thiz), mData(blocks) {}
~Impl() {
@@ -676,8 +676,8 @@
return C2_OK;
}
- std::list<std::shared_ptr<const C2Info>> infos() const {
- std::list<std::shared_ptr<const C2Info>> result(mInfos.size());
+ std::vector<std::shared_ptr<const C2Info>> info() const {
+ std::vector<std::shared_ptr<const C2Info>> result(mInfos.size());
std::transform(
mInfos.begin(), mInfos.end(), result.begin(),
[] (const auto &elem) { return elem.second; });
@@ -712,10 +712,10 @@
std::list<std::pair<OnDestroyNotify, void *>> mNotify;
};
-C2Buffer::C2Buffer(const std::list<C2ConstLinearBlock> &blocks)
+C2Buffer::C2Buffer(const std::vector<C2ConstLinearBlock> &blocks)
: mImpl(new Impl(this, blocks)) {}
-C2Buffer::C2Buffer(const std::list<C2ConstGraphicBlock> &blocks)
+C2Buffer::C2Buffer(const std::vector<C2ConstGraphicBlock> &blocks)
: mImpl(new Impl(this, blocks)) {}
const C2BufferData C2Buffer::data() const { return mImpl->data(); }
@@ -728,8 +728,8 @@
return mImpl->unregisterOnDestroyNotify(onDestroyNotify, arg);
}
-const std::list<std::shared_ptr<const C2Info>> C2Buffer::infos() const {
- return mImpl->infos();
+const std::vector<std::shared_ptr<const C2Info>> C2Buffer::info() const {
+ return mImpl->info();
}
c2_status_t C2Buffer::setInfo(const std::shared_ptr<C2Info> &info) {
diff --git a/media/libstagefright/codecs/aacdec/C2SoftAac.cpp b/media/libstagefright/codecs/aacdec/C2SoftAac.cpp
index 390f36c..5ddfc14 100644
--- a/media/libstagefright/codecs/aacdec/C2SoftAac.cpp
+++ b/media/libstagefright/codecs/aacdec/C2SoftAac.cpp
@@ -316,9 +316,9 @@
work->worklets.front()->output.buffers.clear();
work->worklets.front()->output.buffers.push_back(buffer);
work->worklets.front()->output.ordinal = work->input.ordinal;
- work->worklets_processed = 1u;
+ work->workletsProcessed = 1u;
};
- if (work && work->input.ordinal.frame_index == outInfo.frameIndex) {
+ if (work && work->input.ordinal.frameIndex == c2_cntr64_t(outInfo.frameIndex)) {
fillWork(work);
} else {
finish(outInfo.frameIndex, fillWork);
@@ -332,7 +332,7 @@
void C2SoftAac::process(
const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2BlockPool> &pool) {
- work->worklets_processed = 0u;
+ work->workletsProcessed = 0u;
if (mSignalledError) {
return;
}
@@ -346,8 +346,8 @@
size_t offset = 0u;
size_t size = view.capacity();
- bool eos = (work->input.flags & C2BufferPack::FLAG_END_OF_STREAM) != 0;
- bool codecConfig = (work->input.flags & C2BufferPack::FLAG_CODEC_CONFIG) != 0;
+ bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
+ bool codecConfig = (work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0;
//TODO
#if 0
@@ -381,8 +381,8 @@
}
Info inInfo;
- inInfo.frameIndex = work->input.ordinal.frame_index;
- inInfo.timestamp = work->input.ordinal.timestamp;
+ inInfo.frameIndex = work->input.ordinal.frameIndex.peeku();
+ inInfo.timestamp = work->input.ordinal.timestamp.peeku();
inInfo.bufferSize = size;
inInfo.decodedSizes.clear();
while (size > 0u) {
@@ -604,13 +604,13 @@
work->worklets.front()->output.buffers.clear();
work->worklets.front()->output.buffers.emplace_back(nullptr);
work->worklets.front()->output.ordinal = work->input.ordinal;
- work->worklets_processed = 1u;
+ work->workletsProcessed = 1u;
};
while (mBuffersInfo.size() > 1u) {
finish(mBuffersInfo.front().frameIndex, fillEmptyWork);
mBuffersInfo.pop_front();
}
- if (work->worklets_processed == 0u) {
+ if (work->workletsProcessed == 0u) {
fillEmptyWork(work);
}
mBuffersInfo.clear();
diff --git a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
index 94308c4..7bce21d 100644
--- a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
+++ b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
@@ -176,12 +176,12 @@
void C2SoftAacEnc::process(
const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2BlockPool> &pool) {
- work->worklets_processed = 0u;
+ work->workletsProcessed = 0u;
if (mSignalledError) {
return;
}
- bool eos = (work->input.flags & C2BufferPack::FLAG_END_OF_STREAM) != 0;
+ bool eos = (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0;
if (!mSentCodecSpecificData) {
// The very first thing we want to output is the codec specific
@@ -215,7 +215,7 @@
#if defined(LOG_NDEBUG) && !LOG_NDEBUG
hexdump(csd->m.value, csd->flexCount());
#endif
- work->worklets.front()->output.infos.push_back(std::move(csd));
+ work->worklets.front()->output.configUpdate.push_back(std::move(csd));
mOutBufferSize = encInfo.maxOutBufBytes;
mNumBytesPerInputFrame = encInfo.frameLength * mNumChannels * sizeof(int16_t);
@@ -225,7 +225,7 @@
}
C2ReadView view = work->input.buffers[0]->data().linearBlocks().front().map().get();
- uint64_t timestamp = mInputTimeUs;
+ uint64_t timestamp = mInputTimeUs.peeku();
size_t numFrames = (view.capacity() + mInputSize + (eos ? mNumBytesPerInputFrame - 1 : 0))
/ mNumBytesPerInputFrame;
@@ -336,11 +336,11 @@
}
work->worklets.front()->output.flags =
- (C2BufferPack::flags_t)(eos ? C2BufferPack::FLAG_END_OF_STREAM : 0);
+ (C2FrameData::flags_t)(eos ? C2FrameData::FLAG_END_OF_STREAM : 0);
work->worklets.front()->output.buffers.clear();
work->worklets.front()->output.ordinal = work->input.ordinal;
work->worklets.front()->output.ordinal.timestamp = timestamp;
- work->worklets_processed = 1u;
+ work->workletsProcessed = 1u;
if (nOutputBytes) {
work->worklets.front()->output.buffers.push_back(
createLinearBuffer(block, 0, nOutputBytes));
@@ -350,7 +350,7 @@
#if 0
ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
- nOutputBytes, mInputTimeUs, outHeader->nFlags);
+ nOutputBytes, mInputTimeUs.peekll(), outHeader->nFlags);
hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
#endif
diff --git a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.h b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.h
index 947c960..c9f440f 100644
--- a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.h
+++ b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.h
@@ -57,7 +57,7 @@
bool mSentCodecSpecificData;
size_t mInputSize;
- int64_t mInputTimeUs;
+ c2_cntr64_t mInputTimeUs;
bool mSignalledError;
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
index 0da9cc7..cc12d3c 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
@@ -206,14 +206,14 @@
void fillEmptyWork(const std::unique_ptr<C2Work> &work) {
uint32_t flags = 0;
- if ((work->input.flags & C2BufferPack::FLAG_END_OF_STREAM)) {
- flags |= C2BufferPack::FLAG_END_OF_STREAM;
+ if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM)) {
+ flags |= C2FrameData::FLAG_END_OF_STREAM;
}
- work->worklets.front()->output.flags = (C2BufferPack::flags_t)flags;
+ work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
work->worklets.front()->output.buffers.clear();
work->worklets.front()->output.buffers.emplace_back(nullptr);
work->worklets.front()->output.ordinal = work->input.ordinal;
- work->worklets_processed = 1u;
+ work->workletsProcessed = 1u;
}
} // namespace
@@ -1061,17 +1061,17 @@
std::shared_ptr<C2Buffer> buffer = createGraphicBuffer(std::move(mAllocatedBlock));
auto fillWork = [buffer](const std::unique_ptr<C2Work> &work) {
uint32_t flags = 0;
- if (work->input.flags & C2BufferPack::FLAG_END_OF_STREAM) {
- flags |= C2BufferPack::FLAG_END_OF_STREAM;
+ if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
+ flags |= C2FrameData::FLAG_END_OF_STREAM;
ALOGV("EOS");
}
- work->worklets.front()->output.flags = (C2BufferPack::flags_t)flags;
+ work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
work->worklets.front()->output.buffers.clear();
work->worklets.front()->output.buffers.push_back(buffer);
work->worklets.front()->output.ordinal = work->input.ordinal;
- work->worklets_processed = 1u;
+ work->workletsProcessed = 1u;
};
- if (work && index == work->input.ordinal.frame_index) {
+ if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
fillWork(work);
} else {
finish(index, fillWork);
@@ -1084,25 +1084,25 @@
bool eos = false;
work->result = C2_OK;
- work->worklets_processed = 0u;
+ work->workletsProcessed = 0u;
const C2ConstLinearBlock &buffer =
work->input.buffers[0]->data().linearBlocks().front();
if (buffer.capacity() == 0) {
- ALOGV("empty input: %llu", (long long)work->input.ordinal.frame_index);
+ ALOGV("empty input: %llu", work->input.ordinal.frameIndex.peekull());
// TODO: result?
fillEmptyWork(work);
- if ((work->input.flags & C2BufferPack::FLAG_END_OF_STREAM)) {
+ if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM)) {
eos = true;
}
return;
- } else if (work->input.flags & C2BufferPack::FLAG_END_OF_STREAM) {
- ALOGV("input EOS: %llu", (long long)work->input.ordinal.frame_index);
+ } else if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
+ ALOGV("input EOS: %llu", work->input.ordinal.frameIndex.peekull());
eos = true;
}
C2ReadView input = work->input.buffers[0]->data().linearBlocks().front().map().get();
- uint32_t workIndex = work->input.ordinal.frame_index & 0xFFFFFFFF;
+ uint32_t workIndex = work->input.ordinal.frameIndex.peeku() & 0xFFFFFFFF;
size_t inOffset = 0u;
while (inOffset < input.capacity()) {
@@ -1266,7 +1266,7 @@
}
if (drainMode == DRAIN_COMPONENT_WITH_EOS
- && work && work->worklets_processed == 0u) {
+ && work && work->workletsProcessed == 0u) {
fillEmptyWork(work);
}
diff --git a/media/libstagefright/codecs/cmds/Android.bp b/media/libstagefright/codecs/cmds/Android.bp
index 40f1a3d..6dba0a3 100644
--- a/media/libstagefright/codecs/cmds/Android.bp
+++ b/media/libstagefright/codecs/cmds/Android.bp
@@ -13,6 +13,7 @@
"libcutils",
"libgui",
"liblog",
+ "libmediaextractor",
"libstagefright",
"libstagefright_codec2",
"libstagefright_codec2_vndk",
diff --git a/media/libstagefright/codecs/cmds/codec2.cpp b/media/libstagefright/codecs/cmds/codec2.cpp
index 78fb527..ec05d7a 100644
--- a/media/libstagefright/codecs/cmds/codec2.cpp
+++ b/media/libstagefright/codecs/cmds/codec2.cpp
@@ -247,7 +247,7 @@
}
int slot;
sp<Fence> fence;
- ALOGV("Render: Frame #%" PRId64, work->worklets.front()->output.ordinal.frame_index);
+ ALOGV("Render: Frame #%lld", work->worklets.front()->output.ordinal.frameIndex.peekll());
const std::shared_ptr<C2Buffer> &output = work->worklets.front()->output.buffers[0];
if (output) {
const C2ConstGraphicBlock &block = output->data().graphicBlocks().front();
@@ -266,7 +266,7 @@
status_t err = igbp->attachBuffer(&slot, buffer);
IGraphicBufferProducer::QueueBufferInput qbi(
- work->worklets.front()->output.ordinal.timestamp * 1000ll,
+ (work->worklets.front()->output.ordinal.timestamp * 1000ll).peekll(),
false,
HAL_DATASPACE_UNKNOWN,
Rect(block.width(), block.height()),
@@ -338,9 +338,9 @@
mQueueCondition.wait_for(l, 100ms);
}
}
- work->input.flags = (C2BufferPack::flags_t)0;
+ work->input.flags = (C2FrameData::flags_t)0;
work->input.ordinal.timestamp = timestamp;
- work->input.ordinal.frame_index = numFrames;
+ work->input.ordinal.frameIndex = numFrames;
std::shared_ptr<C2LinearBlock> block;
mLinearPool->fetchLinearBlock(
diff --git a/media/libstagefright/foundation/ABuffer.cpp b/media/libstagefright/foundation/ABuffer.cpp
index 804046a..c8965d9 100644
--- a/media/libstagefright/foundation/ABuffer.cpp
+++ b/media/libstagefright/foundation/ABuffer.cpp
@@ -19,13 +19,11 @@
#include "ADebug.h"
#include "ALooper.h"
#include "AMessage.h"
-#include "MediaBufferBase.h"
namespace android {
ABuffer::ABuffer(size_t capacity)
- : mMediaBufferBase(NULL),
- mRangeOffset(0),
+ : mRangeOffset(0),
mInt32Data(0),
mOwnsData(true) {
mData = malloc(capacity);
@@ -39,8 +37,7 @@
}
ABuffer::ABuffer(void *data, size_t capacity)
- : mMediaBufferBase(NULL),
- mData(data),
+ : mData(data),
mCapacity(capacity),
mRangeOffset(0),
mRangeLength(capacity),
@@ -66,8 +63,6 @@
mData = NULL;
}
}
-
- setMediaBufferBase(NULL);
}
void ABuffer::setRange(size_t offset, size_t size) {
@@ -85,19 +80,5 @@
return mMeta;
}
-MediaBufferBase *ABuffer::getMediaBufferBase() {
- if (mMediaBufferBase != NULL) {
- mMediaBufferBase->add_ref();
- }
- return mMediaBufferBase;
-}
-
-void ABuffer::setMediaBufferBase(MediaBufferBase *mediaBuffer) {
- if (mMediaBufferBase != NULL) {
- mMediaBufferBase->release();
- }
- mMediaBufferBase = mediaBuffer;
-}
-
} // namespace android
diff --git a/media/libstagefright/foundation/Android.bp b/media/libstagefright/foundation/Android.bp
index 4dfe5e5..2258e2c 100644
--- a/media/libstagefright/foundation/Android.bp
+++ b/media/libstagefright/foundation/Android.bp
@@ -62,8 +62,6 @@
"AStringUtils.cpp",
"ByteUtils.cpp",
"ColorUtils.cpp",
- "MediaBuffer.cpp",
- "MediaBufferGroup.cpp",
"MediaDefs.cpp",
"MediaKeys.cpp",
"MetaData.cpp",
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/ABuffer.h b/media/libstagefright/foundation/include/media/stagefright/foundation/ABuffer.h
index ef11434..8fe9f8d 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/ABuffer.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/ABuffer.h
@@ -27,7 +27,6 @@
namespace android {
struct AMessage;
-class MediaBufferBase;
struct ABuffer : public RefBase {
explicit ABuffer(size_t capacity);
@@ -49,17 +48,12 @@
sp<AMessage> meta();
- MediaBufferBase *getMediaBufferBase();
- void setMediaBufferBase(MediaBufferBase *mediaBuffer);
-
protected:
virtual ~ABuffer();
private:
sp<AMessage> mMeta;
- MediaBufferBase *mMediaBufferBase;
-
void *mData;
size_t mCapacity;
size_t mRangeOffset;
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaBufferBase.h b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaBufferBase.h
deleted file mode 100644
index 99418fb..0000000
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaBufferBase.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2014 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 MEDIA_BUFFER_BASE_H_
-
-#define MEDIA_BUFFER_BASE_H_
-
-namespace android {
-
-class MediaBufferBase {
-public:
- MediaBufferBase() {}
-
- virtual void release() = 0;
- virtual void add_ref() = 0;
-
-protected:
- virtual ~MediaBufferBase() {}
-
-private:
- MediaBufferBase(const MediaBufferBase &);
- MediaBufferBase &operator=(const MediaBufferBase &);
-};
-
-} // namespace android
-
-#endif // MEDIA_BUFFER_BASE_H_
diff --git a/media/libstagefright/include/media/stagefright/MediaBuffer.h b/media/libstagefright/include/media/stagefright/MediaBuffer.h
new file mode 120000
index 0000000..1d49c1a
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/MediaBuffer.h
@@ -0,0 +1 @@
+../../../../libmediaextractor/include/media/stagefright/MediaBuffer.h
\ No newline at end of file
diff --git a/media/libstagefright/include/media/stagefright/MediaBufferGroup.h b/media/libstagefright/include/media/stagefright/MediaBufferGroup.h
new file mode 120000
index 0000000..009b3d9
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/MediaBufferGroup.h
@@ -0,0 +1 @@
+../../../../libmediaextractor/include/media/stagefright/MediaBufferGroup.h
\ No newline at end of file
diff --git a/media/libstagefright/tests/Android.bp b/media/libstagefright/tests/Android.bp
index 35119c2..e67a949 100644
--- a/media/libstagefright/tests/Android.bp
+++ b/media/libstagefright/tests/Android.bp
@@ -15,6 +15,7 @@
"libcutils",
"libgui",
"libmedia",
+ "libmediaextractor",
"libstagefright",
"libstagefright_foundation",
"libstagefright_omx",
diff --git a/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java b/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
index f159398..59d8366 100644
--- a/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaBrowser2Impl.java
@@ -61,6 +61,31 @@
}
}
+ @Override
+ public void subscribe_impl(String parentId, Bundle options) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void unsubscribe_impl(String parentId, Bundle options) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void getItem_impl(String mediaId) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void getChildren_impl(String parentId, int page, int pageSize, Bundle options) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void search_impl(String query, int page, int pageSize, Bundle extras) {
+ // TODO(jaewan): Implement
+ }
+
public void onGetRootResult(
final Bundle rootHints, final String rootMediaId, final Bundle rootExtra) {
getCallbackExecutor().execute(() -> {
diff --git a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
index 08a7165..ac3f311 100644
--- a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
@@ -16,12 +16,15 @@
package com.android.media;
+import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.media.IMediaSession2;
import android.media.IMediaSession2Callback;
+import android.media.MediaController2.PlaybackInfo;
+import android.media.MediaItem2;
import android.media.MediaSession2;
import android.media.MediaSession2.Command;
import android.media.MediaSession2.CommandButton;
@@ -29,14 +32,19 @@
import android.media.MediaController2;
import android.media.MediaController2.ControllerCallback;
import android.media.MediaPlayerBase;
+import android.media.MediaSession2.PlaylistParam;
import android.media.MediaSessionService2;
+import android.media.PlaybackState2;
+import android.media.Rating2;
import android.media.SessionToken;
import android.media.session.PlaybackState;
import android.media.update.MediaController2Provider;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.support.annotation.GuardedBy;
import android.util.Log;
@@ -257,69 +265,128 @@
}
}
+ //////////////////////////////////////////////////////////////////////////////////////
+ // TODO(jaewan): Implement follows
+ //////////////////////////////////////////////////////////////////////////////////////
@Override
- public PlaybackState getPlaybackState_impl() {
- final IMediaSession2 binder = mSessionBinder;
- if (binder != null) {
- try {
- return binder.getPlaybackState();
- } catch (RemoteException e) {
- Log.w(TAG, "Cannot connect to the service or the session is gone", e);
- }
- } else {
- Log.w(TAG, "Session isn't active", new IllegalStateException());
- }
- // TODO(jaewan): What to return for error case?
+ public PendingIntent getSessionActivity_impl() {
+ // TODO(jaewan): Implement
return null;
}
@Override
- public void addPlaybackListener_impl(
- MediaPlayerBase.PlaybackListener listener, Handler handler) {
- if (listener == null) {
- throw new IllegalArgumentException("listener shouldn't be null");
- }
- if (handler == null) {
- throw new IllegalArgumentException("handler shouldn't be null");
- }
- boolean registerCallback;
- synchronized (mLock) {
- if (PlaybackListenerHolder.contains(mPlaybackListeners, listener)) {
- throw new IllegalArgumentException("listener is already added. Ignoring.");
- }
- registerCallback = mPlaybackListeners.isEmpty();
- mPlaybackListeners.add(new PlaybackListenerHolder(listener, handler));
- }
- if (registerCallback) {
- registerCallbackForPlaybackNotLocked();
- }
+ public int getRatingType_impl() {
+ // TODO(jaewan): Implement
+ return 0;
}
@Override
- public void removePlaybackListener_impl(MediaPlayerBase.PlaybackListener listener) {
- if (listener == null) {
- throw new IllegalArgumentException("listener shouldn't be null");
- }
- boolean unregisterCallback;
- synchronized (mLock) {
- int idx = PlaybackListenerHolder.indexOf(mPlaybackListeners, listener);
- if (idx >= 0) {
- mPlaybackListeners.get(idx).removeCallbacksAndMessages(null);
- mPlaybackListeners.remove(idx);
- }
- unregisterCallback = mPlaybackListeners.isEmpty();
- }
- if (unregisterCallback) {
- final IMediaSession2 binder = mSessionBinder;
- if (binder != null) {
- // Lazy unregister
- try {
- binder.unregisterCallback(mSessionCallbackStub, CALLBACK_FLAG_PLAYBACK);
- } catch (RemoteException e) {
- Log.e(TAG, "Cannot connect to the service or the session is gone", e);
- }
- }
- }
+ public void setVolumeTo_impl(int value, int flags) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void adjustVolume_impl(int direction, int flags) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public PlaybackInfo getPlaybackInfo_impl() {
+ // TODO(jaewan): Implement
+ return null;
+ }
+
+ @Override
+ public void prepareFromUri_impl(Uri uri, Bundle extras) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void prepareFromSearch_impl(String query, Bundle extras) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void prepareMediaId_impl(String mediaId, Bundle extras) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void playFromSearch_impl(String query, Bundle extras) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void playFromUri_impl(String uri, Bundle extras) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void playFromMediaId_impl(String mediaId, Bundle extras) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void setRating_impl(Rating2 rating) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void sendCustomCommand_impl(Command command, Bundle args, ResultReceiver cb) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public List<MediaItem2> getPlaylist_impl() {
+ // TODO(jaewan): Implement
+ return null;
+ }
+
+ @Override
+ public void prepare_impl() {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void fastForward_impl() {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void rewind_impl() {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void seekTo_impl(long pos) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void setCurrentPlaylistItem_impl(int index) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public PlaybackState2 getPlaybackState_impl() {
+ // TODO(jaewan): Implement
+ return null;
+ }
+
+ @Override
+ public void removePlaylistItem_impl(MediaItem2 index) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void addPlaylistItem_impl(int index, MediaItem2 item) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public PlaylistParam getPlaylistParam_impl() {
+ // TODO(jaewan): Implement
+ return null;
}
///////////////////////////////////////////////////
diff --git a/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java b/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
index 430ab4c..b177dda 100644
--- a/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaLibraryService2Impl.java
@@ -16,12 +16,20 @@
package com.android.media;
+import android.app.PendingIntent;
+import android.content.Context;
import android.content.Intent;
import android.media.MediaLibraryService2;
import android.media.MediaLibraryService2.MediaLibrarySession;
+import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
+import android.media.MediaPlayerBase;
import android.media.MediaSession2;
+import android.media.MediaSession2.ControllerInfo;
+import android.media.MediaSession2.SessionCallback;
import android.media.MediaSessionService2;
+import android.media.VolumeProvider;
import android.media.update.MediaLibraryService2Provider;
+import android.os.Bundle;
public class MediaLibraryService2Impl extends MediaSessionService2Impl implements
MediaLibraryService2Provider {
@@ -51,4 +59,31 @@
serviceIntent.setAction(MediaLibraryService2.SERVICE_INTERFACE);
return serviceIntent;
}
+
+ public static class MediaLibrarySessionImpl extends MediaSession2Impl
+ implements MediaLibrarySessionProvider {
+ private final MediaLibrarySession mInstance;
+ private final MediaLibrarySessionCallback mCallback;
+
+ public MediaLibrarySessionImpl(MediaLibrarySession instance, Context context,
+ MediaPlayerBase player, String id,
+ MediaLibrarySessionCallback callback, VolumeProvider volumeProvider, int ratingType,
+ PendingIntent sessionActivity) {
+ super(instance, context, player, id, callback, volumeProvider, ratingType,
+ sessionActivity);
+ mInstance = instance;
+ mCallback = callback;
+ }
+
+ @Override
+ public void notifyChildrenChanged_impl(ControllerInfo controller, String parentId,
+ Bundle options) {
+ // TODO(jaewan): Implements
+ }
+
+ @Override
+ public void notifyChildrenChanged_impl(String parentId, Bundle options) {
+ // TODO(jaewan): Implements
+ }
+ }
}
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
index 19ea1b2..2e71641 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
@@ -17,24 +17,32 @@
package com.android.media;
import android.Manifest.permission;
+import android.app.PendingIntent;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.media.AudioAttributes;
import android.media.IMediaSession2Callback;
-import android.media.MediaController2;
+import android.media.MediaItem2;
import android.media.MediaPlayerBase;
import android.media.MediaSession2;
import android.media.MediaSession2.Builder;
+import android.media.MediaSession2.Command;
import android.media.MediaSession2.CommandButton;
+import android.media.MediaSession2.CommandGroup;
import android.media.MediaSession2.ControllerInfo;
+import android.media.MediaSession2.PlaylistParam;
import android.media.MediaSession2.SessionCallback;
import android.media.SessionToken;
+import android.media.VolumeProvider;
import android.media.session.MediaSessionManager;
import android.media.session.PlaybackState;
import android.media.update.MediaSession2Provider;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
+import android.os.ResultReceiver;
import android.util.Log;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -60,16 +68,21 @@
/**
* Can be only called by the {@link Builder#build()}.
- *
+ *
* @param instance
* @param context
* @param player
* @param id
* @param callback
+ * @param volumeProvider
+ * @param ratingType
+ * @param sessionActivity
*/
public MediaSession2Impl(MediaSession2 instance, Context context, MediaPlayerBase player,
- String id, SessionCallback callback) {
+ String id, SessionCallback callback, VolumeProvider volumeProvider, int ratingType,
+ PendingIntent sessionActivity) {
mInstance = instance;
+ // TODO(jaewan): Keep other params.
// Argument checks are done by builder already.
// Initialize finals first.
@@ -102,7 +115,7 @@
// setPlayer(null). Token can be available when player is null, and
// controller can also attach to session.
@Override
- public void setPlayer_impl(MediaPlayerBase player) throws IllegalArgumentException {
+ public void setPlayer_impl(MediaPlayerBase player, VolumeProvider volumeProvider) throws IllegalArgumentException {
ensureCallingThread();
if (player == null) {
throw new IllegalArgumentException("player shouldn't be null");
@@ -156,6 +169,16 @@
}
@Override
+ public void setAudioAttributes_impl(AudioAttributes attributes) {
+ // implement
+ }
+
+ @Override
+ public void setAudioFocusRequest_impl(int focusGain) {
+ // implement
+ }
+
+ @Override
public void play_impl() {
ensureCallingThread();
ensurePlayer();
@@ -191,43 +214,6 @@
}
@Override
- public PlaybackState getPlaybackState_impl() {
- ensureCallingThread();
- ensurePlayer();
- return mPlayer.getPlaybackState();
- }
-
- @Override
- public void addPlaybackListener_impl(
- MediaPlayerBase.PlaybackListener listener, Handler handler) {
- if (listener == null) {
- throw new IllegalArgumentException("listener shouldn't be null");
- }
- if (handler == null) {
- throw new IllegalArgumentException("handler shouldn't be null");
- }
- ensureCallingThread();
- if (PlaybackListenerHolder.contains(mListeners, listener)) {
- Log.w(TAG, "listener is already added. Ignoring.");
- return;
- }
- mListeners.add(new PlaybackListenerHolder(listener, handler));
- }
-
- @Override
- public void removePlaybackListener_impl(MediaPlayerBase.PlaybackListener listener) {
- if (listener == null) {
- throw new IllegalArgumentException("listener shouldn't be null");
- }
- ensureCallingThread();
- int idx = PlaybackListenerHolder.indexOf(mListeners, listener);
- if (idx >= 0) {
- mListeners.get(idx).removeCallbacksAndMessages(null);
- mListeners.remove(idx);
- }
- }
-
- @Override
public void setCustomLayout_impl(ControllerInfo controller, List<CommandButton> layout) {
ensureCallingThread();
if (controller == null) {
@@ -239,6 +225,65 @@
mSessionStub.notifyCustomLayoutNotLocked(controller, layout);
}
+ //////////////////////////////////////////////////////////////////////////////////////
+ // TODO(jaewan): Implement follows
+ //////////////////////////////////////////////////////////////////////////////////////
+ @Override
+ public void setPlayer_impl(MediaPlayerBase player) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void setAllowedCommands_impl(ControllerInfo controller, CommandGroup commands) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void notifyMetadataChanged_impl() {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void sendCustomCommand_impl(ControllerInfo controller, Command command, Bundle args,
+ ResultReceiver receiver) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void sendCustomCommand_impl(Command command, Bundle args) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void setPlaylist_impl(List<MediaItem2> playlist, PlaylistParam param) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void prepare_impl() {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void fastForward_impl() {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void rewind_impl() {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void seekTo_impl(long pos) {
+ // TODO(jaewan): Implement
+ }
+
+ @Override
+ public void setCurrentPlaylistItem_impl(int index) {
+ // TODO(jaewan): Implement
+ }
+
///////////////////////////////////////////////////
// Protected or private methods
///////////////////////////////////////////////////
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
index f2772ed..3f7a1b1 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.media.IMediaSession2;
import android.media.IMediaSession2Callback;
+import android.media.MediaLibraryService2.BrowserRoot;
import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
import android.media.MediaSession2;
import android.media.MediaSession2.Command;
@@ -36,7 +37,6 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
-import android.service.media.MediaBrowserService.BrowserRoot;
import android.support.annotation.GuardedBy;
import android.util.ArrayMap;
import android.util.Log;
diff --git a/packages/MediaComponents/src/com/android/media/update/ApiFactory.java b/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
index 07b565e..43acaf9 100644
--- a/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
+++ b/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
@@ -16,6 +16,7 @@
package com.android.media.update;
+import android.app.PendingIntent;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
@@ -23,6 +24,8 @@
import android.media.MediaBrowser2.BrowserCallback;
import android.media.MediaController2;
import android.media.MediaLibraryService2;
+import android.media.MediaLibraryService2.MediaLibrarySession;
+import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
import android.media.MediaPlayerBase;
import android.media.MediaSession2;
import android.media.MediaSession2.ControllerInfo;
@@ -30,9 +33,11 @@
import android.media.MediaSessionService2;
import android.media.IMediaSession2Callback;
import android.media.SessionToken;
+import android.media.VolumeProvider;
import android.media.update.MediaBrowser2Provider;
import android.media.update.MediaControlView2Provider;
import android.media.update.MediaController2Provider;
+import android.media.update.MediaLibraryService2Provider.MediaLibrarySessionProvider;
import android.media.update.MediaSession2Provider;
import android.media.update.MediaSessionService2Provider;
import android.media.update.VideoView2Provider;
@@ -46,6 +51,7 @@
import com.android.media.MediaBrowser2Impl;
import com.android.media.MediaController2Impl;
import com.android.media.MediaLibraryService2Impl;
+import com.android.media.MediaLibraryService2Impl.MediaLibrarySessionImpl;
import com.android.media.MediaSession2Impl;
import com.android.media.MediaSessionService2Impl;
import com.android.widget.MediaControlView2Impl;
@@ -75,8 +81,11 @@
@Override
public MediaSession2Provider createMediaSession2(MediaSession2 instance, Context context,
- MediaPlayerBase player, String id, SessionCallback callback) {
- return new MediaSession2Impl(instance, context, player, id, callback);
+ MediaPlayerBase player, String id, SessionCallback callback,
+ VolumeProvider volumeProvider, int ratingType,
+ PendingIntent sessionActivity) {
+ return new MediaSession2Impl(instance, context, player, id, callback,
+ volumeProvider, ratingType, sessionActivity);
}
@Override
@@ -100,6 +109,15 @@
}
@Override
+ public MediaLibrarySessionProvider createMediaLibraryService2MediaLibrarySession(
+ MediaLibrarySession instance, Context context, MediaPlayerBase player, String id,
+ MediaLibrarySessionCallback callback, VolumeProvider volumeProvider, int ratingType,
+ PendingIntent sessionActivity) {
+ return new MediaLibrarySessionImpl(instance, context, player, id, callback, volumeProvider,
+ ratingType, sessionActivity);
+ }
+
+ @Override
public MediaControlView2Provider createMediaControlView2(
MediaControlView2 instance, ViewProvider superProvider) {
return new MediaControlView2Impl(instance, superProvider);
diff --git a/packages/MediaComponents/test/src/android/media/MediaController2Test.java b/packages/MediaComponents/test/src/android/media/MediaController2Test.java
index ac0bd73..f99935a 100644
--- a/packages/MediaComponents/test/src/android/media/MediaController2Test.java
+++ b/packages/MediaComponents/test/src/android/media/MediaController2Test.java
@@ -144,6 +144,8 @@
@Test
public void testGetPlaybackState() throws InterruptedException {
+ // TODO(jaewan): add equivalent test later
+ /*
final CountDownLatch latch = new CountDownLatch(1);
final MediaPlayerBase.PlaybackListener listener = (state) -> {
assertEquals(PlaybackState.STATE_BUFFERING, state.getState());
@@ -155,8 +157,11 @@
mPlayer.notifyPlaybackState(createPlaybackState(PlaybackState.STATE_BUFFERING));
assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
assertEquals(PlaybackState.STATE_BUFFERING, mController.getPlaybackState().getState());
+ */
}
+ // TODO(jaewan): add equivalent test later
+ /*
@Test
public void testAddPlaybackListener() throws InterruptedException {
final CountDownLatch latch = new CountDownLatch(2);
@@ -192,6 +197,7 @@
mPlayer.notifyPlaybackState(createPlaybackState(PlaybackState.STATE_PLAYING));
assertFalse(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
}
+ */
@Test
public void testControllerCallback_onConnected() throws InterruptedException {
@@ -273,9 +279,6 @@
});
final MediaController2 controller = createController(mSession.getToken());
testHandler.post(() -> {
- controller.addPlaybackListener((state) -> {
- // no-op. Just to set a binder call path from session to controller.
- }, sessionHandler);
final PlaybackState state = createPlaybackState(PlaybackState.STATE_ERROR);
for (int i = 0; i < 100; i++) {
// triggers call from session to controller.
@@ -360,6 +363,8 @@
assertTrue(mPlayer.mPlayCalled);
// Test command from session service to controller
+ // TODO(jaewan): Add equivalent tests again
+ /*
final CountDownLatch latch = new CountDownLatch(1);
mController.addPlaybackListener((state) -> {
assertNotNull(state);
@@ -369,6 +374,7 @@
mPlayer.notifyPlaybackState(
TestUtils.createPlaybackState(PlaybackState.STATE_REWINDING));
assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ */
}
@Test
@@ -467,10 +473,13 @@
fail("Controller shouldn't be notified about change in session after the close.");
latch.countDown();
};
+ // TODO(jaewan): Add equivalent tests again
+ /*
mController.addPlaybackListener(playbackListener, sHandler);
mPlayer.notifyPlaybackState(TestUtils.createPlaybackState(PlaybackState.STATE_BUFFERING));
assertFalse(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
mController.removePlaybackListener(playbackListener);
+ */
}
// TODO(jaewan): Add test for service connect rejection, when we differentiate session
diff --git a/packages/MediaComponents/test/src/android/media/MediaSession2Test.java b/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
index c5408e8..7b58f0e 100644
--- a/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
+++ b/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
@@ -139,6 +139,8 @@
@Test
public void testPlaybackStateChangedListener() throws InterruptedException {
+ // TODO(jaewan): Add equivalent tests again
+ /*
final CountDownLatch latch = new CountDownLatch(2);
final MockPlayer player = new MockPlayer(0);
final PlaybackListener listener = (state) -> {
@@ -164,10 +166,13 @@
});
player.notifyPlaybackState(createPlaybackState(PlaybackState.STATE_PAUSED));
assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ */
}
@Test
public void testBadPlayer() throws InterruptedException {
+ // TODO(jaewan): Add equivalent tests again
+ /*
final CountDownLatch latch = new CountDownLatch(3); // expected call + 1
final BadPlayer player = new BadPlayer(0);
sHandler.postAndSync(() -> {
@@ -181,6 +186,7 @@
});
player.notifyPlaybackState(createPlaybackState(PlaybackState.STATE_PAUSED));
assertFalse(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+ */
}
private static class BadPlayer extends MockPlayer {
diff --git a/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java b/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java
index 7a16127..acf733f 100644
--- a/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java
+++ b/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java
@@ -24,7 +24,6 @@
import android.media.TestUtils.SyncHandler;
import android.os.Bundle;
import android.os.Process;
-import android.service.media.MediaBrowserService.BrowserRoot;
import javax.annotation.concurrent.GuardedBy;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index e058dc8..7343601 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2939,7 +2939,7 @@
sinkDeviceDesc->toAudioPortConfig(&newPatch.sinks[i], &patch->sinks[i]);
// create a software bridge in PatchPanel if:
- // - source and sink devices are on differnt HW modules OR
+ // - source and sink devices are on different HW modules OR
// - audio HAL version is < 3.0
if (!srcDeviceDesc->hasSameHwModuleAs(sinkDeviceDesc) ||
(srcDeviceDesc->mModule->getHalVersionMajor() < 3)) {
diff --git a/services/mediacodec/Android.mk b/services/mediacodec/Android.mk
index 8e5b260..97eaf77 100644
--- a/services/mediacodec/Android.mk
+++ b/services/mediacodec/Android.mk
@@ -1,5 +1,28 @@
LOCAL_PATH := $(call my-dir)
+_software_codecs := \
+ libstagefright_soft_aacdec \
+ libstagefright_soft_aacenc \
+ libstagefright_soft_amrdec \
+ libstagefright_soft_amrnbenc \
+ libstagefright_soft_amrwbenc \
+ libstagefright_soft_avcdec \
+ libstagefright_soft_avcenc \
+ libstagefright_soft_flacdec \
+ libstagefright_soft_flacenc \
+ libstagefright_soft_g711dec \
+ libstagefright_soft_gsmdec \
+ libstagefright_soft_hevcdec \
+ libstagefright_soft_mp3dec \
+ libstagefright_soft_mpeg2dec \
+ libstagefright_soft_mpeg4dec \
+ libstagefright_soft_mpeg4enc \
+ libstagefright_soft_opusdec \
+ libstagefright_soft_rawdec \
+ libstagefright_soft_vorbisdec \
+ libstagefright_soft_vpxdec \
+ libstagefright_soft_vpxenc \
+
# service executable
include $(CLEAR_VARS)
# seccomp is not required for coverage build.
@@ -27,6 +50,15 @@
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_VENDOR_MODULE := true
LOCAL_32_BIT_ONLY := true
+# Since this is 32-bit-only module, only 32-bit version of the codecs are installed.
+# TODO(b/72343507): eliminate the need for manually adding .vendor suffix. This should be done
+# by the build system.
+LOCAL_REQUIRED_MODULES := \
+$(foreach codec,$(_software_codecs),\
+ $(eval _vendor_suffix := $(if $(BOARD_VNDK_VERSION),.vendor))\
+ $(codec)$(_vendor_suffix)\
+)
+_software_codecs :=
LOCAL_INIT_RC := android.hardware.media.omx@1.0-service.rc
include $(BUILD_EXECUTABLE)