gpt4 book ai didi

android - 如何使用 MediaBufferGroup 类适配 android 4.x 和 5.0

转载 作者:太空宇宙 更新时间:2023-11-04 13:41:46 42 4
gpt4 key购买 nike

我的 libxx.so 使用了 MediaBufferGroup 类,在 android 4.2 环境下编译和链接,在 android 4.x 上运行正常,但在 android 5.0 上运行失败。

logcat: dlopen("/data/app/org.cocos2dx.simplegame-1/lib/arm/libxx.so", RTLD_LAZY) failed: dlopen failed: cannot locate symbol "_ZN7android16MediaBufferGroup14acquire_bufferEPPNS_11MediaBufferE"由“libxx.so”引用...

原因是 4.x 和 5.0 之间的 acquire_buffer 声明差异。安卓 4.x status_t acquire_buffer(MediaBuffer **缓冲区); http://androidxref.com/4.2_r1/xref/frameworks/av/include/media/stagefright/MediaBufferGroup.h安卓5.0status_t acquire_buffer(MediaBuffer **buffer, bool nonBlocking = false); http://androidxref.com/5.0.0_r2/xref/frameworks/av/include/media/stagefright/MediaBufferGroup.h

我不想构建两个 libxx.so,一个用于 4.x,另一个用于 5.0。问题是如何构建 libxx.so 以适配 4.x 和 5.0?谢谢!

更新:将源 MediaBufferGroup.h 和 MediaBufferGroup.cpp (4.2_r1) 添加到我的 libxx.so Android.mk。在 4.x 和 5.x 上运行正常。

最佳答案

解决此问题的一种方法是构建两个版本的 libxx.so,一个用于 4.x,另一个用于 5.0,但将尽可能多的功能分离到另一个不链接原生 Android 的 .so 文件中像 MediaBufferGroup 这样的类,并且可以链接到两个版本。但是,这需要重新构建您的库,并且也没有回答问题。

另一种避免构建两个版本的 libxx.so 的方法是为 MediaBufferGroup 创建一个包装类并将其编译为两个小的 .so 文件(一个用于 4.x,另一个用于 5.0)并在运行时将 libxx.so 与正确的版本链接起来,从而避免在 libxx.so 和 MediaBufferGroup 之间直接建立任何链接。

MediaBufferGroupWrapper.h:

#ifndef MEDIA_BUFFER_GROUP_WRAPPER_H_

#define MEDIA_BUFFER_GROUP_WRAPPER_H_

#include <media/stagefright/MediaBufferGroup.h>
#include <utils/Errors.h>

namespace android {

class MediaBufferGroupWrapper : public MediaBufferGroup {
public:
MediaBufferGroupWrapper() {}
~MediaBufferGroupWrapper() {}

status_t acquire_buffer(MediaBuffer **buffer);
};

}

#endif // MEDIA_BUFFER_GROUP_WRAPPER_H_

MediaBufferGroupWrapper.cpp:

#include "MediaBufferGroupWrapper.h"

namespace android
{

status_t MediaBufferGroupWrapper::acquire_buffer(MediaBuffer **buffer)
{
return MediaBufferGroup::acquire_buffer(buffer);
}

}

MediaBufferGroup 包装器库 (4.x) 的 Android.mk 文件:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := libmediabuffergroupwrapper
LOCAL_SRC_FILES := MediaBufferGroupWrapper.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../AndroidSource/JB4_2/system/core/include
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../AndroidSource/JB4_2/frameworks/av/include
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../AndroidSource/JB4_2/frameworks/native/include
LOCAL_LDFLAGS += $(LOCAL_PATH)/../../AndroidLibs/JB4_2/system/lib/libstagefright.so
include $(BUILD_SHARED_LIBRARY)

(更改 AndroidSource/JB4_2AndroidLibs/JB4_2 路径以指向您拥有 Jellybean 源代码和 Jellybean 库的位置)

MediaBufferGroup 包装器库 (5.0) 的 Android.mk 文件:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := libmediabuffergroupwrapper
LOCAL_SRC_FILES := MediaBufferGroupWrapper.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../AndroidSource/L/system/core/include
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../AndroidSource/L/frameworks/av/include
LOCAL_LDFLAGS += $(LOCAL_PATH)/../../AndroidLibs/L/system/lib/libstagefright.so
include $(BUILD_SHARED_LIBRARY)

然后更改 libxx.so 的代码以直接使用包装器而不是 MediaBufferGroup:

// #include <media/stagefright/MediaBufferGroup.h>
#include "MediaBufferGroupWrapper.h"

// MediaBufferGroup mGroup;
MediaBufferGroupWrapper mGroup;

等并链接到 libxx.so 的 make 文件中的包装器。在顶部添加:

include $(CLEAR_VARS)
LOCAL_MODULE := mediabuffergroupwrapper
LOCAL_SRC_FILES := $(LOCAL_PATH)/libmediabuffergroupwrapper.so
include $(PREBUILT_SHARED_LIBRARY)

然后在构建 libxx 时:

LOCAL_SHARED_LIBRARIES += mediabuffergroupwrapper

如果您要继续与 Jellybean 库链接,请使用包装器的 Jellybean 版本。您可以继续与 libstagefright.so 的 Jellybean 版本链接,只要您不直接使用任何已更改的类(如 MediaBufferGroup),它就不会导致运行时链接错误。

现在您只需在运行时链接到正确的包装器。不幸的是,似乎不可能只将两个 .so 文件放入库中,然后使用 System.loadLibrary("mediabuffergroupwrapper_lollipop")System.load("lollipop/libmediabuffergroupwrapper.so") 等等。我能够让它工作的唯一方法是将两个包装器 .so 文件保存在我项目的原始文件夹中,分别为 libmediabuffergroupwrapper_jellybean.solibmediabuffergroupwrapper_lollipop.so 和然后将正确的复制到应用程序的数据文件夹,然后从那里加载它,如下所示:

String wrapperLibPath = getFilesDir().getAbsolutePath() + "/libmediabuffergroupwrapper.so";
File wrapperLibPathFile = new File(wrapperLibPath);
if(!wrapperLibPathFile.exists())
{
// copy the correct file from the raw folder to the path:
InputStream is = getResources().openRawResource((android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) ?
R.raw.libmediabuffergroupwrapper_lollipop : R.raw.libmediabuffergroupwrapper_jellybean);
try {
fileCopy(is, wrapperLibPathFile);
} catch (IOException e) {
e.printStackTrace();
}
}
System.load(wrapperLibPath);
System.loadLibrary("xx"); // load libxx.so, linking with the wrapper

filecopy 只是像这样复制文件:

public void fileCopy(InputStream in, File dst) throws IOException {
OutputStream out = new FileOutputStream(dst);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}

我已经在运行 5.0.2 的 Nexus7、运行 5.0 的 Nexus 5 和运行 4.4.2 的 Optimus G Pro 上对此进行了测试,它可以正常工作。这并不是真的安全,但如果您已经链接到可以在您脚下改变的私有(private) API,那么问题似乎已经暗示了接受该风险。

Jellybean 和 Lollipop 版本的两个包装 .so 文件分别编译为 21.7 Kb 和 17.6 Kb。

关于android - 如何使用 MediaBufferGroup 类适配 android 4.x 和 5.0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27436475/

42 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com