package com.example.guoheng_iri.helloworld;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.os.Environment;
import android.util.Log;
import junit.framework.Assert;
public class VideoEncode {
private static final int TEST_Y = 120; // YUV values for colored rect
private static final int TEST_U = 160;
private static final int TEST_V = 200;
public int mWidth=1920;
public int mHeight=1080;
private static final int BIT_RATE = 1920*1080*30; // 2Mbps
private static final int FRAME_RATE = 30; // 30fps
private static final int IFRAME_INTERVAL = 10; // 10 seconds between I-frames
private static final int WIDTH = 1920;
private static final int HEIGHT = 1080;
public static final int NUMFRAMES=300;
private static final String TAG = "EncodeDecodeTest";
private static final boolean VERBOSE = true; // lots of logging
private static final String MIME_TYPE = "video/avc"; // H.264 Advanced Video Coding
private MediaCodec.BufferInfo mBufferInfo;
public MediaCodec mediaCodec;
public MediaMuxer mMuxer;
public int mTrackIndex;
public boolean mMuxerStarted;
private static final int encoderColorFormat=MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
public void VideoEncodePrepare() //这里需要传进来一个编码时的mediaformat,后续做
{
String outputPath = new File(Environment.getExternalStorageDirectory(),
"mytest." + WIDTH + "x" + HEIGHT + ".mp4").toString();
mBufferInfo = new MediaCodec.BufferInfo();
MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, mWidth, mHeight);
// Set some properties. Failing to specify some of these can cause the MediaCodec
// configure() call to throw an unhelpful exception.
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, encoderColorFormat);
format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
mediaCodec = null;
try {
mediaCodec = MediaCodec.createEncoderByType(MIME_TYPE);
mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
mediaCodec.start();
mMuxer = new MediaMuxer(outputPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
}catch (IOException ioe) {
throw new RuntimeException("failed init encoder", ioe);
}
mTrackIndex = -1;
mMuxerStarted = false;
}
public void close() {
mediaCodec.stop();
mediaCodec.release();
if (mMuxer != null) {
mMuxer.stop();
mMuxer.release();
mMuxer = null;
}
}
public void offerEncoder(byte[] input, int frameIdx) {
try {
ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
//outputBuffers = mediaCodec.getOutputBuffers();
int inputBufferIndex = mediaCodec.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
if (frameIdx==NUMFRAMES)
{
mediaCodec.queueInputBuffer(inputBufferIndex, 0, 0, System.nanoTime()/1000,
MediaCodec.BUFFER_FLAG_END_OF_STREAM);
if (VERBOSE) Log.d(TAG, "sent input EOS (with zero-length frame)");
}
else
{
ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
Assert.assertTrue(inputBuffer.capacity() >= input.length); //断言,帧数据容器超过缓冲区会抛出 AssertionFailedError
inputBuffer.clear();
inputBuffer.put(input);
mediaCodec.queueInputBuffer(inputBufferIndex, 0, input.length, 0, MediaCodec.BUFFER_FLAG_CODEC_CONFIG);
}
}else {
Log.i("AvcEncoder", "input buffer "+ frameIdx + " not read");
}
// int outputBufferIndex = mediaCodec.dequeueOutputBuffer(mBufferInfo,TIMEOUT_USEC);
//
//
// while (true) {
//
// outputBuffers = mediaCodec.getOutputBuffers();
// if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
// outputBuffers = mediaCodec.getOutputBuffers();
//
// }
//
// else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
// // should happen before receiving buffers, and should only happen once
// if (mMuxerStarted) {
// throw new RuntimeException("format changed twice");
// }
// MediaFormat newFormat = mediaCodec.getOutputFormat();
// Log.d(TAG, "encoder output format changed: " + newFormat);
//
// // now that we have the Magic Goodies, start the muxer
// mTrackIndex = mMuxer.addTrack(newFormat);
// mMuxer.start();
// mMuxerStarted = true;
// break;
// }
//
//
// else if(outputBufferIndex >= 0) {
// ByteBuffer outputBuffer = outputBuffers[outputBufferIndex];
//
// if (outputBuffer == null) {
// throw new RuntimeException("encoderOutputBuffer " + outputBufferIndex +
// " was null");
// }
//
// if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
// // The codec config data was pulled out and fed to the muxer when we got
// // the INFO_OUTPUT_FORMAT_CHANGED status. Ignore it.
// if (VERBOSE) Log.d(TAG, "ignoring BUFFER_FLAG_CODEC_CONFIG");
// mBufferInfo.size = 0;
// }
//
//
// if (mBufferInfo.size != 0) {
// if (!mMuxerStarted) {
// throw new RuntimeException("muxer hasn't started");
// }
//
// // adjust the ByteBuffer values to match BufferInfo (not needed?)
// outputBuffer.position(mBufferInfo.offset);
// outputBuffer.limit(mBufferInfo.offset + mBufferInfo.size);
//
// mMuxer.writeSampleData(mTrackIndex, outputBuffer, mBufferInfo);
// mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
//
// if (VERBOSE) Log.d(TAG, "sent " + mBufferInfo.size + " bytes to muxer");
// break;
// }
//
//
// //outputBuffer.position(bufferInfo.offset);
// //outputBuffer.limit(bufferInfo.offset + bufferInfo.size);
//
//// byte[] outData = new byte[bufferInfo.size];
//// outputBuffer.get(outData);
//// outputStream.write(outData, 0, outData.length);
//// outputStream.flush();
//// Log.i("AvcEncoder", outData.length + " bytes written");
//
//
// }
//
// if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
// break;
//
- 1
- 2
- 3
前往页