Android视频旋转90度
在Android开发中,有时候我们需要对视频进行旋转操作,以满足用户的需求。本文将介绍如何使用Android提供的API来实现视频旋转90度的功能。
1. 获取视频文件
首先,我们需要获取需要旋转的视频文件。可以通过以下代码来实现:
private File getVideoFile() {
File file = new File(Environment.getExternalStorageDirectory(), "test.mp4");
if (!file.exists()) {
try {
InputStream is = getResources().openRawResource(R.raw.test);
FileOutputStream fos = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) != -1) {
fos.write(buffer, 0, length);
}
is.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
上述代码中,我们创建了一个名为test.mp4
的测试视频文件,并将其保存在设备的外部存储目录中。如果文件不存在,则从res/raw
目录下的test.mp4
文件中读取数据,并将其写入到创建的文件中。
2. 旋转视频
接下来,我们使用Android提供的MediaCodec
和MediaMuxer
类来实现视频旋转功能。代码如下:
private void rotateVideo(File videoFile) {
try {
MediaExtractor extractor = new MediaExtractor();
extractor.setDataSource(videoFile.getPath());
int trackIndex = -1;
for (int i = 0; i < extractor.getTrackCount(); i++) {
MediaFormat format = extractor.getTrackFormat(i);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) {
trackIndex = i;
break;
}
}
extractor.selectTrack(trackIndex);
MediaFormat format = extractor.getTrackFormat(trackIndex);
int width = format.getInteger(MediaFormat.KEY_WIDTH);
int height = format.getInteger(MediaFormat.KEY_HEIGHT);
int rotation = 90;
MediaCodec decoder = MediaCodec.createDecoderByType(format.getString(MediaFormat.KEY_MIME));
decoder.configure(format, null, null, 0);
decoder.start();
MediaCodec encoder = MediaCodec.createEncoderByType(format.getString(MediaFormat.KEY_MIME));
format.setInteger(MediaFormat.KEY_ROTATION, rotation);
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
encoder.start();
ByteBuffer[] decoderInputBuffers = decoder.getInputBuffers();
ByteBuffer[] decoderOutputBuffers = decoder.getOutputBuffers();
ByteBuffer[] encoderInputBuffers = encoder.getInputBuffers();
ByteBuffer[] encoderOutputBuffers = encoder.getOutputBuffers();
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
boolean isEOS = false;
long startTime = System.nanoTime();
while (!Thread.interrupted()) {
if (!isEOS) {
int inIndex = decoder.dequeueInputBuffer(10000);
if (inIndex >= 0) {
ByteBuffer buffer = decoderInputBuffers[inIndex];
int sampleSize = extractor.readSampleData(buffer, 0);
if (sampleSize < 0) {
decoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isEOS = true;
} else {
long presentationTimeUs = extractor.getSampleTime();
decoder.queueInputBuffer(inIndex, 0, sampleSize, presentationTimeUs, 0);
extractor.advance();
}
}
}
int outIndex = decoder.dequeueOutputBuffer(info, 10000);
switch (outIndex) {
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
decoderOutputBuffers = decoder.getOutputBuffers();
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
format = decoder.getOutputFormat();
int rotationValue = format.getInteger(MediaFormat.KEY_ROTATION);
if (rotationValue != rotation) {
format.setInteger(MediaFormat.KEY_ROTATION, rotation);
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
encoder.start();
encoderInputBuffers = encoder.getInputBuffers();
encoderOutputBuffers = encoder.getOutputBuffers();
}
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
break;
default:
ByteBuffer buffer = decoderOutputBuffers[outIndex];
int size = info.size;
long presentationTimeUs = info.presentationTimeUs;
if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
info.size = 0;
}
if (size >= 0) {
buffer.position(info.offset);
buffer.limit(info.offset + size);
encoder.queueInputBuffer(outIndex, 0, size, presentationTimeUs, info.flags);
}
decoder.releaseOutputBuffer(outIndex, false);
break;
}
int outIndex2 = encoder.dequeueOutputBuffer(info, 10000);
switch (outIndex2) {
case