android中 MediaCodec 压缩视频使用示例
时间: 2023-10-11 10:11:36 浏览: 75
好的,以下是一个使用 MediaCodec 进行视频编码的示例代码,你可以参考一下:
```java
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 java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
public class VideoEncoder {
private static final String TAG = "VideoEncoder";
// 编码器
private MediaCodec mEncoder;
// 复用器
private MediaMuxer mMuxer;
// 视频轨道
private int mTrackIndex;
// 是否已经开始编码
private boolean mIsStarted;
// 视频宽度
private int mWidth;
// 视频高度
private int mHeight;
// 视频帧率
private int mFrameRate;
// 视频码率
private int mBitRate;
// 编码器输出的 buffer 信息
private MediaCodec.BufferInfo mBufferInfo;
// 用于存储编码后的数据
private ByteBuffer mOutputBuffer;
public VideoEncoder(int width, int height, int frameRate, int bitRate) {
mWidth = width;
mHeight = height;
mFrameRate = frameRate;
mBitRate = bitRate;
}
/**
* 开始编码
*/
public void start() {
try {
// 初始化编码器
mEncoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, mWidth, mHeight);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
format.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
// 创建一个文件用于存储编码后的数据
String outputPath = new File(Environment.getExternalStorageDirectory(), "output.mp4").getAbsolutePath();
mMuxer = new MediaMuxer(outputPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
// 开始编码
mEncoder.start();
mIsStarted = true;
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 编码一帧数据
*
* @param input 输入的数据
* @param pts 每一帧的时间戳
*/
public void encodeFrame(byte[] input, long pts) {
if (!mIsStarted) {
Log.e(TAG, "Encoder is not started.");
return;
}
// 取出可用的输入 buffer
int inputBufferIndex = mEncoder.dequeueInputBuffer(-1);
if (inputBufferIndex >= 0) {
ByteBuffer inputBuffer = mEncoder.getInputBuffer(inputBufferIndex);
inputBuffer.clear();
inputBuffer.put(input);
// 将输入的数据喂给编码器
mEncoder.queueInputBuffer(inputBufferIndex, 0, input.length, pts, 0);
}
// 取出可用的输出 buffer
int outputBufferIndex = mEncoder.dequeueOutputBuffer(mBufferInfo, 0);
while (outputBufferIndex >= 0) {
mOutputBuffer = mEncoder.getOutputBuffer(outputBufferIndex);
mOutputBuffer.position(mBufferInfo.offset);
mOutputBuffer.limit(mBufferInfo.offset + mBufferInfo.size);
// 写入到复用器
mMuxer.writeSampleData(mTrackIndex, mOutputBuffer, mBufferInfo);
// 释放输出 buffer
mEncoder.releaseOutputBuffer(outputBufferIndex, false);
outputBufferIndex = mEncoder.dequeueOutputBuffer(mBufferInfo, 0);
}
}
/**
* 停止编码
*/
public void stop() {
if (!mIsStarted) {
Log.e(TAG, "Encoder is not started.");
return;
}
mEncoder.stop();
mEncoder.release();
mMuxer.stop();
mMuxer.release();
mIsStarted = false;
}
/**
* 初始化视频轨道
*/
public void initTrack() {
if (!mIsStarted) {
Log.e(TAG, "Encoder is not started.");
return;
}
mTrackIndex = mMuxer.addTrack(mEncoder.getOutputFormat());
mMuxer.start();
mBufferInfo = new MediaCodec.BufferInfo();
}
}
```
这段代码中,我们使用 MediaCodec 进行视频编码,并将编码后的数据通过 MediaMuxer 写入到文件中。
需要注意的是,编码器的输入数据必须是 YUV 格式的数据,而不是一般的 RGB 格式,因此你需要将原始数据转化为 YUV 格式,然后再进行编码。除此之外,还需要注意编码器的配置参数,例如视频宽度、高度、帧率、码率等等。