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提供的MediaCodecMediaMuxer类来实现视频旋转功能。代码如下:

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