Untitled

 avatar
unknown
plain_text
5 months ago
5.9 kB
3
Indexable
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaMuxer;
import android.view.Surface;

import java.io.IOException;
import java.nio.ByteBuffer;

public class VideoProcessor {
    private String inputPath;
    private String outputPath;

    public VideoProcessor(String inputPath, String outputPath) {
        this.inputPath = inputPath;
        this.outputPath = outputPath;
    }

    public void processVideo() {
        try {
            // Setup decoder
            MediaExtractor extractor = new MediaExtractor();
            extractor.setDataSource(inputPath);
            int videoTrackIndex = selectVideoTrack(extractor);
            extractor.selectTrack(videoTrackIndex);

            MediaFormat format = extractor.getTrackFormat(videoTrackIndex);
            int width = format.getInteger(MediaFormat.KEY_WIDTH);
            int height = format.getInteger(MediaFormat.KEY_HEIGHT);

            MediaCodec decoder = MediaCodec.createDecoderByType(format.getString(MediaFormat.KEY_MIME));
            Surface inputSurface = setupDecoder(decoder, format);

            // Setup encoder
            MediaCodec encoder = setupEncoder(width, height);
            Surface outputSurface = encoder.createInputSurface();

            // Setup muxer for output file
            MediaMuxer muxer = new MediaMuxer(outputPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);

            // Setup EGL for OpenGL rendering
            EGLHelper eglHelper = new EGLHelper(outputSurface);
            OpenGLRenderer renderer = new OpenGLRenderer();

            // Start decoder and encoder
            decoder.start();
            encoder.start();

            // Configure the muxer with video format
            int videoTrackIndexForMuxer = muxer.addTrack(encoder.getOutputFormat());
            muxer.start();

            // Process frames
            processFrames(extractor, decoder, encoder, muxer, eglHelper, renderer, videoTrackIndexForMuxer);

            // Stop muxer and codecs
            muxer.stop();
            muxer.release();
            decoder.stop();
            decoder.release();
            encoder.stop();
            encoder.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Surface setupDecoder(MediaCodec decoder, MediaFormat format) {
        Surface surface = MediaCodec.createPersistentInputSurface();
        decoder.configure(format, surface, null, 0);
        return surface;
    }

    private MediaCodec setupEncoder(int width, int height) throws IOException {
        MediaFormat format = MediaFormat.createVideoFormat("video/avc", width, height);
        format.setInteger(MediaFormat.KEY_BIT_RATE, 2000000);
        format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5);

        MediaCodec encoder = MediaCodec.createEncoderByType("video/avc");
        encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        return encoder;
    }

    private void processFrames(MediaExtractor extractor, MediaCodec decoder, MediaCodec encoder,
                               MediaMuxer muxer, EGLHelper eglHelper, OpenGLRenderer renderer,
                               int videoTrackIndexForMuxer) {
        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
        boolean endOfStream = false;

        while (!endOfStream) {
            // Feed input to decoder
            int inputIndex = decoder.dequeueInputBuffer(10000);
            if (inputIndex >= 0) {
                ByteBuffer inputBuffer = decoder.getInputBuffer(inputIndex);
                int size = extractor.readSampleData(inputBuffer, 0);
                if (size < 0) {
                    decoder.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                    endOfStream = true;
                } else {
                    decoder.queueInputBuffer(inputIndex, 0, size, extractor.getSampleTime(), 0);
                    extractor.advance();
                }
            }

            // Process decoder output
            int outputIndex = decoder.dequeueOutputBuffer(bufferInfo, 10000);
            if (outputIndex >= 0) {
                eglHelper.makeCurrent();
                renderer.drawFrame(eglHelper.getTextureId());
                eglHelper.swapBuffers();

                // Encoder
                int encoderInputIndex = encoder.dequeueInputBuffer(10000);
                if (encoderInputIndex >= 0) {
                    ByteBuffer encoderInputBuffer = encoder.getInputBuffer(encoderInputIndex);
                    encoderInputBuffer.clear();
                    encoder.queueInputBuffer(encoderInputIndex, 0, bufferInfo.size, bufferInfo.presentationTimeUs, 0);
                }

                // Encoder output
                int encoderOutputIndex = encoder.dequeueOutputBuffer(bufferInfo, 10000);
                if (encoderOutputIndex >= 0) {
                    muxer.writeSampleData(videoTrackIndexForMuxer, encoder.getOutputBuffer(encoderOutputIndex), bufferInfo);
                    encoder.releaseOutputBuffer(encoderOutputIndex, false);
                }

                decoder.releaseOutputBuffer(outputIndex, true);
            }
        }
    }

    private int selectVideoTrack(MediaExtractor extractor) {
        for (int i = 0; i < extractor.getTrackCount(); i++) {
            MediaFormat format = extractor.getTrackFormat(i);
            String mime = format.getString(MediaFormat.KEY_MIME);
            if (mime.startsWith("video/")) {
                return i;
            }
        }
        throw new IllegalArgumentException("No video track found");
    }
}
Editor is loading...
Leave a Comment