Resuelva el problema de la pantalla negra al decodificar video H264

No hay ningún vídeo de error en la capa inferior de Android, pero la pantalla está en negro y no se puede decodificar.
Simplemente asegúrese de que la operación de decodificación se realice cuando haya un cuadro I.

   boolean hasI = false;
   try {
    
    
            int i = msg[4] & 0x1f;
            if (i == 7) {
    
    
                Log.d(TAG, "dataBack: 收到I帧");
                hasI = true;
                 }
           
          
            if (hasI) {
    
    
                //解码
                mediaCodecUtil.onFrame(msg, 0, msg.length);
            }

        } catch (Exception e) {
    
    


        }

Herramientas utilizadas para decodificar.

import android.media.MediaCodec;
import android.media.MediaFormat;
import android.util.Log;
import android.view.SurfaceHolder;

import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * Created by sy012 on 18-4-30.
 * 用于硬件解码(MediaCodec)H264的工具
 */

public class MediaCodecUtil {
    
    
    //解码后显示的surface及其宽高
    private SurfaceHolder holder;
    private int width, height;
    //解码器
    private MediaCodec mCodec;
    private boolean isFirst = true;
    // 需要解码的类型
    private final static String MIME_TYPE = "video/avc"; // H.264 Advanced Video

    /**
     * 初始化解码器
     *
     * @param holder 用于显示视频的surface
     * @param width  surface宽
     * @param height surface高
     */
    public MediaCodecUtil(SurfaceHolder holder, int width, int height) {
    
    
        this.holder = holder;
        this.width = width;
        this.height = height;
    }

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

    public boolean onFrame(byte[] buf, int offset, int length) {
    
    
        if (mCodec == null) {
    
    
            return false;
        }

        try {
    
    

            // 获取输入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, 0, 0);

            } else {
    
    
                com.orhanobut.logger.Logger.w("onFrame");
                return false;
            }
            // 获取输出buffer index
            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
            int outputBufferIndex = mCodec.dequeueOutputBuffer(bufferInfo, 100);
//        Logger.w(outputBufferIndex+"");
            //循环解码,直到数据全部解码完成
            while (outputBufferIndex >= 0) {
    
    
                //true : 将解码的数据显示到surface上
                mCodec.releaseOutputBuffer(outputBufferIndex, true);
                outputBufferIndex = mCodec.dequeueOutputBuffer(bufferInfo, 0);
            }

        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 停止解码,释放解码器
     */
    public void stopCodec() {
    
    
        try {
    
    
            if (mCodec != null) {
    
    
                mCodec.stop();
                mCodec.release();
                mCodec = null;
            }
            isFirst = true;
        } catch (Exception e) {
    
    
            e.printStackTrace();
            mCodec = null;
        }
    }

おすすめ

転載: blog.csdn.net/qq910689331/article/details/108513016
おすすめ