我正在学习如何最近使用mediacodec,它似乎有一些问题。我写了一个演示,从相机预览中获取数据,将其编码为h264并将h264解码到surfaceview上,但看起来corlor是错误的,就像这样:wrong corlor
我试图发送h264我已经超过rtp并且通过ffplay播放,corlor也是错误的。我很困惑。有人知道如何解决这个问题吗?因为我是新来的,不擅长英语,请多指教(中文)。这是我的代码`package com.example.androidcodec;
import java.nio.ByteBuffer;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.util.Log;
import android.view.Surface;
public class Encoder {
private byte[] sps;
private byte[] pps;
private MediaCodec mEncoder;
private int width, height;
private byte[] yuv420;
private byte[] mInfo = null;
private MediaCodec mDecoder;
private Surface surface;
private int framerate;
private int bitrate;
public Encoder(int width, int height, int framerate, int bitrate,Surface surface) {
this.surface = surface;
this.width = width;
this.height = height;
this.framerate = framerate;
this.bitrate = bitrate;
yuv420 = new byte[width * height * 3 / 2];
mEncoder = MediaCodec.createEncoderByType("video/avc");
MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", width, height);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, framerate);
mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
mEncoder.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mEncoder.start();
}
public void close() {
try {
mEncoder.stop();
mEncoder.release();
mEncoder = null;
mDecoder.stop();
mDecoder.release();
mDecoder = null;
} catch (Exception e) {
e.printStackTrace();
}
}
public int offerEncoder(byte[] input, byte[] output) {
int pos = 0;
swapYV12toI420(input, yuv420, width, height);
ByteBuffer[] inputBuffers = mEncoder.getInputBuffers();
ByteBuffer[] outputBuffers = mEncoder.getOutputBuffers();
int inputBufferIndex = mEncoder.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(yuv420);
mEncoder.queueInputBuffer(inputBufferIndex, 0, yuv420.length, 0, 0);
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = mEncoder.dequeueOutputBuffer(bufferInfo, 0);
while (outputBufferIndex >= 0) {
ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
byte[] outData = new byte[bufferInfo.size];
outputBuffer.get(outData);
if (mInfo != null) {
System.arraycopy(outData, 0, output, pos, outData.length);
pos += outData.length;
} else {
ByteBuffer spsPpsBuffer = ByteBuffer.wrap(outData);
if (spsPpsBuffer.getInt() == 0x00000001) {
mInfo = new byte[outData.length];
System.arraycopy(outData, 0, mInfo, 0, outData.length);
findSpsAndPps(mInfo);
initDecoder();
}else {
return -1;
}
}
mEncoder.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = mEncoder.dequeueOutputBuffer(bufferInfo, 0);
}
return pos;
}
private void initDecoder() {
mDecoder = MediaCodec.createDecoderByType("video/avc");
MediaFormat mediaFormat = MediaFormat.createVideoFormat("video/avc", width, height);
mediaFormat.setByteBuffer("csd-0" , ByteBuffer.wrap(sps));
mediaFormat.setByteBuffer("csd-1", ByteBuffer.wrap(pps));
mediaFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, height*width);
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, framerate);
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
mDecoder.configure(mediaFormat, surface, null, 0);
mDecoder.start();
}
public void onFrame(byte[] buf, int offset, int length) {
ByteBuffer[] inputBuffers = mDecoder.getInputBuffers();
int inputBufferIndex = mDecoder.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
inputBuffer.clear();
inputBuffer.put(buf, offset, length);
int capacity = inputBuffer.capacity();
Log.e("tag", "capacity < length?"+":"+(capacity < length)+"......................");
mDecoder.queueInputBuffer(inputBufferIndex, 0, length, System.currentTimeMillis(), 0);
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputBufferIndex = mDecoder.dequeueOutputBuffer(bufferInfo, 0);
Log.e("tag", outputBufferIndex+"onFrame.........................................................");
while (outputBufferIndex >= 0) {
mDecoder.releaseOutputBuffer(outputBufferIndex, true);
outputBufferIndex = mDecoder.dequeueOutputBuffer(bufferInfo, 0);
}
}
// yv12 转 yuv420p yvu -> yuv
private void swapYV12toI420(byte[] yv12bytes, byte[] i420bytes, int width, int height) {
System.arraycopy(yv12bytes, 0, i420bytes, 0, width * height);
System.arraycopy(yv12bytes, width * height + width * height / 4, i420bytes, width * height, width * height / 4);
System.arraycopy(yv12bytes, width * height, i420bytes, width * height + width * height / 4, width * height / 4);
}
private void findSpsAndPps(byte[] config) {
Log.e("tag", printBuffer(config,0,config.length-1));
int spsEnd = 1;
for(int i = 4; i < config.length-4; i ++){
if(config[i]==0X00 && config[i+1]==0X00 &&config[i+2]==0X00 &&config[i+3]==0X01){
spsEnd = i-1;
break;
}
}
Log.e("tag", spsEnd-3+"...............................");
sps = new byte[spsEnd-3];
pps = new byte[config.length-spsEnd-5];
System.arraycopy(config,4,sps,0,spsEnd-3);
System.arraycopy(config,spsEnd+5,pps,0,config.length-spsEnd-5);
}
public byte[] getSps() {
return sps;
}
public byte[] getPps() {
return pps;
}
protected static String printBuffer(byte[] buffer, int start,int end) {
String str = "";
for (int i=start;i<end;i++) str+=","+Integer.toHexString(buffer[i]&0xFF);
return str+"\r\n";
}
}
`
答案 0 :(得分:0)
我自己解决了这个问题,我在details.parameters.setPreviewFormat中犯了一个错误,应该在预览开始之前调用参数.setPictureFormat。