codec2: list c2.* components in MediaCodecList
- Set proper media type for component interface and read them in
CCodec instead of current hack.
- Define debug.stagefright.omx_default_rank to override default OMX.*
rank value (currently set to be preferred over c2.*)
- Move MediaCodec::CreateByType logic from ACodec to MediaCodec.
Test: am instrument -e size small -w 'android.media.cts/android.support.test.runner.AndroidJUnitRunner'
Test: setprop debug.stagefright.ccodec yes
Test: killall mediaserver
Test: cts-tradefed run cts -m CtsMediaTestCases -t android.media.cts.MediaCodecListTest
Change-Id: I55bd10d2d8c65867eae654e5bd64ef545689e699
diff --git a/media/libmedia/MediaCodecInfo.cpp b/media/libmedia/MediaCodecInfo.cpp
index a570ffe..5308e1c 100644
--- a/media/libmedia/MediaCodecInfo.cpp
+++ b/media/libmedia/MediaCodecInfo.cpp
@@ -141,6 +141,10 @@
return mIsEncoder;
}
+uint32_t MediaCodecInfo::rank() const {
+ return mRank;
+}
+
void MediaCodecInfo::getSupportedMimes(Vector<AString> *mimes) const {
mimes->clear();
for (size_t ix = 0; ix < mCaps.size(); ix++) {
@@ -170,10 +174,12 @@
AString name = AString::FromParcel(parcel);
AString owner = AString::FromParcel(parcel);
bool isEncoder = static_cast<bool>(parcel.readInt32());
+ uint32_t rank = parcel.readUint32();
sp<MediaCodecInfo> info = new MediaCodecInfo;
info->mName = name;
info->mOwner = owner;
info->mIsEncoder = isEncoder;
+ info->mRank = rank;
size_t size = static_cast<size_t>(parcel.readInt32());
for (size_t i = 0; i < size; i++) {
AString mime = AString::FromParcel(parcel);
@@ -191,6 +197,7 @@
mName.writeToParcel(parcel);
mOwner.writeToParcel(parcel);
parcel->writeInt32(mIsEncoder);
+ parcel->writeUint32(mRank);
parcel->writeInt32(mCaps.size());
for (size_t i = 0; i < mCaps.size(); i++) {
mCaps.keyAt(i).writeToParcel(parcel);
@@ -210,7 +217,7 @@
return -1;
}
-MediaCodecInfo::MediaCodecInfo() {
+MediaCodecInfo::MediaCodecInfo() : mRank(0x100) {
}
void MediaCodecInfoWriter::setName(const char* name) {
@@ -225,6 +232,10 @@
mInfo->mIsEncoder = isEncoder;
}
+void MediaCodecInfoWriter::setRank(uint32_t rank) {
+ mInfo->mRank = rank;
+}
+
std::unique_ptr<MediaCodecInfo::CapabilitiesWriter>
MediaCodecInfoWriter::addMime(const char *mime) {
ssize_t ix = mInfo->getCapabilityIndex(mime);
diff --git a/media/libmedia/include/media/MediaCodecInfo.h b/media/libmedia/include/media/MediaCodecInfo.h
index ab2cd24..b3777d3 100644
--- a/media/libmedia/include/media/MediaCodecInfo.h
+++ b/media/libmedia/include/media/MediaCodecInfo.h
@@ -170,6 +170,7 @@
* Currently, this is the "instance name" of the IOmx service.
*/
const char *getOwnerName() const;
+ uint32_t rank() const;
/**
* Serialization over Binder
@@ -182,6 +183,7 @@
AString mOwner;
bool mIsEncoder;
KeyedVector<AString, sp<Capabilities> > mCaps;
+ uint32_t mRank;
ssize_t getCapabilityIndex(const char *mime) const;
@@ -252,6 +254,13 @@
* @return `true` if `mime` is removed; `false` if `mime` is not found.
*/
bool removeMime(const char* mime);
+ /**
+ * Set rank of the codec. MediaCodecList will stable-sort the list according
+ * to rank in non-descending order.
+ *
+ * @param rank The rank of the component.
+ */
+ void setRank(uint32_t rank);
private:
/**
* The associated `MediaCodecInfo`.
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 6da6c13..b296622 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -6349,90 +6349,54 @@
Vector<AString> matchingCodecs;
Vector<AString> owners;
- AString mime;
-
AString componentName;
- int32_t encoder = false;
- if (msg->findString("componentName", &componentName)) {
- sp<IMediaCodecList> list = MediaCodecList::getInstance();
- if (list == nullptr) {
- ALOGE("Unable to obtain MediaCodecList while "
- "attempting to create codec \"%s\"",
- componentName.c_str());
- mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
- return false;
- }
- ssize_t index = list->findCodecByName(componentName.c_str());
- if (index < 0) {
- ALOGE("Unable to find codec \"%s\"",
- componentName.c_str());
- mCodec->signalError(OMX_ErrorInvalidComponent, NAME_NOT_FOUND);
- return false;
- }
- sp<MediaCodecInfo> info = list->getCodecInfo(index);
- if (info == nullptr) {
- ALOGE("Unexpected error (index out-of-bound) while "
- "retrieving information for codec \"%s\"",
- componentName.c_str());
- mCodec->signalError(OMX_ErrorUndefined, UNKNOWN_ERROR);
- return false;
- }
- matchingCodecs.add(info->getCodecName());
- owners.add(info->getOwnerName() == nullptr ?
- "default" : info->getOwnerName());
- } else {
- CHECK(msg->findString("mime", &mime));
+ CHECK(msg->findString("componentName", &componentName));
- if (!msg->findInt32("encoder", &encoder)) {
- encoder = false;
- }
-
- MediaCodecList::findMatchingCodecs(
- mime.c_str(),
- encoder, // createEncoder
- 0, // flags
- &matchingCodecs,
- &owners);
+ sp<IMediaCodecList> list = MediaCodecList::getInstance();
+ if (list == nullptr) {
+ ALOGE("Unable to obtain MediaCodecList while "
+ "attempting to create codec \"%s\"",
+ componentName.c_str());
+ mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
+ return false;
}
+ ssize_t index = list->findCodecByName(componentName.c_str());
+ if (index < 0) {
+ ALOGE("Unable to find codec \"%s\"",
+ componentName.c_str());
+ mCodec->signalError(OMX_ErrorInvalidComponent, NAME_NOT_FOUND);
+ return false;
+ }
+ sp<MediaCodecInfo> info = list->getCodecInfo(index);
+ if (info == nullptr) {
+ ALOGE("Unexpected error (index out-of-bound) while "
+ "retrieving information for codec \"%s\"",
+ componentName.c_str());
+ mCodec->signalError(OMX_ErrorUndefined, UNKNOWN_ERROR);
+ return false;
+ }
+ AString owner = (info->getOwnerName() == nullptr) ? "default" : info->getOwnerName();
sp<CodecObserver> observer = new CodecObserver;
sp<IOMX> omx;
sp<IOMXNode> omxNode;
status_t err = NAME_NOT_FOUND;
- for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
- ++matchIndex) {
- componentName = matchingCodecs[matchIndex];
-
- OMXClient client;
- if (client.connect(owners[matchIndex].c_str()) != OK) {
- mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
- return false;
- }
- omx = client.interface();
-
- pid_t tid = gettid();
- int prevPriority = androidGetThreadPriority(tid);
- androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
- err = omx->allocateNode(componentName.c_str(), observer, &omxNode);
- androidSetThreadPriority(tid, prevPriority);
-
- if (err == OK) {
- break;
- } else {
- ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
- }
-
- omxNode = NULL;
+ OMXClient client;
+ if (client.connect(owner.c_str()) != OK) {
+ mCodec->signalError(OMX_ErrorUndefined, NO_INIT);
+ return false;
}
+ omx = client.interface();
- if (omxNode == NULL) {
- if (!mime.empty()) {
- ALOGE("Unable to instantiate a %scoder for type '%s' with err %#x.",
- encoder ? "en" : "de", mime.c_str(), err);
- } else {
- ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
- }
+ pid_t tid = gettid();
+ int prevPriority = androidGetThreadPriority(tid);
+ androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
+ err = omx->allocateNode(componentName.c_str(), observer, &omxNode);
+ androidSetThreadPriority(tid, prevPriority);
+
+ if (err != OK) {
+ ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
return false;
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 8a15a50..f598062 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -63,6 +63,7 @@
"C2OMXNode.cpp",
"CCodec.cpp",
"CCodecBufferChannel.cpp",
+ "Codec2InfoBuilder.cpp",
"CodecBase.cpp",
"CallbackDataSource.cpp",
"CallbackMediaSource.cpp",
diff --git a/media/libstagefright/CCodec.cpp b/media/libstagefright/CCodec.cpp
index bb70458..f62ee41 100644
--- a/media/libstagefright/CCodec.cpp
+++ b/media/libstagefright/CCodec.cpp
@@ -313,6 +313,19 @@
}
void CCodec::configure(const sp<AMessage> &msg) {
+ std::shared_ptr<C2ComponentInterface> intf;
+ {
+ Mutexed<State>::Locked state(mState);
+ if (state->get() != ALLOCATED) {
+ state->set(RELEASED);
+ state.unlock();
+ mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
+ state.lock();
+ return;
+ }
+ intf = state->comp->intf();
+ }
+
sp<AMessage> inputFormat(new AMessage);
sp<AMessage> outputFormat(new AMessage);
if (status_t err = [=] {
@@ -332,11 +345,34 @@
setSurface(surface);
}
+ std::vector<std::unique_ptr<C2Param>> params;
+ std::initializer_list<C2Param::Index> indices {
+ C2PortMimeConfig::input::PARAM_TYPE,
+ C2PortMimeConfig::output::PARAM_TYPE,
+ };
+ c2_status_t c2err = intf->query_vb(
+ {},
+ indices,
+ C2_DONT_BLOCK,
+ ¶ms);
+ if (c2err != C2_OK) {
+ ALOGE("Failed to query component interface: %d", c2err);
+ return UNKNOWN_ERROR;
+ }
+ if (params.size() != indices.size()) {
+ ALOGE("Component returns wrong number of params");
+ return UNKNOWN_ERROR;
+ }
+ if (!params[0] || !params[1]) {
+ ALOGE("Component returns null params");
+ return UNKNOWN_ERROR;
+ }
+ inputFormat->setString("mime", ((C2PortMimeConfig *)params[0].get())->m.value);
+ outputFormat->setString("mime", ((C2PortMimeConfig *)params[1].get())->m.value);
+
// XXX: hack
bool audio = mime.startsWithIgnoreCase("audio/");
if (encoder) {
- outputFormat->setString("mime", mime);
- inputFormat->setString("mime", AStringPrintf("%s/raw", audio ? "audio" : "video"));
if (audio) {
inputFormat->setInt32("channel-count", 1);
inputFormat->setInt32("sample-rate", 44100);
@@ -347,8 +383,6 @@
outputFormat->setInt32("height", 1920);
}
} else {
- inputFormat->setString("mime", mime);
- outputFormat->setString("mime", AStringPrintf("%s/raw", audio ? "audio" : "video"));
if (audio) {
outputFormat->setInt32("channel-count", 2);
outputFormat->setInt32("sample-rate", 44100);
@@ -712,7 +746,7 @@
switch (msg->what()) {
case kWhatAllocate: {
// C2ComponentStore::createComponent() should return within 100ms.
- setDeadline(now + 150ms);
+ setDeadline(now + 150ms, "allocate");
AString componentName;
CHECK(msg->findString("componentName", &componentName));
allocate(componentName);
@@ -720,7 +754,7 @@
}
case kWhatConfigure: {
// C2Component::commit_sm() should return within 5ms.
- setDeadline(now + 50ms);
+ setDeadline(now + 50ms, "configure");
sp<AMessage> format;
CHECK(msg->findMessage("format", &format));
configure(format);
@@ -728,31 +762,31 @@
}
case kWhatStart: {
// C2Component::start() should return within 500ms.
- setDeadline(now + 550ms);
+ setDeadline(now + 550ms, "start");
start();
break;
}
case kWhatStop: {
// C2Component::stop() should return within 500ms.
- setDeadline(now + 550ms);
+ setDeadline(now + 550ms, "stop");
stop();
break;
}
case kWhatFlush: {
// C2Component::flush_sm() should return within 5ms.
- setDeadline(now + 50ms);
+ setDeadline(now + 50ms, "flush");
flush();
break;
}
case kWhatCreateInputSurface: {
// Surface operations may be briefly blocking.
- setDeadline(now + 100ms);
+ setDeadline(now + 100ms, "createInputSurface");
createInputSurface();
break;
}
case kWhatSetInputSurface: {
// Surface operations may be briefly blocking.
- setDeadline(now + 100ms);
+ setDeadline(now + 100ms, "setInputSurface");
sp<RefBase> obj;
CHECK(msg->findObject("surface", &obj));
sp<PersistentSurface> surface(static_cast<PersistentSurface *>(obj.get()));
@@ -780,25 +814,28 @@
break;
}
}
- setDeadline(TimePoint::max());
+ setDeadline(TimePoint::max(), "none");
}
-void CCodec::setDeadline(const TimePoint &newDeadline) {
- Mutexed<TimePoint>::Locked deadline(mDeadline);
- *deadline = newDeadline;
+void CCodec::setDeadline(const TimePoint &newDeadline, const char *name) {
+ Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
+ deadline->set(newDeadline, name);
}
void CCodec::initiateReleaseIfStuck() {
+ std::string name;
{
- Mutexed<TimePoint>::Locked deadline(mDeadline);
- if (*deadline >= std::chrono::steady_clock::now()) {
+ Mutexed<NamedTimePoint>::Locked deadline(mDeadline);
+ if (deadline->get() >= std::chrono::steady_clock::now()) {
// We're not stuck.
return;
}
+ name = deadline->getName();
}
+ ALOGW("previous call to %s exceeded timeout", name.c_str());
mCallback->onError(UNKNOWN_ERROR, ACTION_CODE_FATAL);
- initiateRelease();
+ initiateRelease(false);
}
} // namespace android
diff --git a/media/libstagefright/Codec2InfoBuilder.cpp b/media/libstagefright/Codec2InfoBuilder.cpp
new file mode 100644
index 0000000..ee7258d
--- /dev/null
+++ b/media/libstagefright/Codec2InfoBuilder.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "Codec2InfoBuilder"
+#include <log/log.h>
+
+#include <C2Component.h>
+#include <C2PlatformSupport.h>
+#include <C2V4l2Support.h>
+
+#include <cutils/properties.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+#include <media/stagefright/Codec2InfoBuilder.h>
+
+namespace android {
+
+using ConstTraitsPtr = std::shared_ptr<const C2Component::Traits>;
+
+status_t Codec2InfoBuilder::buildMediaCodecList(MediaCodecListWriter* writer) {
+ // Obtain C2ComponentStore
+ std::shared_ptr<C2ComponentStore> store = GetCodec2PlatformComponentStore();
+ if (store == nullptr) {
+ ALOGE("Cannot find a component store.");
+ return NO_INIT;
+ }
+
+ std::vector<ConstTraitsPtr> traits = store->listComponents();
+
+ if (property_get_bool("debug.stagefright.ccodec_v4l2", false)) {
+ std::shared_ptr<C2ComponentStore> v4l2Store = GetCodec2VDAComponentStore();
+ if (v4l2Store == nullptr) {
+ ALOGD("Cannot find a V4L2 component store.");
+ // non-fatal.
+ } else {
+ std::vector<ConstTraitsPtr> v4l2Traits = v4l2Store->listComponents();
+ traits.insert(traits.end(), v4l2Traits.begin(), v4l2Traits.end());
+ }
+ }
+
+ for (const ConstTraitsPtr &trait : traits) {
+ std::unique_ptr<MediaCodecInfoWriter> codecInfo = writer->addMediaCodecInfo();
+ codecInfo->setName(trait->name.c_str());
+ codecInfo->setOwner("dummy");
+ // TODO: get this from trait->kind
+ codecInfo->setEncoder(trait->name.find("encoder") != std::string::npos);
+ codecInfo->setRank(trait->rank);
+ (void)codecInfo->addMime(trait->mediaType.c_str());
+ }
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 2b33708..7d5c63a 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -421,13 +421,33 @@
sp<MediaCodec> MediaCodec::CreateByType(
const sp<ALooper> &looper, const AString &mime, bool encoder, status_t *err, pid_t pid,
uid_t uid) {
- sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
+ Vector<AString> matchingCodecs;
+ Vector<AString> owners;
- const status_t ret = codec->init(mime, true /* nameIsType */, encoder);
+ MediaCodecList::findMatchingCodecs(
+ mime.c_str(),
+ encoder,
+ 0,
+ &matchingCodecs,
+ &owners);
+
if (err != NULL) {
- *err = ret;
+ *err = NAME_NOT_FOUND;
}
- return ret == OK ? codec : NULL; // NULL deallocates codec.
+ for (size_t i = 0; i < matchingCodecs.size(); ++i) {
+ sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
+ AString componentName = matchingCodecs[i];
+ status_t ret = codec->init(componentName);
+ if (err != NULL) {
+ *err = ret;
+ }
+ if (ret == OK) {
+ return codec;
+ }
+ ALOGD("Allocating component '%s' failed (%d), try next one.",
+ componentName.c_str(), ret);
+ }
+ return NULL;
}
// static
@@ -435,7 +455,7 @@
const sp<ALooper> &looper, const AString &name, status_t *err, pid_t pid, uid_t uid) {
sp<MediaCodec> codec = new MediaCodec(looper, pid, uid);
- const status_t ret = codec->init(name, false /* nameIsType */, false /* encoder */);
+ const status_t ret = codec->init(name);
if (err != NULL) {
*err = ret;
}
@@ -553,11 +573,11 @@
}
//static
-sp<CodecBase> MediaCodec::GetCodecBase(const AString &name, bool nameIsType) {
+sp<CodecBase> MediaCodec::GetCodecBase(const AString &name) {
static bool ccodecEnabled = property_get_bool("debug.stagefright.ccodec", false);
- if (ccodecEnabled && !nameIsType && name.startsWithIgnoreCase("c2.")) {
+ if (ccodecEnabled && name.startsWithIgnoreCase("c2.")) {
return new CCodec;
- } else if (nameIsType || name.startsWithIgnoreCase("omx.")) {
+ } else if (name.startsWithIgnoreCase("omx.")) {
// at this time only ACodec specifies a mime type.
return new ACodec;
} else if (name.startsWithIgnoreCase("android.filter.")) {
@@ -567,48 +587,42 @@
}
}
-status_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder) {
+status_t MediaCodec::init(const AString &name) {
mResourceManagerService->init();
// save init parameters for reset
mInitName = name;
- mInitNameIsType = nameIsType;
- mInitIsEncoder = encoder;
// Current video decoders do not return from OMX_FillThisBuffer
// quickly, violating the OpenMAX specs, until that is remedied
// we need to invest in an extra looper to free the main event
// queue.
- mCodec = GetCodecBase(name, nameIsType);
+ mCodec = GetCodecBase(name);
if (mCodec == NULL) {
return NAME_NOT_FOUND;
}
bool secureCodec = false;
- if (nameIsType && !strncasecmp(name.c_str(), "video/", 6)) {
- mIsVideo = true;
- } else {
- AString tmp = name;
- if (tmp.endsWith(".secure")) {
- secureCodec = true;
- tmp.erase(tmp.size() - 7, 7);
- }
- const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
- if (mcl == NULL) {
- mCodec = NULL; // remove the codec.
- return NO_INIT; // if called from Java should raise IOException
- }
- ssize_t codecIdx = mcl->findCodecByName(tmp.c_str());
- if (codecIdx >= 0) {
- const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx);
- Vector<AString> mimes;
- info->getSupportedMimes(&mimes);
- for (size_t i = 0; i < mimes.size(); i++) {
- if (mimes[i].startsWith("video/")) {
- mIsVideo = true;
- break;
- }
+ AString tmp = name;
+ if (tmp.endsWith(".secure")) {
+ secureCodec = true;
+ tmp.erase(tmp.size() - 7, 7);
+ }
+ const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
+ if (mcl == NULL) {
+ mCodec = NULL; // remove the codec.
+ return NO_INIT; // if called from Java should raise IOException
+ }
+ ssize_t codecIdx = mcl->findCodecByName(tmp.c_str());
+ if (codecIdx >= 0) {
+ const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx);
+ Vector<AString> mimes;
+ info->getSupportedMimes(&mimes);
+ for (size_t i = 0; i < mimes.size(); i++) {
+ if (mimes[i].startsWith("video/")) {
+ mIsVideo = true;
+ break;
}
}
}
@@ -638,22 +652,10 @@
sp<AMessage> msg = new AMessage(kWhatInit, this);
msg->setString("name", name);
- msg->setInt32("nameIsType", nameIsType);
-
- if (nameIsType) {
- msg->setInt32("encoder", encoder);
- }
if (mAnalyticsItem != NULL) {
- if (nameIsType) {
- // name is the mime type
- mAnalyticsItem->setCString(kCodecMime, name.c_str());
- } else {
- mAnalyticsItem->setCString(kCodecCodec, name.c_str());
- }
+ mAnalyticsItem->setCString(kCodecCodec, name.c_str());
mAnalyticsItem->setCString(kCodecMode, mIsVideo ? kCodecModeVideo : kCodecModeAudio);
- if (nameIsType)
- mAnalyticsItem->setInt32(kCodecEncoder, encoder);
}
status_t err;
@@ -719,6 +721,7 @@
if (format->findInt32("level", &level)) {
mAnalyticsItem->setInt32(kCodecLevel, level);
}
+ mAnalyticsItem->setInt32(kCodecEncoder, (flags & CONFIGURE_FLAG_ENCODE) ? 1 : 0);
}
if (mIsVideo) {
@@ -743,8 +746,7 @@
}
// Prevent possible integer overflow in downstream code.
- if (mInitIsEncoder
- && (uint64_t)mVideoWidth * mVideoHeight > (uint64_t)INT32_MAX / 4) {
+ if ((uint64_t)mVideoWidth * mVideoHeight > (uint64_t)INT32_MAX / 4) {
ALOGE("buffer size is too big, width=%d, height=%d", mVideoWidth, mVideoHeight);
return BAD_VALUE;
}
@@ -1023,7 +1025,7 @@
mHaveInputSurface = false;
if (err == OK) {
- err = init(mInitName, mInitNameIsType, mInitIsEncoder);
+ err = init(mInitName);
}
return err;
}
@@ -1973,21 +1975,8 @@
AString name;
CHECK(msg->findString("name", &name));
- int32_t nameIsType;
- int32_t encoder = false;
- CHECK(msg->findInt32("nameIsType", &nameIsType));
- if (nameIsType) {
- CHECK(msg->findInt32("encoder", &encoder));
- }
-
sp<AMessage> format = new AMessage;
-
- if (nameIsType) {
- format->setString("mime", name.c_str());
- format->setInt32("encoder", encoder);
- } else {
- format->setString("componentName", name.c_str());
- }
+ format->setString("componentName", name.c_str());
mCodec->initiateAllocateComponent(format);
break;
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 54265a4..f595646 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -29,6 +29,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/MediaDefs.h>
+#include <media/stagefright/Codec2InfoBuilder.h>
#include <media/stagefright/MediaCodecList.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/OmxInfoBuilder.h>
@@ -77,6 +78,15 @@
}
OmxInfoBuilder sOmxInfoBuilder;
+Codec2InfoBuilder sCodec2InfoBuilder;
+
+std::initializer_list<MediaCodecListBuilderBase *> GetBuilders() {
+ if (property_get_bool("debug.stagefright.ccodec", false)) {
+ return {&sOmxInfoBuilder, &sCodec2InfoBuilder};
+ } else {
+ return {&sOmxInfoBuilder};
+ }
+}
} // unnamed namespace
@@ -88,7 +98,7 @@
ALOGV("Enter profilerThreadWrapper.");
remove(kProfilingResults); // remove previous result so that it won't be loaded to
// the new MediaCodecList
- sp<MediaCodecList> codecList(new MediaCodecList(&sOmxInfoBuilder));
+ sp<MediaCodecList> codecList(new MediaCodecList(GetBuilders()));
if (codecList->initCheck() != OK) {
ALOGW("Failed to create a new MediaCodecList, skipping codec profiling.");
return nullptr;
@@ -98,7 +108,7 @@
ALOGV("Codec profiling started.");
profileCodecs(infos, kProfilingResults);
ALOGV("Codec profiling completed.");
- codecList = new MediaCodecList(&sOmxInfoBuilder);
+ codecList = new MediaCodecList(GetBuilders());
if (codecList->initCheck() != OK) {
ALOGW("Failed to parse profiling results.");
return nullptr;
@@ -116,7 +126,7 @@
Mutex::Autolock autoLock(sInitMutex);
if (sCodecList == nullptr) {
- MediaCodecList *codecList = new MediaCodecList(&sOmxInfoBuilder);
+ MediaCodecList *codecList = new MediaCodecList(GetBuilders());
if (codecList->initCheck() == OK) {
sCodecList = codecList;
@@ -169,11 +179,28 @@
return sRemoteList;
}
-MediaCodecList::MediaCodecList(MediaCodecListBuilderBase* builder) {
+MediaCodecList::MediaCodecList(std::initializer_list<MediaCodecListBuilderBase*> builders) {
mGlobalSettings = new AMessage();
mCodecInfos.clear();
MediaCodecListWriter writer(this);
- mInitCheck = builder->buildMediaCodecList(&writer);
+ for (MediaCodecListBuilderBase *builder : builders) {
+ mInitCheck = builder->buildMediaCodecList(&writer);
+ if (mInitCheck != OK) {
+ break;
+ }
+ }
+ std::stable_sort(
+ mCodecInfos.begin(),
+ mCodecInfos.end(),
+ [](const sp<MediaCodecInfo> &info1, const sp<MediaCodecInfo> &info2) {
+ if (info2 == nullptr) {
+ return false;
+ } else if (info1 == nullptr) {
+ return true;
+ } else {
+ return info1->rank() < info2->rank();
+ }
+ });
}
MediaCodecList::~MediaCodecList() {
diff --git a/media/libstagefright/OmxInfoBuilder.cpp b/media/libstagefright/OmxInfoBuilder.cpp
index a6ebadd..fe141ab 100644
--- a/media/libstagefright/OmxInfoBuilder.cpp
+++ b/media/libstagefright/OmxInfoBuilder.cpp
@@ -154,22 +154,22 @@
// codec name -> index into swCodecs/hwCodecs
std::map<hidl_string, std::unique_ptr<MediaCodecInfoWriter>>
swCodecName2Info, hwCodecName2Info;
- // owner name -> MediaCodecInfo
- // This map will be used to obtain the correct IOmx service(s) needed for
- // creating IOmxNode instances and querying capabilities.
- std::map<std::string, std::vector<sp<MediaCodecInfo> > >
- owner2CodecInfo;
- for (const auto& role : roles) {
- const auto& typeName = role.type;
+ char rank[PROPERTY_VALUE_MAX];
+ uint32_t defaultRank = 0x100;
+ if (property_get("debug.stagefright.omx_default_rank", rank, nullptr)) {
+ defaultRank = std::strtoul(rank, nullptr, 10);
+ }
+ for (const IOmxStore::RoleInfo& role : roles) {
+ const hidl_string& typeName = role.type;
bool isEncoder = role.isEncoder;
bool preferPlatformNodes = role.preferPlatformNodes;
// If preferPlatformNodes is true, hardware nodes must be added after
// platform (software) nodes. hwCodecs is used to hold hardware nodes
// that need to be added after software nodes for the same role.
std::vector<const IOmxStore::NodeInfo*> hwCodecs;
- for (const auto& node : role.nodes) {
- const auto& nodeName = node.name;
+ for (const IOmxStore::NodeInfo& node : role.nodes) {
+ const hidl_string& nodeName = node.name;
bool isSoftware = hasPrefix(nodeName, "OMX.google");
MediaCodecInfoWriter* info;
if (isSoftware) {
@@ -182,6 +182,7 @@
info->setName(nodeName.c_str());
info->setOwner(node.owner.c_str());
info->setEncoder(isEncoder);
+ info->setRank(defaultRank);
} else {
// The node has been seen before. Simply retrieve the
// existing MediaCodecInfoWriter.
@@ -198,6 +199,7 @@
info->setName(nodeName.c_str());
info->setOwner(node.owner.c_str());
info->setEncoder(isEncoder);
+ info->setRank(defaultRank);
} else {
// If preferPlatformNodes is true, this node must be
// added after all software nodes.
@@ -224,9 +226,9 @@
// added in the loop above, but rather saved in hwCodecs. They are
// going to be added here.
if (preferPlatformNodes) {
- for (const auto& node : hwCodecs) {
+ for (const IOmxStore::NodeInfo *node : hwCodecs) {
MediaCodecInfoWriter* info;
- const auto& nodeName = node->name;
+ const hidl_string& nodeName = node->name;
auto c2i = hwCodecName2Info.find(nodeName);
if (c2i == hwCodecName2Info.end()) {
// Create a new MediaCodecInfo for a new node.
@@ -236,6 +238,7 @@
info->setName(nodeName.c_str());
info->setOwner(node->owner.c_str());
info->setEncoder(isEncoder);
+ info->setRank(defaultRank);
} else {
// The node has been seen before. Simply retrieve the
// existing MediaCodecInfoWriter.
diff --git a/media/libstagefright/codec2/SimpleC2Component.cpp b/media/libstagefright/codec2/SimpleC2Component.cpp
index c345783..333cfeb 100644
--- a/media/libstagefright/codec2/SimpleC2Component.cpp
+++ b/media/libstagefright/codec2/SimpleC2Component.cpp
@@ -226,7 +226,9 @@
releasing = std::move(state->mThread);
}
mExitRequested = true;
- releasing.join();
+ if (releasing.joinable()) {
+ releasing.join();
+ }
onRelease();
return C2_OK;
}
diff --git a/media/libstagefright/codec2/SimpleC2Interface.cpp b/media/libstagefright/codec2/SimpleC2Interface.cpp
index f082243..d159426 100644
--- a/media/libstagefright/codec2/SimpleC2Interface.cpp
+++ b/media/libstagefright/codec2/SimpleC2Interface.cpp
@@ -45,15 +45,38 @@
if (heapParams) {
heapParams->clear();
for (const auto &index : heapParamIndices) {
- if (index.coreIndex() != C2StreamFormatConfig::CORE_INDEX
- || !index.forStream()
- || index.stream() != 0u) {
- heapParams->push_back(nullptr);
- }
- if (index.forInput()) {
- heapParams->push_back(C2Param::Copy(mInputFormat));
- } else {
- heapParams->push_back(C2Param::Copy(mOutputFormat));
+ switch (index.type()) {
+ case C2StreamFormatConfig::input::PARAM_TYPE:
+ if (index.stream() == 0u) {
+ heapParams->push_back(C2Param::Copy(mInputFormat));
+ } else {
+ heapParams->push_back(nullptr);
+ }
+ break;
+ case C2StreamFormatConfig::output::PARAM_TYPE:
+ if (index.stream() == 0u) {
+ heapParams->push_back(C2Param::Copy(mOutputFormat));
+ } else {
+ heapParams->push_back(nullptr);
+ }
+ break;
+ case C2PortMimeConfig::input::PARAM_TYPE:
+ if (mInputMediaType) {
+ heapParams->push_back(C2Param::Copy(*mInputMediaType));
+ } else {
+ heapParams->push_back(nullptr);
+ }
+ break;
+ case C2PortMimeConfig::output::PARAM_TYPE:
+ if (mOutputMediaType) {
+ heapParams->push_back(C2Param::Copy(*mOutputMediaType));
+ } else {
+ heapParams->push_back(nullptr);
+ }
+ break;
+ default:
+ heapParams->push_back(nullptr);
+ break;
}
}
}
diff --git a/media/libstagefright/codec2/include/C2Component.h b/media/libstagefright/codec2/include/C2Component.h
index 61fcfc0..dbcd82d 100644
--- a/media/libstagefright/codec2/include/C2Component.h
+++ b/media/libstagefright/codec2/include/C2Component.h
@@ -398,7 +398,7 @@
domain_t domain; ///< component domain (e.g. audio or video)
kind_t kind; ///< component kind (e.g. encoder, decoder or filter)
rank_t rank; ///< rank used to determine component ordering (the lower the sooner)
- C2StringLiteral mediaType; ///< media type supported by the component
+ C2String mediaType; ///< media type supported by the component
/**
* name alias(es) for backward compatibility.
diff --git a/media/libstagefright/codec2/include/SimpleC2Interface.h b/media/libstagefright/codec2/include/SimpleC2Interface.h
index b934f12..310096f 100644
--- a/media/libstagefright/codec2/include/SimpleC2Interface.h
+++ b/media/libstagefright/codec2/include/SimpleC2Interface.h
@@ -27,13 +27,9 @@
public:
inline Builder(
const char *name,
- c2_node_id_t id)
- : mIntf(new SimpleC2Interface(name, id)) {}
-
- inline Builder(
- const char *name,
c2_node_id_t id,
- std::function<void(::android::SimpleC2Interface*)> deleter)
+ std::function<void(C2ComponentInterface*)> deleter =
+ std::default_delete<C2ComponentInterface>())
: mIntf(new SimpleC2Interface(name, id), deleter) {}
inline Builder &inputFormat(C2FormatKind input) {
@@ -46,6 +42,28 @@
return *this;
}
+ inline Builder &inputMediaType(const char *mediaType, size_t maxLen = 128) {
+ mIntf->mInputMediaType = C2PortMimeConfig::input::AllocShared(maxLen);
+ std::strncpy(mIntf->mInputMediaType->m.value, mediaType, maxLen);
+ return *this;
+ }
+
+ inline Builder &outputMediaType(const char *mediaType, size_t maxLen = 128) {
+ mIntf->mOutputMediaType = C2PortMimeConfig::output::AllocShared(maxLen);
+ std::strncpy(mIntf->mOutputMediaType->m.value, mediaType, maxLen);
+ return *this;
+ }
+
+ template<size_t N>
+ inline Builder &inputMediaType(const char mediaType[N]) {
+ return inputMediaType(mediaType, N);
+ }
+
+ template<size_t N>
+ inline Builder &outputMediaType(const char mediaType[N]) {
+ return outputMediaType(mediaType, N);
+ }
+
inline std::shared_ptr<SimpleC2Interface> build() {
return mIntf;
}
@@ -89,6 +107,8 @@
const c2_node_id_t mId;
C2StreamFormatConfig::input mInputFormat;
C2StreamFormatConfig::output mOutputFormat;
+ std::shared_ptr<C2PortMimeConfig::input> mInputMediaType;
+ std::shared_ptr<C2PortMimeConfig::output> mOutputMediaType;
SimpleC2Interface() = delete;
};
diff --git a/media/libstagefright/codec2/vndk/C2Store.cpp b/media/libstagefright/codec2/vndk/C2Store.cpp
index c4ed2f4..f612b4f 100644
--- a/media/libstagefright/codec2/vndk/C2Store.cpp
+++ b/media/libstagefright/codec2/vndk/C2Store.cpp
@@ -203,9 +203,17 @@
/**
* Creates an uninitialized component module.
*
+ * \param name[in] component name.
+ *
* \note Only used by ComponentLoader.
*/
- ComponentModule() : mInit(C2_NO_INIT) {}
+ ComponentModule()
+ : mInit(C2_NO_INIT),
+ mLibHandle(nullptr),
+ createFactory(nullptr),
+ destroyFactory(nullptr),
+ mComponentFactory(nullptr) {
+ }
/**
* Initializes a component module with a given library path. Must be called exactly once.
@@ -383,12 +391,35 @@
std::shared_ptr<C2ComponentInterface> intf;
c2_status_t res = createInterface(0, &intf);
if (res != C2_OK) {
+ ALOGD("failed to create interface: %d", res);
return nullptr;
}
std::shared_ptr<C2Component::Traits> traits(new (std::nothrow) C2Component::Traits);
if (traits) {
- // traits->name = intf->getName();
+ traits->name = intf->getName();
+ // TODO: get this from interface properly.
+ bool encoder = (traits->name.find("encoder") != std::string::npos);
+ uint32_t mediaTypeIndex = encoder ? C2PortMimeConfig::output::PARAM_TYPE
+ : C2PortMimeConfig::input::PARAM_TYPE;
+ std::vector<std::unique_ptr<C2Param>> params;
+ res = intf->query_vb({}, { mediaTypeIndex }, C2_MAY_BLOCK, ¶ms);
+ if (res != C2_OK) {
+ ALOGD("failed to query interface: %d", res);
+ return nullptr;
+ }
+ if (params.size() != 1u) {
+ ALOGD("failed to query interface: unexpected vector size: %zu", params.size());
+ return nullptr;
+ }
+ C2PortMimeConfig *mediaTypeConfig = (C2PortMimeConfig *)(params[0].get());
+ if (mediaTypeConfig == nullptr) {
+ ALOGD("failed to query media type");
+ return nullptr;
+ }
+ traits->mediaType = mediaTypeConfig->m.value;
+ // TODO: get this properly.
+ traits->rank = 0x200;
}
mTraits = traits;
diff --git a/media/libstagefright/codecs/aacdec/C2SoftAac.cpp b/media/libstagefright/codecs/aacdec/C2SoftAac.cpp
index 3f09e0a..c82ea45 100644
--- a/media/libstagefright/codecs/aacdec/C2SoftAac.cpp
+++ b/media/libstagefright/codecs/aacdec/C2SoftAac.cpp
@@ -25,6 +25,7 @@
#include <cutils/properties.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/MediaDefs.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MediaErrors.h>
#include <utils/misc.h>
@@ -50,12 +51,22 @@
namespace android {
-C2SoftAac::C2SoftAac(const char *name, c2_node_id_t id)
- : SimpleC2Component(
- SimpleC2Interface::Builder(name, id)
+constexpr char kComponentName[] = "c2.google.aac.decoder";
+
+static std::shared_ptr<C2ComponentInterface> BuildIntf(
+ const char *name, c2_node_id_t id,
+ std::function<void(C2ComponentInterface*)> deleter =
+ std::default_delete<C2ComponentInterface>()) {
+ return SimpleC2Interface::Builder(name, id, deleter)
.inputFormat(C2FormatCompressed)
.outputFormat(C2FormatAudio)
- .build()),
+ .inputMediaType(MEDIA_MIMETYPE_AUDIO_AAC)
+ .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
+ .build();
+}
+
+C2SoftAac::C2SoftAac(const char *name, c2_node_id_t id)
+ : SimpleC2Component(BuildIntf(name, id)),
mAACDecoder(NULL),
mStreamInfo(NULL),
mIsADTS(false),
@@ -333,6 +344,7 @@
const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2BlockPool> &pool) {
work->workletsProcessed = 0u;
+ work->result = C2_OK;
if (mSignalledError) {
return;
}
@@ -675,20 +687,18 @@
class C2SoftAacDecFactory : public C2ComponentFactory {
public:
virtual c2_status_t createComponent(
- c2_node_id_t id, std::shared_ptr<C2Component>* const component,
- std::function<void(::C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftAac("aac", id), deleter);
+ c2_node_id_t id,
+ std::shared_ptr<C2Component>* const component,
+ std::function<void(C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(new C2SoftAac(kComponentName, id), deleter);
return C2_OK;
}
virtual c2_status_t createInterface(
- c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(::C2ComponentInterface*)> deleter) override {
- *interface =
- SimpleC2Interface::Builder("aac", id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatVideo)
- .build();
+ c2_node_id_t id,
+ std::shared_ptr<C2ComponentInterface>* const interface,
+ std::function<void(C2ComponentInterface*)> deleter) override {
+ *interface = BuildIntf(kComponentName, id, deleter);
return C2_OK;
}
diff --git a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
index 74f5a7a..70f6817 100644
--- a/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
+++ b/media/libstagefright/codecs/aacenc/C2SoftAacEnc.cpp
@@ -22,20 +22,31 @@
#include <C2PlatformSupport.h>
#include <SimpleC2Interface.h>
+#include <media/stagefright/foundation/MediaDefs.h>
#include <media/stagefright/foundation/hexdump.h>
#include "C2SoftAacEnc.h"
namespace android {
+constexpr char kComponentName[] = "c2.google.aac.encoder";
+
+static std::shared_ptr<C2ComponentInterface> BuildIntf(
+ const char *name, c2_node_id_t id,
+ std::function<void(C2ComponentInterface*)> deleter =
+ std::default_delete<C2ComponentInterface>()) {
+ return SimpleC2Interface::Builder(name, id, deleter)
+ .inputFormat(C2FormatAudio)
+ .outputFormat(C2FormatCompressed)
+ .inputMediaType(MEDIA_MIMETYPE_AUDIO_AAC)
+ .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
+ .build();
+}
+
C2SoftAacEnc::C2SoftAacEnc(
const char *name,
c2_node_id_t id)
- : SimpleC2Component(
- SimpleC2Interface::Builder(name, id)
- .inputFormat(C2FormatAudio)
- .outputFormat(C2FormatCompressed)
- .build()),
+ : SimpleC2Component(BuildIntf(name, id)),
mAACEncoder(NULL),
mNumChannels(1),
mSampleRate(44100),
@@ -176,6 +187,7 @@
void C2SoftAacEnc::process(
const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2BlockPool> &pool) {
+ work->result = C2_OK;
work->workletsProcessed = 0u;
if (mSignalledError) {
@@ -381,20 +393,17 @@
class C2SoftAacEncFactory : public C2ComponentFactory {
public:
virtual c2_status_t createComponent(
- c2_node_id_t id, std::shared_ptr<C2Component>* const component,
- std::function<void(::C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftAacEnc("aacenc", id), deleter);
+ c2_node_id_t id,
+ std::shared_ptr<C2Component>* const component,
+ std::function<void(C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(new C2SoftAacEnc(kComponentName, id), deleter);
return C2_OK;
}
virtual c2_status_t createInterface(
c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(::C2ComponentInterface*)> deleter) override {
- *interface =
- SimpleC2Interface::Builder("aacenc", id, deleter)
- .inputFormat(C2FormatAudio)
- .outputFormat(C2FormatCompressed)
- .build();
+ std::function<void(C2ComponentInterface*)> deleter) override {
+ *interface = BuildIntf(kComponentName, id, deleter);
return C2_OK;
}
diff --git a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
index 3c09e37..b9ba251 100644
--- a/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
+++ b/media/libstagefright/codecs/avcdec/C2SoftAvcDec.cpp
@@ -54,7 +54,7 @@
#define PRINT_TIME ALOGV
-#define componentName "video_decoder.avc"
+constexpr char kComponentName[] = "c2.google.avc.decoder";
// #define codingType OMX_VIDEO_CodingAVC
#define CODEC_MIME_TYPE MEDIA_MIMETYPE_VIDEO_AVC
@@ -71,6 +71,18 @@
(IVD_CONTROL_API_COMMAND_TYPE_T)IH264D_CMD_CTL_SET_NUM_CORES
namespace {
+std::shared_ptr<C2ComponentInterface> BuildIntf(
+ const char *name, c2_node_id_t id,
+ std::function<void(C2ComponentInterface*)> deleter =
+ std::default_delete<C2ComponentInterface>()) {
+ return SimpleC2Interface::Builder(name, id, deleter)
+ .inputFormat(C2FormatCompressed)
+ .outputFormat(C2FormatVideo)
+ .inputMediaType(MEDIA_MIMETYPE_VIDEO_AVC)
+ .outputMediaType(MEDIA_MIMETYPE_VIDEO_RAW)
+ .build();
+}
+
#if 0
using SupportedValuesWithFields = C2SoftAvcDecIntf::SupportedValuesWithFields;
@@ -614,11 +626,7 @@
C2SoftAvcDec::C2SoftAvcDec(
const char *name,
c2_node_id_t id)
- : SimpleC2Component(
- SimpleC2Interface::Builder(name, id)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatVideo)
- .build()),
+ : SimpleC2Component(BuildIntf(name, id)),
mCodecCtx(NULL),
mFlushOutBuffer(NULL),
mIvColorFormat(IV_YUV_420P),
@@ -1327,21 +1335,18 @@
class C2SoftAvcDecFactory : public C2ComponentFactory {
public:
virtual c2_status_t createComponent(
- c2_node_id_t id, std::shared_ptr<C2Component>* const component,
- std::function<void(::C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftAvcDec("avc", id), deleter);
+ c2_node_id_t id,
+ std::shared_ptr<C2Component>* const component,
+ std::function<void(C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(new C2SoftAvcDec(kComponentName, id), deleter);
return C2_OK;
}
virtual c2_status_t createInterface(
- c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(::C2ComponentInterface*)> deleter) override {
- *interface =
- SimpleC2Interface::Builder("avc", id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatVideo)
- .build();
-// std::shared_ptr<C2ComponentInterface>(new C2SoftAvcDecIntf("avc", id), deleter);
+ c2_node_id_t id,
+ std::shared_ptr<C2ComponentInterface>* const interface,
+ std::function<void(C2ComponentInterface*)> deleter) override {
+ *interface = BuildIntf(kComponentName, id, deleter);
return C2_OK;
}
diff --git a/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.cpp b/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.cpp
index e105460..8fb8122 100644
--- a/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.cpp
+++ b/media/libstagefright/codecs/avcenc/C2SoftAvcEnc.cpp
@@ -35,7 +35,9 @@
namespace android {
-#define ive_api_function ih264e_api_function
+#define ive_api_function ih264e_api_function
+
+constexpr char kComponentName[] = "c2.google.avc.encoder";
namespace {
@@ -55,6 +57,18 @@
return (size_t)cpuCoreCount;
}
+std::shared_ptr<C2ComponentInterface> BuildIntf(
+ const char *name, c2_node_id_t id,
+ std::function<void(C2ComponentInterface*)> deleter =
+ std::default_delete<C2ComponentInterface>()) {
+ return SimpleC2Interface::Builder(name, id, deleter)
+ .inputFormat(C2FormatVideo)
+ .outputFormat(C2FormatCompressed)
+ .inputMediaType(MEDIA_MIMETYPE_VIDEO_RAW)
+ .outputMediaType(MEDIA_MIMETYPE_VIDEO_AVC)
+ .build();
+}
+
void ConvertRGBToPlanarYUV(
uint8_t *dstY, size_t dstStride, size_t dstVStride,
const C2GraphicView &src) {
@@ -115,11 +129,7 @@
} // namespace
C2SoftAvcEnc::C2SoftAvcEnc(const char *name, c2_node_id_t id)
- : SimpleC2Component(
- SimpleC2Interface::Builder(name, id)
- .inputFormat(C2FormatVideo)
- .outputFormat(C2FormatCompressed)
- .build()),
+ : SimpleC2Component(BuildIntf(name, id)),
mUpdateFlag(0),
mIvVideoColorFormat(IV_YUV_420P),
mAVCEncProfile(IV_PROFILE_BASE),
@@ -1209,20 +1219,18 @@
class C2SoftAvcEncFactory : public C2ComponentFactory {
public:
virtual c2_status_t createComponent(
- c2_node_id_t id, std::shared_ptr<C2Component>* const component,
- std::function<void(::C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftAvcEnc("avcenc", id), deleter);
+ c2_node_id_t id,
+ std::shared_ptr<C2Component>* const component,
+ std::function<void(C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(new C2SoftAvcEnc(kComponentName, id), deleter);
return C2_OK;
}
virtual c2_status_t createInterface(
- c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(::C2ComponentInterface*)> deleter) override {
- *interface =
- SimpleC2Interface::Builder("avcenc", id, deleter)
- .inputFormat(C2FormatVideo)
- .outputFormat(C2FormatCompressed)
- .build();
+ c2_node_id_t id,
+ std::shared_ptr<C2ComponentInterface>* const interface,
+ std::function<void(C2ComponentInterface*)> deleter) override {
+ *interface = BuildIntf(kComponentName, id, deleter);
return C2_OK;
}
diff --git a/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp b/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp
index e830324..d296a3d 100644
--- a/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp
+++ b/media/libstagefright/codecs/g711/dec/C2SoftG711.cpp
@@ -24,21 +24,37 @@
#include <SimpleC2Interface.h>
#include <media/stagefright/foundation/ADebug.h>
-
-#ifdef ALAW
-#define COMPONENT_NAME "g711a"
-#else
-#define COMPONENT_NAME "g711m"
-#endif
+#include <media/stagefright/foundation/MediaDefs.h>
namespace android {
-C2SoftG711::C2SoftG711(const char *name, c2_node_id_t id)
- : SimpleC2Component(
- SimpleC2Interface::Builder(name, id)
+#ifdef ALAW
+constexpr char kComponentName[] = "c2.google.g711.alaw.decoder";
+#else
+constexpr char kComponentName[] = "c2.google.g711.mlaw.decoder";
+#endif
+
+static std::shared_ptr<C2ComponentInterface> BuildIntf(
+ const char *name, c2_node_id_t id,
+ std::function<void(C2ComponentInterface*)> deleter =
+ std::default_delete<C2ComponentInterface>()) {
+ return SimpleC2Interface::Builder(name, id, deleter)
.inputFormat(C2FormatCompressed)
.outputFormat(C2FormatAudio)
- .build()) {
+ .inputMediaType(
+#ifdef ALAW
+ MEDIA_MIMETYPE_AUDIO_G711_ALAW
+#else
+ MEDIA_MIMETYPE_AUDIO_G711_MLAW
+#endif
+ )
+ .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
+ .build();
+}
+
+
+C2SoftG711::C2SoftG711(const char *name, c2_node_id_t id)
+ : SimpleC2Component(BuildIntf(name, id)) {
}
C2SoftG711::~C2SoftG711() {
@@ -206,20 +222,17 @@
class C2SoftG711DecFactory : public C2ComponentFactory {
public:
virtual c2_status_t createComponent(
- c2_node_id_t id, std::shared_ptr<C2Component>* const component,
- std::function<void(::C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftG711(COMPONENT_NAME, id), deleter);
+ c2_node_id_t id,
+ std::shared_ptr<C2Component>* const component,
+ std::function<void(C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(new C2SoftG711(kComponentName, id), deleter);
return C2_OK;
}
virtual c2_status_t createInterface(
c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(::C2ComponentInterface*)> deleter) override {
- *interface =
- SimpleC2Interface::Builder(COMPONENT_NAME, id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatAudio)
- .build();
+ std::function<void(C2ComponentInterface*)> deleter) override {
+ *interface = BuildIntf(kComponentName, id, deleter);
return C2_OK;
}
diff --git a/media/libstagefright/codecs/mp3dec/C2SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/C2SoftMP3.cpp
index 9e8b527..9cac87e 100644
--- a/media/libstagefright/codecs/mp3dec/C2SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/C2SoftMP3.cpp
@@ -26,17 +26,28 @@
#include <SimpleC2Interface.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/MediaDefs.h>
#include <numeric>
namespace android {
-C2SoftMP3::C2SoftMP3(const char *name, c2_node_id_t id)
- : SimpleC2Component(
- SimpleC2Interface::Builder(name, id)
+constexpr char kComponentName[] = "c2.google.aac.encoder";
+
+static std::shared_ptr<C2ComponentInterface> BuildIntf(
+ const char *name, c2_node_id_t id,
+ std::function<void(C2ComponentInterface*)> deleter =
+ std::default_delete<C2ComponentInterface>()) {
+ return SimpleC2Interface::Builder(name, id, deleter)
.inputFormat(C2FormatCompressed)
.outputFormat(C2FormatAudio)
- .build()),
+ .inputMediaType(MEDIA_MIMETYPE_AUDIO_MPEG)
+ .outputMediaType(MEDIA_MIMETYPE_AUDIO_RAW)
+ .build();
+}
+
+C2SoftMP3::C2SoftMP3(const char *name, c2_node_id_t id)
+ : SimpleC2Component(BuildIntf(name, id)),
mConfig(nullptr),
mDecoderBuf(nullptr) {
}
@@ -397,20 +408,18 @@
class C2SoftMp3DecFactory : public C2ComponentFactory {
public:
virtual c2_status_t createComponent(
- c2_node_id_t id, std::shared_ptr<C2Component>* const component,
- std::function<void(::C2Component*)> deleter) override {
- *component = std::shared_ptr<C2Component>(new C2SoftMP3("mp3", id), deleter);
+ c2_node_id_t id,
+ std::shared_ptr<C2Component>* const component,
+ std::function<void(C2Component*)> deleter) override {
+ *component = std::shared_ptr<C2Component>(new C2SoftMP3(kComponentName, id), deleter);
return C2_OK;
}
virtual c2_status_t createInterface(
- c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
- std::function<void(::C2ComponentInterface*)> deleter) override {
- *interface =
- SimpleC2Interface::Builder("mp3", id, deleter)
- .inputFormat(C2FormatCompressed)
- .outputFormat(C2FormatAudio)
- .build();
+ c2_node_id_t id,
+ std::shared_ptr<C2ComponentInterface>* const interface,
+ std::function<void(C2ComponentInterface*)> deleter) override {
+ *interface = BuildIntf(kComponentName, id, deleter);
return C2_OK;
}
diff --git a/media/libstagefright/include/media/stagefright/CCodec.h b/media/libstagefright/include/media/stagefright/CCodec.h
index 24ee0a3..3a2670d 100644
--- a/media/libstagefright/include/media/stagefright/CCodec.h
+++ b/media/libstagefright/include/media/stagefright/CCodec.h
@@ -83,7 +83,7 @@
void setInputSurface(const sp<PersistentSurface> &surface);
status_t setupInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface);
- void setDeadline(const TimePoint &deadline);
+ void setDeadline(const TimePoint &deadline, const char *name);
enum {
kWhatAllocate,
@@ -126,10 +126,25 @@
sp<AMessage> outputFormat;
};
+ struct NamedTimePoint {
+ inline void set(
+ const TimePoint &timePoint,
+ const char *name) {
+ mTimePoint = timePoint;
+ mName = name;
+ }
+
+ inline TimePoint get() const { return mTimePoint; }
+ inline const char *getName() const { return mName; }
+ private:
+ TimePoint mTimePoint;
+ const char *mName;
+ };
+
Mutexed<State> mState;
std::shared_ptr<CCodecBufferChannel> mChannel;
std::shared_ptr<C2Component::Listener> mListener;
- Mutexed<TimePoint> mDeadline;
+ Mutexed<NamedTimePoint> mDeadline;
Mutexed<Formats> mFormats;
Mutexed<std::list<std::unique_ptr<C2Work>>> mWorkDoneQueue;
diff --git a/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h b/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h
new file mode 100644
index 0000000..ea0b5c4
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h
@@ -0,0 +1,33 @@
+/*
+ * 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 CODEC2_INFO_BUILDER_H_
+#define CODEC2_INFO_BUILDER_H_
+
+#include <media/stagefright/MediaCodecList.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+class Codec2InfoBuilder : public MediaCodecListBuilderBase {
+public:
+ Codec2InfoBuilder() = default;
+ status_t buildMediaCodecList(MediaCodecListWriter* writer) override;
+};
+
+} // namespace android
+
+#endif // CODEC2_INFO_BUILDER_H_
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 0bc02af..e7faea5 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -334,8 +334,6 @@
// initial create parameters
AString mInitName;
- bool mInitNameIsType;
- bool mInitIsEncoder;
// configure parameter
sp<AMessage> mConfigureMsg;
@@ -370,14 +368,14 @@
MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid);
- static sp<CodecBase> GetCodecBase(const AString &name, bool nameIsType = false);
+ static sp<CodecBase> GetCodecBase(const AString &name);
static status_t PostAndAwaitResponse(
const sp<AMessage> &msg, sp<AMessage> *response);
void PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err);
- status_t init(const AString &name, bool nameIsType, bool encoder);
+ status_t init(const AString &name);
void setState(State newState);
void returnBuffersToCodec(bool isReclaim = false);
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecList.h b/media/libstagefright/include/media/stagefright/MediaCodecList.h
index f2bd496..d46fe85 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecList.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecList.h
@@ -18,6 +18,8 @@
#define MEDIA_CODEC_LIST_H_
+#include <initializer_list>
+
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/foundation/AString.h>
#include <media/IMediaCodecList.h>
@@ -94,9 +96,9 @@
/**
* This constructor will call `buildMediaCodecList()` from the given
- * `MediaCodecListBuilderBase` object.
+ * `MediaCodecListBuilderBase` objects.
*/
- MediaCodecList(MediaCodecListBuilderBase* builder);
+ MediaCodecList(std::initializer_list<MediaCodecListBuilderBase*> builders);
~MediaCodecList();