Decouple libstagefright from Codec 2.0
And load CCodec as a plugin.
Bug: 74403547
Test: adb shell am instrument -e size small -w 'android.media.cts/android.support.test.runner.AndroidJUnitRunner'
Test: adb shell setprop debug.stagefright.ccodec yes
Test: adb shell stagefright -S -N c2.google.avc.decoder /sdcard/a.mp4
Change-Id: I42f4a3d8dde0e1ae9fc2dbeab11be3dc3a8576fb
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 71bff84..e2d5d0d 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -56,6 +56,7 @@
srcs: [
"CodecBase.cpp",
"FrameRenderTracker.cpp",
+ "MediaCodecListWriter.cpp",
],
cflags: [
@@ -66,7 +67,7 @@
shared_libs: [
"libgui",
"liblog",
- "libmedia",
+ "libmedia_omx",
"libstagefright_foundation",
"libui",
"libutils",
@@ -95,6 +96,7 @@
"CCodec.cpp",
"CCodecBufferChannel.cpp",
"Codec2Buffer.cpp",
+ "Codec2InfoBuilder.cpp",
],
cflags: [
@@ -120,8 +122,10 @@
"libstagefright_codecbase",
"libstagefright_foundation",
"libstagefright_omx_utils",
+ "libstagefright_xmlparser",
"libui",
"libutils",
+ // TODO: Remove libv4l2_c2_componentstore.
"libv4l2_c2componentstore",
"android.hardware.cas.native@1.0",
@@ -154,7 +158,6 @@
"AudioPresentationInfo.cpp",
"AudioSource.cpp",
"BufferImpl.cpp",
- "Codec2InfoBuilder.cpp",
"CallbackDataSource.cpp",
"CallbackMediaSource.cpp",
"CameraSource.cpp",
@@ -190,6 +193,7 @@
"SkipCutBuffer.cpp",
"StagefrightMediaScanner.cpp",
"StagefrightMetadataRetriever.cpp",
+ "StagefrightPluginLoader.cpp",
"SurfaceUtils.cpp",
"Utils.cpp",
"ThrottledSource.cpp",
@@ -217,8 +221,6 @@
"libutils",
"libmedia_helper",
"libstagefright_ccodec",
- "libstagefright_codec2",
- "libstagefright_codec2_vndk",
"libstagefright_codecbase",
"libstagefright_foundation",
"libstagefright_omx",
@@ -228,8 +230,6 @@
"libhidlallocatorutils",
"libhidlbase",
"libhidlmemory",
- // TODO: Remove libv4l2_c2_componentstore.
- "libv4l2_c2componentstore",
"libziparchive",
"android.hidl.allocator@1.0",
"android.hardware.cas.native@1.0",
diff --git a/media/libstagefright/CCodec.cpp b/media/libstagefright/CCodec.cpp
index 0a20d34..322f9fd 100644
--- a/media/libstagefright/CCodec.cpp
+++ b/media/libstagefright/CCodec.cpp
@@ -910,3 +910,7 @@
}
} // namespace android
+
+extern "C" android::CodecBase *CreateCodec() {
+ return new android::CCodec;
+}
diff --git a/media/libstagefright/Codec2InfoBuilder.cpp b/media/libstagefright/Codec2InfoBuilder.cpp
index 78c4e38..bd749c4 100644
--- a/media/libstagefright/Codec2InfoBuilder.cpp
+++ b/media/libstagefright/Codec2InfoBuilder.cpp
@@ -159,3 +159,7 @@
}
} // namespace android
+
+extern "C" android::MediaCodecListBuilderBase *CreateBuilder() {
+ return new android::Codec2InfoBuilder;
+}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index edcb8c7..5ad4c01 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -16,11 +16,14 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "MediaCodec"
+#include <utils/Log.h>
+
#include <inttypes.h>
#include "include/SecureBuffer.h"
#include "include/SharedMemoryBuffer.h"
#include "include/SoftwareRenderer.h"
+#include "StagefrightPluginLoader.h"
#include <android/hardware/cas/native/1.0/IDescrambler.h>
@@ -45,7 +48,6 @@
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/ACodec.h>
#include <media/stagefright/BufferProducerWrapper.h>
-#include <media/stagefright/CCodec.h>
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/MediaCodecList.h>
#include <media/stagefright/MediaDefs.h>
@@ -56,7 +58,6 @@
#include <media/stagefright/SurfaceUtils.h>
#include <mediautils/BatteryNotifier.h>
#include <private/android_filesystem_config.h>
-#include <utils/Log.h>
#include <utils/Singleton.h>
namespace android {
@@ -570,11 +571,15 @@
response->postReply(replyID);
}
+static CodecBase *CreateCCodec() {
+ return StagefrightPluginLoader::GetCCodecInstance()->createCodec();
+}
+
//static
sp<CodecBase> MediaCodec::GetCodecBase(const AString &name) {
static bool ccodecEnabled = property_get_bool("debug.stagefright.ccodec", false);
if (ccodecEnabled && name.startsWithIgnoreCase("c2.")) {
- return new CCodec;
+ return CreateCCodec();
} else if (name.startsWithIgnoreCase("omx.")) {
// at this time only ACodec specifies a mime type.
return new ACodec;
diff --git a/media/libstagefright/MediaCodecList.cpp b/media/libstagefright/MediaCodecList.cpp
index 9244886..cd091a6 100644
--- a/media/libstagefright/MediaCodecList.cpp
+++ b/media/libstagefright/MediaCodecList.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include "MediaCodecListOverrides.h"
+#include "StagefrightPluginLoader.h"
#include <binder/IServiceManager.h>
@@ -29,7 +30,6 @@
#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>
@@ -78,14 +78,25 @@
}
OmxInfoBuilder sOmxInfoBuilder;
-Codec2InfoBuilder sCodec2InfoBuilder;
-std::initializer_list<MediaCodecListBuilderBase *> GetBuilders() {
- if (property_get_bool("debug.stagefright.ccodec", false)) {
- return {&sOmxInfoBuilder, &sCodec2InfoBuilder};
- } else {
- return {&sOmxInfoBuilder};
+Mutex sCodec2InfoBuilderMutex;
+std::unique_ptr<MediaCodecListBuilderBase> sCodec2InfoBuilder;
+
+MediaCodecListBuilderBase *GetCodec2InfoBuilder() {
+ Mutex::Autolock _l(sCodec2InfoBuilderMutex);
+ if (!sCodec2InfoBuilder) {
+ sCodec2InfoBuilder.reset(
+ StagefrightPluginLoader::GetCCodecInstance()->createBuilder());
}
+ return sCodec2InfoBuilder.get();
+}
+
+std::vector<MediaCodecListBuilderBase *> GetBuilders() {
+ std::vector<MediaCodecListBuilderBase *> builders {&sOmxInfoBuilder};
+ if (property_get_bool("debug.stagefright.ccodec", false)) {
+ builders.push_back(GetCodec2InfoBuilder());
+ }
+ return builders;
}
} // unnamed namespace
@@ -179,16 +190,22 @@
return sRemoteList;
}
-MediaCodecList::MediaCodecList(std::initializer_list<MediaCodecListBuilderBase*> builders) {
+MediaCodecList::MediaCodecList(std::vector<MediaCodecListBuilderBase*> builders) {
mGlobalSettings = new AMessage();
mCodecInfos.clear();
- MediaCodecListWriter writer(this);
+ MediaCodecListWriter writer;
for (MediaCodecListBuilderBase *builder : builders) {
+ if (builder == nullptr) {
+ ALOGD("ignored a null builder");
+ continue;
+ }
mInitCheck = builder->buildMediaCodecList(&writer);
if (mInitCheck != OK) {
break;
}
}
+ writer.writeGlobalSettings(mGlobalSettings);
+ writer.writeCodecInfos(&mCodecInfos);
std::stable_sort(
mCodecInfos.begin(),
mCodecInfos.end(),
@@ -210,23 +227,6 @@
return mInitCheck;
}
-MediaCodecListWriter::MediaCodecListWriter(MediaCodecList* list) :
- mList(list) {
-}
-
-void MediaCodecListWriter::addGlobalSetting(
- const char* key, const char* value) {
- mList->mGlobalSettings->setString(key, value);
-}
-
-std::unique_ptr<MediaCodecInfoWriter>
- MediaCodecListWriter::addMediaCodecInfo() {
- sp<MediaCodecInfo> info = new MediaCodecInfo();
- mList->mCodecInfos.push_back(info);
- return std::unique_ptr<MediaCodecInfoWriter>(
- new MediaCodecInfoWriter(info.get()));
-}
-
// legacy method for non-advanced codecs
ssize_t MediaCodecList::findCodecByType(
const char *type, bool encoder, size_t startIndex) const {
@@ -344,7 +344,4 @@
}
}
-MediaCodecListBuilderBase::~MediaCodecListBuilderBase() {
-}
-
} // namespace android
diff --git a/media/libstagefright/MediaCodecListWriter.cpp b/media/libstagefright/MediaCodecListWriter.cpp
new file mode 100644
index 0000000..b32e470
--- /dev/null
+++ b/media/libstagefright/MediaCodecListWriter.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MediaCodecListWriter"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaCodecListWriter.h>
+#include <media/MediaCodecInfo.h>
+
+namespace android {
+
+void MediaCodecListWriter::addGlobalSetting(
+ const char* key, const char* value) {
+ mGlobalSettings.emplace_back(key, value);
+}
+
+std::unique_ptr<MediaCodecInfoWriter>
+ MediaCodecListWriter::addMediaCodecInfo() {
+ sp<MediaCodecInfo> info = new MediaCodecInfo();
+ mCodecInfos.push_back(info);
+ return std::unique_ptr<MediaCodecInfoWriter>(
+ new MediaCodecInfoWriter(info.get()));
+}
+
+void MediaCodecListWriter::writeGlobalSettings(
+ const sp<AMessage> &globalSettings) const {
+ for (const std::pair<std::string, std::string> &kv : mGlobalSettings) {
+ globalSettings->setString(kv.first.c_str(), kv.second.c_str());
+ }
+}
+
+void MediaCodecListWriter::writeCodecInfos(
+ std::vector<sp<MediaCodecInfo>> *codecInfos) const {
+ for (const sp<MediaCodecInfo> &info : mCodecInfos) {
+ codecInfos->push_back(info);
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/StagefrightPluginLoader.cpp b/media/libstagefright/StagefrightPluginLoader.cpp
new file mode 100644
index 0000000..7f13f87
--- /dev/null
+++ b/media/libstagefright/StagefrightPluginLoader.cpp
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "StagefrightPluginLoader"
+#include <utils/Log.h>
+
+#include <dlfcn.h>
+
+#include "StagefrightPluginLoader.h"
+
+namespace android {
+
+/* static */ Mutex StagefrightPluginLoader::sMutex;
+/* static */ std::unique_ptr<StagefrightPluginLoader> StagefrightPluginLoader::sInstance;
+
+StagefrightPluginLoader::StagefrightPluginLoader(const char *libPath)
+ : mCreateCodec(nullptr),
+ mCreateBuilder(nullptr) {
+ mLibHandle = dlopen(libPath, RTLD_NOW | RTLD_NODELETE);
+ if (mLibHandle == nullptr) {
+ ALOGD("Failed to load library: %s (%s)", libPath, dlerror());
+ return;
+ }
+ mCreateCodec = (CodecBase::CreateCodecFunc)dlsym(mLibHandle, "CreateCodec");
+ if (mCreateCodec == nullptr) {
+ ALOGD("Failed to find symbol: CreateCodec (%s)", dlerror());
+ }
+ mCreateBuilder = (MediaCodecListBuilderBase::CreateBuilderFunc)dlsym(
+ mLibHandle, "CreateBuilder");
+ if (mCreateBuilder == nullptr) {
+ ALOGD("Failed to find symbol: CreateBuilder (%s)", dlerror());
+ }
+}
+
+StagefrightPluginLoader::~StagefrightPluginLoader() {
+ if (mLibHandle != nullptr) {
+ ALOGV("Closing handle");
+ dlclose(mLibHandle);
+ }
+}
+
+CodecBase *StagefrightPluginLoader::createCodec() {
+ if (mLibHandle == nullptr || mCreateCodec == nullptr) {
+ ALOGD("Handle or CreateCodec symbol is null");
+ return nullptr;
+ }
+ return mCreateCodec();
+}
+
+MediaCodecListBuilderBase *StagefrightPluginLoader::createBuilder() {
+ if (mLibHandle == nullptr || mCreateBuilder == nullptr) {
+ ALOGD("Handle or CreateBuilder symbol is null");
+ return nullptr;
+ }
+ return mCreateBuilder();
+}
+
+//static
+const std::unique_ptr<StagefrightPluginLoader> &StagefrightPluginLoader::GetCCodecInstance() {
+ Mutex::Autolock _l(sMutex);
+ if (!sInstance) {
+ ALOGV("Loading library");
+ sInstance.reset(new StagefrightPluginLoader("libstagefright_ccodec.so"));
+ }
+ return sInstance;
+}
+
+} // namespace android
diff --git a/media/libstagefright/StagefrightPluginLoader.h b/media/libstagefright/StagefrightPluginLoader.h
new file mode 100644
index 0000000..2746756
--- /dev/null
+++ b/media/libstagefright/StagefrightPluginLoader.h
@@ -0,0 +1,47 @@
+/*
+ * 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 STAGEFRIGHT_PLUGIN_LOADER_H_
+
+#define STAGEFRIGHT_PLUGIN_LOADER_H_
+
+#include <media/stagefright/CodecBase.h>
+#include <media/stagefright/MediaCodecListWriter.h>
+#include <utils/Mutex.h>
+
+namespace android {
+
+class StagefrightPluginLoader {
+public:
+ static const std::unique_ptr<StagefrightPluginLoader> &GetCCodecInstance();
+ ~StagefrightPluginLoader();
+
+ CodecBase *createCodec();
+ MediaCodecListBuilderBase *createBuilder();
+private:
+ explicit StagefrightPluginLoader(const char *libPath);
+
+ static Mutex sMutex;
+ static std::unique_ptr<StagefrightPluginLoader> sInstance;
+
+ void *mLibHandle;
+ CodecBase::CreateCodecFunc mCreateCodec;
+ MediaCodecListBuilderBase::CreateBuilderFunc mCreateBuilder;
+};
+
+} // namespace android
+
+#endif // STAGEFRIGHT_PLUGIN_LOADER_H_
diff --git a/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h b/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h
index ea0b5c4..30c189e 100644
--- a/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h
+++ b/media/libstagefright/include/media/stagefright/Codec2InfoBuilder.h
@@ -25,6 +25,7 @@
class Codec2InfoBuilder : public MediaCodecListBuilderBase {
public:
Codec2InfoBuilder() = default;
+ ~Codec2InfoBuilder() override = default;
status_t buildMediaCodecList(MediaCodecListWriter* writer) override;
};
diff --git a/media/libstagefright/include/media/stagefright/CodecBase.h b/media/libstagefright/include/media/stagefright/CodecBase.h
index 268662f..1cbf865 100644
--- a/media/libstagefright/include/media/stagefright/CodecBase.h
+++ b/media/libstagefright/include/media/stagefright/CodecBase.h
@@ -222,9 +222,7 @@
virtual void signalSetParameters(const sp<AMessage> &msg) = 0;
virtual void signalEndOfInputStream() = 0;
- /*
- * Codec-related defines
- */
+ typedef CodecBase *(*CreateCodecFunc)(void);
protected:
CodecBase() = default;
@@ -324,4 +322,3 @@
} // namespace android
#endif // CODEC_BASE_H_
-
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecList.h b/media/libstagefright/include/media/stagefright/MediaCodecList.h
index bb4da09..e44b0a4 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodecList.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodecList.h
@@ -18,10 +18,11 @@
#define MEDIA_CODEC_LIST_H_
-#include <initializer_list>
+#include <vector>
#include <media/stagefright/foundation/ABase.h>
#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/MediaCodecListWriter.h>
#include <media/IMediaCodecList.h>
#include <media/MediaCodecInfo.h>
@@ -37,8 +38,6 @@
struct AMessage;
-struct MediaCodecListBuilderBase;
-
struct MediaCodecList : public BnMediaCodecList {
static sp<IMediaCodecList> getInstance();
@@ -97,7 +96,7 @@
* This constructor will call `buildMediaCodecList()` from the given
* `MediaCodecListBuilderBase` objects.
*/
- MediaCodecList(std::initializer_list<MediaCodecListBuilderBase*> builders);
+ MediaCodecList(std::vector<MediaCodecListBuilderBase*> builders);
~MediaCodecList();
@@ -105,66 +104,6 @@
MediaCodecList(const MediaCodecList&) = delete;
MediaCodecList& operator=(const MediaCodecList&) = delete;
-
- friend MediaCodecListWriter;
-};
-
-/**
- * This class is to be used by a `MediaCodecListBuilderBase` instance to add
- * information to the associated `MediaCodecList` object.
- */
-struct MediaCodecListWriter {
- /**
- * Add a key-value pair to a `MediaCodecList`'s global settings.
- *
- * @param key Key.
- * @param value Value.
- */
- void addGlobalSetting(const char* key, const char* value);
- /**
- * Create an add a new `MediaCodecInfo` object to a `MediaCodecList`, and
- * return a `MediaCodecInfoWriter` object associated with the newly added
- * `MediaCodecInfo`.
- *
- * @return The `MediaCodecInfoWriter` object associated with the newly
- * added `MediaCodecInfo` object.
- */
- std::unique_ptr<MediaCodecInfoWriter> addMediaCodecInfo();
-private:
- /**
- * The associated `MediaCodecList` object.
- */
- MediaCodecList* mList;
-
- /**
- * Construct this writer object associated with the given `MediaCodecList`
- * object.
- *
- * @param list The "base" `MediaCodecList` object.
- */
- MediaCodecListWriter(MediaCodecList* list);
-
- friend MediaCodecList;
-};
-
-/**
- * This interface is to be used by `MediaCodecList` to fill its members with
- * appropriate information. `buildMediaCodecList()` will be called from a
- * `MediaCodecList` object during its construction.
- */
-struct MediaCodecListBuilderBase {
- /**
- * Build the `MediaCodecList` via the given `MediaCodecListWriter` interface.
- *
- * @param writer The writer interface.
- * @return The status of the construction. `NO_ERROR` means success.
- */
- virtual status_t buildMediaCodecList(MediaCodecListWriter* writer) = 0;
-
- /**
- * The default destructor does nothing.
- */
- virtual ~MediaCodecListBuilderBase();
};
} // namespace android
diff --git a/media/libstagefright/include/media/stagefright/MediaCodecListWriter.h b/media/libstagefright/include/media/stagefright/MediaCodecListWriter.h
new file mode 100644
index 0000000..59f57c7
--- /dev/null
+++ b/media/libstagefright/include/media/stagefright/MediaCodecListWriter.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEDIA_CODEC_LIST_WRITER_H_
+
+#define MEDIA_CODEC_LIST_WRITER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaCodecListWriter.h>
+#include <media/MediaCodecInfo.h>
+
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+/**
+ * This class is to be used by a `MediaCodecListBuilderBase` instance to add
+ * information to the destination `MediaCodecList` object.
+ */
+struct MediaCodecListWriter {
+ /**
+ * Add a key-value pair to a `MediaCodecList`'s global settings.
+ *
+ * @param key Key.
+ * @param value Value.
+ */
+ void addGlobalSetting(const char* key, const char* value);
+ /**
+ * Create an add a new `MediaCodecInfo` object for a `MediaCodecList`, and
+ * return a `MediaCodecInfoWriter` object associated with the newly added
+ * `MediaCodecInfo`.
+ *
+ * @return The `MediaCodecInfoWriter` object associated with the newly
+ * added `MediaCodecInfo` object.
+ */
+ std::unique_ptr<MediaCodecInfoWriter> addMediaCodecInfo();
+private:
+ MediaCodecListWriter() = default;
+
+ void writeGlobalSettings(const sp<AMessage> &globalSettings) const;
+ void writeCodecInfos(std::vector<sp<MediaCodecInfo>> *codecInfos) const;
+
+ std::vector<std::pair<std::string, std::string>> mGlobalSettings;
+ std::vector<sp<MediaCodecInfo>> mCodecInfos;
+
+ friend struct MediaCodecList;
+};
+
+/**
+ * This interface is to be used by `MediaCodecList` to fill its members with
+ * appropriate information. `buildMediaCodecList()` will be called from a
+ * `MediaCodecList` object during its construction.
+ */
+struct MediaCodecListBuilderBase {
+ /**
+ * Build the `MediaCodecList` via the given `MediaCodecListWriter` interface.
+ *
+ * @param writer The writer interface.
+ * @return The status of the construction. `NO_ERROR` means success.
+ */
+ virtual status_t buildMediaCodecList(MediaCodecListWriter* writer) = 0;
+
+ /**
+ * The default destructor does nothing.
+ */
+ virtual ~MediaCodecListBuilderBase() = default;
+
+ typedef MediaCodecListBuilderBase *(*CreateBuilderFunc)(void);
+};
+
+} // namespace android
+
+#endif // MEDIA_CODEC_LIST_WRITER_H_
+
diff --git a/media/libstagefright/include/media/stagefright/OmxInfoBuilder.h b/media/libstagefright/include/media/stagefright/OmxInfoBuilder.h
index 1b4d873..28f6094 100644
--- a/media/libstagefright/include/media/stagefright/OmxInfoBuilder.h
+++ b/media/libstagefright/include/media/stagefright/OmxInfoBuilder.h
@@ -25,6 +25,7 @@
class OmxInfoBuilder : public MediaCodecListBuilderBase {
public:
OmxInfoBuilder();
+ ~OmxInfoBuilder() override = default;
status_t buildMediaCodecList(MediaCodecListWriter* writer) override;
};