使用 CMakeLists.txt 编译 SO 提供给第三方调用(1)

    技术2026-04-01  8

    创建 c++ 项目,

    将 mainactive 调用 c++ 部分的 java 代码全部去掉,这个只要用来 编译 so 文件

    将  native-lib.cpp 删掉

    新增一个 使用 mediacodec 进行解码 h264 的类的头文件

    #ifndef TESTADD_DECODEOP_H #define TESTADD_DECODEOP_H class AMediaCodec; class DecodeOp { private: int mWidth; int mHeight; int mOriFrameSize; int mFrameSize; AMediaCodec *mMediaCodec; public: int init(int width, int height); int fini(); int decode(char *bufData, int bufSize, char *outBuf); }; #endif //TESTADD_DECODEOP_H

    新增一个 cpp文件 DecodeOp.cpp

    不明白代码 mOriFrameSize = width * height * 3 / 2;   这个应该是 Y 分量 应该是 /3 才对啊 

    #include "DecodeOp.h" #include <media/NdkMediaCodec.h> //#include "CommonOp.h" #include <stdlib.h> #include <stdio.h> #include <string.h> #define MIN(_a,_b) ((_a) > (_b) ? (_b) : (_a)) int DecodeOp::init(int width, int height) { const char *mine = "video/avc"; mMediaCodec = AMediaCodec_createDecoderByType(mine); //注意这里,如果系统不存在对应的mine,mMediaCodec也会返回对象, //不过之后涉及到mMediaCodec的任何函数都会直接导致程序崩掉。 if (NULL == mMediaCodec) { return 0; } AMediaFormat *videoFormat = AMediaFormat_new(); AMediaFormat_setString(videoFormat, "mime", "video/avc"); AMediaFormat_setInt32(videoFormat, AMEDIAFORMAT_KEY_WIDTH, width); AMediaFormat_setInt32(videoFormat, AMEDIAFORMAT_KEY_HEIGHT, height); media_status_t status = AMediaCodec_configure(mMediaCodec, videoFormat, NULL, NULL, 0); if (status != AMEDIA_OK) { AMediaCodec_delete(mMediaCodec); mMediaCodec = NULL; return 0; } mWidth = width; mHeight = height; mOriFrameSize = width * height * 3 / 2; mFrameSize = mOriFrameSize; status = AMediaCodec_start(mMediaCodec); if (status != AMEDIA_OK) { AMediaCodec_delete(mMediaCodec); mMediaCodec = NULL; return 0; } return 1; } int DecodeOp::fini() { AMediaCodec_stop(mMediaCodec); AMediaCodec_delete(mMediaCodec); mMediaCodec = NULL; return 1; } int DecodeOp::decode(char *bufData, int bufSize, char *outBuf) { if (NULL == mMediaCodec) return 0; ssize_t bufidx = AMediaCodec_dequeueInputBuffer(mMediaCodec, 2000); if (bufidx >= 0) { // 获取buffer的索引 size_t outsize; uint8_t *inputBuf = AMediaCodec_getInputBuffer(mMediaCodec, bufidx, &outsize); if (inputBuf != nullptr && bufSize <= outsize) { // 将待解码的数据copy到硬件中 memcpy(inputBuf, bufData, bufSize); media_status_t status = AMediaCodec_queueInputBuffer(mMediaCodec, bufidx, 0, bufSize, 2000 /* pts */, 0); } } AMediaCodecBufferInfo info; ssize_t outbufidx = AMediaCodec_dequeueOutputBuffer(mMediaCodec, &info, 2000); if (outbufidx >= 0) { size_t outsize; uint8_t *outputBuf = AMediaCodec_getOutputBuffer(mMediaCodec, outbufidx, &outsize); if (outputBuf != nullptr) { //pts = info.presentationTimeUs; //int32_t pts32 = (int32_t) pts; uint8_t *dst = (uint8_t *) outBuf; memcpy(dst, outputBuf, MIN(mOriFrameSize, mFrameSize)); uint8_t *uvBuf = outputBuf + mFrameSize; uint32_t uvSize = MIN(mOriFrameSize >> 1, mFrameSize >> 1); uint8_t *uBuf = dst + mOriFrameSize; uint8_t *vBuf = uBuf + (mOriFrameSize >> 2); memcpy(uBuf, uvBuf, uvSize); AMediaCodec_releaseOutputBuffer(mMediaCodec, outbufidx, info.size != 0); return 1; } } else { switch (outbufidx) { case AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED: // 解码输出的格式发生变化 { auto format = AMediaCodec_getOutputFormat(mMediaCodec); AMediaFormat_getInt32(format, "width", &mWidth); AMediaFormat_getInt32(format, "height", &mHeight); int32_t localColorFMT; AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_COLOR_FORMAT, &localColorFMT); /* mColorFormat = getTTFormatFromMC(localColorFMT); int32_t stride = 0; AMediaFormat_getInt32(format, "stride", &stride); if(stride == 0) { stride = mWidth; } mLineSize[0] = stride; mFrameSize = stride * mHeight; mOriFrameSize = stride * mOriHeight; */ return 0; } case AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED: break; default: break; } } return 1; }

    修改 CMakeList.txt 

    修改了 源文件由 native-lib.cpp 改为  DecodeOp.cpp

    修改了输出 库的名称 由 native-lib 改为 MediaH264

    增加了 调用 库  mediandk 应该= gcc 里面 的 -lmediandk

    # For more information about using CMake with Android Studio, read the # documentation: https://d.android.com/studio/projects/add-native-code.html # Sets the minimum version of CMake required to build the native library. cmake_minimum_required(VERSION 3.4.1) # Creates and names a library, sets it as either STATIC # or SHARED, and provides the relative paths to its source code. # You can define multiple libraries, and CMake builds them for you. # Gradle automatically packages shared libraries with your APK. add_library( # Sets the name of the library. - native-lib + MediaH264 # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). - native-lib.cpp + DecodeOp.cpp) # Searches for a specified prebuilt library and stores the path as a # variable. Because CMake includes system libraries in the search path by # default, you only need to specify the name of the public NDK library # you want to add. CMake verifies that the library exists before # completing its build. find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log) #find_library( # Sets the name of the path variable. # mediandk-lib # # # Specifies the name of the NDK library that # # you want CMake to locate. # mediandk) # Specifies libraries CMake should link to your target library. You # can link multiple libraries, such as libraries you define in this # build script, prebuilt third-party libraries, or system libraries. target_link_libraries( # Specifies the target library. MediaH264 # Links the target library to the log library # included in the NDK. ${log-lib} +  mediandk)

    顺利编译通过,下次试试在 通过库 调用这个 库

    参考说明:

    https://blog.csdn.net/hukou6335490/article/details/83687419

    http://euhat.com/wp/2018/09/26/android-jni%E5%9F%BA%E4%BA%8Endkmediacodec%E7%A1%AC%E8%A7%A3%E7%A0%81mjpeg/

    Processed: 0.013, SQL: 9