qbasicbirthday 发表于 2020-7-16 12:11:46

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;
}

qbasicbirthday 发表于 2020-7-16 12:17:26

如果 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]
查看完整版本: RK3288 MediaCodec ndk 下解码错误 求助