Untitled

 avatar
unknown
plain_text
5 months ago
7.4 kB
4
Indexable
package com.example.myapplication;

import android.content.Context;
import android.media.MediaExtractor;
import android.media.MediaCodec;
import android.media.MediaFormat;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class VideoBatchProcessor {

    private static final String VIDEO_PATH = "android.resource://com.example.app/" + R.raw.sample_video;
    private String OUTPUT_DIR;


    private Context context;

    public VideoBatchProcessor(Context context) {
        this.context = context;
        this.OUTPUT_DIR = context.getCacheDir().getAbsolutePath();
    }
    private static final long BATCH_DURATION_US = 3000000;

    public void abcd() throws IOException {
        MediaExtractor extractor = new MediaExtractor();
        extractor.setDataSource(this.context.getResources().openRawResourceFd(R.raw.sample_video));

        int videoTrackIndex = -1;
        for (int i = 0; i < extractor.getTrackCount(); i++) {
            MediaFormat format = extractor.getTrackFormat(i);
            String mimeType = format.getString(MediaFormat.KEY_MIME);
            if (mimeType.startsWith("video/")) {
                videoTrackIndex = i;
                break;
            }
        }

        if (videoTrackIndex == -1) {
            throw new RuntimeException("Video track không tìm thấy.");
        }

        extractor.selectTrack(videoTrackIndex);
        MediaFormat videoFormat = extractor.getTrackFormat(videoTrackIndex);
        long videoDurationUs = videoFormat.getLong(MediaFormat.KEY_DURATION);

        extractor.release();

        // 2. Chia video thành các batch dựa trên thời gian
        List<Batch> batches = new ArrayList<>();
        for (long startTimeUs = 0; startTimeUs < videoDurationUs; startTimeUs += BATCH_DURATION_US) {
            long endTimeUs = Math.min(startTimeUs + BATCH_DURATION_US, videoDurationUs);
            batches.add(new Batch(VIDEO_PATH, OUTPUT_DIR, videoTrackIndex, startTimeUs, endTimeUs));
        }

        // 3. Xử lý song song các batch bằng ForkJoinPool
        ForkJoinPool pool = new ForkJoinPool();
        pool.invoke(new BatchTask(batches,context));
    }

    // Class đại diện cho mỗi batch
    static class Batch {
        String videoPath;
        String outputDir;
        int videoTrackIndex;
        long startTimeUs;
        long endTimeUs;

        Batch(String videoPath, String outputDir, int videoTrackIndex, long startTimeUs, long endTimeUs) {
            this.videoPath = videoPath;
            this.outputDir = outputDir;
            this.videoTrackIndex = videoTrackIndex;
            this.startTimeUs = startTimeUs;
            this.endTimeUs = endTimeUs;
        }
    }

    // ForkJoinTask xử lý các batch
    static class BatchTask extends RecursiveTask<Void> {
        List<Batch> batches;
        Context context;
        BatchTask(List<Batch> batches,Context context) {
            this.batches = batches;
            this.context = context;
        }

        @Override
        protected Void compute() {
            if (batches.size() <= 1) {
                // Xử lý một batch
                if (!batches.isEmpty()) {
                    processBatch(batches.get(0));
                }
                return null;
            }

            // Chia các batch thành hai nhóm và xử lý song song
            int mid = batches.size() / 2;
            BatchTask leftTask = new BatchTask(batches.subList(0, mid),context);
            BatchTask rightTask = new BatchTask(batches.subList(mid, batches.size()),context);

            invokeAll(leftTask, rightTask);

            return null;
        }

        private void processBatch(Batch batch) {
            try {
                MediaExtractor extractor = new MediaExtractor();
                extractor.setDataSource(this.context.getResources().openRawResourceFd(R.raw.sample_video));
                extractor.selectTrack(batch.videoTrackIndex);
                extractor.seekTo(batch.startTimeUs, MediaExtractor.SEEK_TO_CLOSEST_SYNC);

                MediaFormat format = extractor.getTrackFormat(batch.videoTrackIndex);
                String mimeType = format.getString(MediaFormat.KEY_MIME);

                MediaCodec codec = MediaCodec.createDecoderByType(mimeType);
                codec.configure(format, null, null, 0);
                codec.start();

                ByteBuffer inputBuffer = ByteBuffer.allocateDirect(format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE));
                MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();

                File batchDir = new File(batch.outputDir, "batch_" + (batch.startTimeUs / 1000000) + "s");
                if (!batchDir.exists()) batchDir.mkdirs();

                while (true) {
                    int sampleSize = extractor.readSampleData(inputBuffer, 0);
                    long sampleTime = extractor.getSampleTime();

                    if (sampleSize < 0 || sampleTime >= batch.endTimeUs) {
                        break;
                    }

                    int inputIndex = codec.dequeueInputBuffer(10000);
                    if (inputIndex >= 0) {
                        ByteBuffer codecInputBuffer = codec.getInputBuffer(inputIndex);
                        if (codecInputBuffer != null) {
                            codecInputBuffer.put(inputBuffer);
                        }
                        codec.queueInputBuffer(inputIndex, 0, sampleSize, sampleTime, 0);
                        extractor.advance();
                    }

                    int outputIndex = codec.dequeueOutputBuffer(bufferInfo, 10000);
                    while (outputIndex >= 0) {
                        ByteBuffer outputBuffer = codec.getOutputBuffer(outputIndex);
                        if (outputBuffer != null) {
                            // Lưu frame ra file
                            saveFrameToFile(outputBuffer, bufferInfo, batchDir);
                        }
                        codec.releaseOutputBuffer(outputIndex, false);
                        outputIndex = codec.dequeueOutputBuffer(bufferInfo, 10000);
                    }
                }

                extractor.release();
                codec.stop();
                codec.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        private void saveFrameToFile(ByteBuffer buffer, MediaCodec.BufferInfo info, File outputDir) {
            try {
                // Tạo file mới
                File frameFile = new File(outputDir, "frame_" + (info.presentationTimeUs / 1000) + ".yuv");
                FileOutputStream fos = new FileOutputStream(frameFile);

                // Ghi dữ liệu vào file
                byte[] data = new byte[info.size];
                buffer.get(data);
                fos.write(data);

                fos.flush();
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
Editor is loading...
Leave a Comment