创建 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)
顺利编译通过,下次试试在 通过库 调用这个 库
参考说明: