Firefly开源社区

打印 上一主题 下一主题

[Android] RK3288 MediaCodec ndk 下解码错误 求助

94

积分

0

威望

0

贡献

技术小白

积分
94

RK3288 MediaCodec ndk 下解码错误 求助

发表于 2020-7-16 12:11:46      浏览:3559 | 回复:1        打印      只看该作者   [复制链接] 楼主
解码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;
}
回复

使用道具 举报

94

积分

0

威望

0

贡献

技术小白

积分
94
发表于 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 width  surface宽
     * @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[inputBufferIndex];
            //清空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;
        }
    }
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

友情链接 : 爱板网 电子发烧友论坛 云汉电子社区 粤ICP备14022046号-2
快速回复 返回顶部 返回列表