借助mp4parser进行视频修剪

时间:2018-12-03 11:22:55

标签: android video video-processing

在使用该应用程序时,我正在使用mp4parser在android应用程序中对视频进行修剪。

在表演时,有时我将开始时间和结束时间设为零,所以它会创建空白视频。

下面是我的代码。

private void generateVideo(@NonNull File src, @NonNull File dst, long startMs,
                           long endMs, @NonNull OnVideoTrimListener callback) throws IOException {

    try {
        // NOTE: Switched to using FileDataSourceViaHeapImpl since it does not use memory mapping (VM).
        // Otherwise we get OOM with large movie files.
        Movie movie = MovieCreator.build(new FileDataSourceImpl(src.getAbsolutePath()));

        List<Track> tracks = movie.getTracks();
        movie.setTracks(new LinkedList<Track>());
        // remove all tracks we will create new tracks from the old

        double startTime1 = startMs / 1000;
        double endTime1 = endMs / 1000;

        boolean timeCorrected = false;

        // Here we try to find a track that has sync samples. Since we can only start decoding
        // at such a sample we SHOULD make sure that the start of the new fragment is exactly
        // such a frame
        for (Track track : tracks) {
            if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) {
                if (timeCorrected) {
                    // This exception here could be a false positive in case we have multiple tracks
                    // with sync samples at exactly the same positions. E.g. a single movie containing
                    // multiple qualities of the same video (Microsoft Smooth Streaming file)

                    throw new RuntimeException("The startTime has already been corrected by another track with SyncSample. Not Supported.");
                }
                startTime1 = correctTimeToSyncSample(track, startTime1, false);
                endTime1 = correctTimeToSyncSample(track, endTime1, true);
                timeCorrected = true;
            }
        }

        for (Track track : tracks) {
            long currentSample = 0;
            double currentTime = 0;
            double lastTime = -1;
            long startSample1 = -1;
            long endSample1 = -1;

            for (int i = 0; i < track.getSampleDurations().length; i++) {
                long delta = track.getSampleDurations()[i];


                if (currentTime > lastTime && currentTime <= startTime1) {
                    // current sample is still before the new starttime
                    startSample1 = currentSample;
                }
                if (currentTime > lastTime && currentTime <= endTime1) {
                    // current sample is after the new start time and still before the new endtime
                    endSample1 = currentSample;
                }
                lastTime = currentTime;
                currentTime += (double) delta / (double) track.getTrackMetaData().getTimescale();
                currentSample++;
            }
            movie.addTrack(new AppendTrack(new CroppedTrack(track, startSample1, endSample1)));
        }

        Container out = new DefaultMp4Builder().build(movie);

        FileOutputStream fos = new FileOutputStream(dst);
        FileChannel fc = fos.getChannel();
        out.writeContainer(fc);

        fc.close();
        fos.close();
        if (callback != null)
            callback.getResult(Uri.parse(dst.toString()));
    } catch (IOException e) {
        e.printStackTrace();
    } catch (RuntimeException e) {
        e.printStackTrace();
    }
}

然后

private static double correctTimeToSyncSample(@NonNull Track track, double cutHere, boolean next) {
    double[] timeOfSyncSamples = new double[track.getSyncSamples().length];
    long currentSample = 0;
    double currentTime = 0;
    for (int i = 0; i < track.getSampleDurations().length; i++) {
        long delta = track.getSampleDurations()[i];

        if (Arrays.binarySearch(track.getSyncSamples(), currentSample + 1) >= 0) {
            // samples always start with 1 but we start with zero therefore +1
            timeOfSyncSamples[Arrays.binarySearch(track.getSyncSamples(), currentSample + 1)] = currentTime;
        }
        currentTime += (double) delta / (double) track.getTrackMetaData().getTimescale();
        currentSample++;

    }
    double previous = 0;
    for (double timeOfSyncSample : timeOfSyncSamples) {
        if (timeOfSyncSample > cutHere) {
            if (next) {
                return timeOfSyncSample;
            } else {
                return previous;
            }
        }
        previous = timeOfSyncSample;
    }
    return timeOfSyncSamples[timeOfSyncSamples.length - 1];
}

代码有什么问题吗?

0 个答案:

没有答案