RK3288 MediaCodec ndk 下解码错误 求助
解码H264 代码如下AMediaCodec_queueInputBuffer 先是正确返回>=0一两分钟后
后面就是返回-1,一直解码不成功
#include "DecodeOp.h"
#include <media/NdkMediaCodec.h>
//#include "CommonOp.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <android/log.h>
#include <pthread.h>
#define LOG_TAG"C_MDA"
#define LOGD(...)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#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;
mFramecnt=0;
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,pthread_mutex_t *mutex) {
if (NULL == mMediaCodec)
return 0;
ssize_t bufidx = AMediaCodec_dequeueInputBuffer(mMediaCodec, 10000); //-1);
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,5*mFramecnt++ /* pts */, 0);
}
//LOGD("ie:%lld",mFramecnt);
}else
{
LOGD("ib:%d",bufidx);
AMediaCodec_flush(mMediaCodec);
AMediaCodec_start(mMediaCodec);
}
int ret=0;
AMediaCodecBufferInfo info;
ssize_t outbufidx = AMediaCodec_dequeueOutputBuffer(mMediaCodec, &info, 0);
//LOGD("ob:%d",outbufidx);
if (outbufidx >= 0) {
size_t outsize;
uint8_t *outputBuf = AMediaCodec_getOutputBuffer(mMediaCodec, outbufidx, &outsize);
LOGD("obs:%d",outsize);
if (outputBuf != nullptr) {
ret= 1;
}
AMediaCodec_releaseOutputBuffer(mMediaCodec, outbufidx, false);
} 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);
}
case AMEDIACODEC_INFO_OUTPUT_BUFFERS_CHANGED:
break;
default:
break;
}
}
return ret;
} 如果 java 模式下 调用 mediacodec 就能一直解码成功
java 调用 mediacodec 解码的代码如下
/**
* Created by ZhangHao on 2016/8/5.
* 用于硬件解码(MediaCodec)H264的工具类
*/
public class MediaCodecUtil {
//自定义的log打印,可以无视
//Logger logger = Logger.getLogger();
private String TAG = "MediaCodecUtil";
//解码后显示的surface及其宽高
private SurfaceHolder holder;
private int width, height;
//解码器
private MediaCodec mCodec;
private MediaFormat mFormat;
private boolean isFirst = true;
// 需要解码的类型
private final static String MIME_TYPE = "video/avc"; // H.264 Advanced Video
private final static int TIME_INTERNAL = 5;
/**
* 初始化解码器
*
* @param holder 用于显示视频的surface
* @param widthsurface宽
* @param height surface高
*/
public MediaCodecUtil(SurfaceHolder holder, int width, int height) {
// logger.d("MediaCodecUtil() called with: " + "holder = [" + holder + "], " +
// "width = [" + width + "], height = [" + height + "]");
this.holder = holder;
this.width = width;
this.height = height;
//mFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
}
public MediaCodecUtil(SurfaceHolder holder) {
this(holder, holder.getSurfaceFrame().width(), holder.getSurfaceFrame().height());
}
public void startCodec() {
if (isFirst) {
//第一次打开则初始化解码器
initDecoder();
}
}
private void initDecoder() {
try {
//根据需要解码的类型创建解码器
mCodec = MediaCodec.createDecoderByType(MIME_TYPE);
} catch (IOException e) {
e.printStackTrace();
}
//初始化MediaFormat
MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE,
width, height);
//配置MediaFormat以及需要显示的surface
mCodec.configure(mediaFormat, holder.getSurface(), null, 0);
//开始解码
mCodec.start();
isFirst = false;
}
int mCount = 0;
public boolean onFrame(byte[] buf, int offset, int length) {
// 获取输入buffer index
ByteBuffer[] inputBuffers = mCodec.getInputBuffers();
//-1表示一直等待;0表示不等待;其他大于0的参数表示等待毫秒数
int inputBufferIndex = mCodec.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers;
//清空buffer
inputBuffer.clear();
//put需要解码的数据
inputBuffer.put(buf, offset, length);
//解码
mCodec.queueInputBuffer(inputBufferIndex, 0, length, mCount * TIME_INTERNAL, 0);
mCount++;
} else {
return false;
}
//mCodec.flush();
// 获取输出buffer index
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex;
do{
outputBufferIndex = mCodec.dequeueOutputBuffer(bufferInfo, 0);
if(outputBufferIndex<0) break;
mCodec.releaseOutputBuffer(outputBufferIndex, true);
}while(true);
if (outputBufferIndex < 0) {
//logger.e("outputBufferIndex = " + outputBufferIndex);
}
return true;
}
/**
*停止解码,释放解码器
*/
public void stopCodec() {
try {
mCodec.stop();
mCodec.release();
mCodec = null;
isFirst = true;
} catch (Exception e) {
e.printStackTrace();
mCodec = null;
}
}
}
页:
[1]