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