Распространение видео с помощью MediaMuxer и MediaExtractor дает вывод журнала ошибок с отметкой времени в Android Lollipop - PullRequest
0 голосов
/ 24 апреля 2020

Я создал функцию для разделения видео на заданные клипы длиной c с помощью Media Muxer и Media Extracter.

 private int splitVideo(Uri uri, String dstDirPath, int splitTime) {
    int error = 0;

    try {
        // Set up MediaExtractor to read from the source.
        MediaExtractor extractor = new MediaExtractor();
        MediaMuxer muxer;
        MediaMetadataRetriever retrieverSrc = new MediaMetadataRetriever();
        String extension;

        if (isContentUri(uri)) {
            ContentResolver contentResolver = getContentResolver();
            FileInputStream fileInputStream = (FileInputStream) contentResolver.openInputStream(uri);
            FileDescriptor fileDescriptor = fileInputStream.getFD();

            extractor.setDataSource(fileDescriptor);
            retrieverSrc.setDataSource(fileDescriptor);
            extension = getExtensionFromType(contentResolver.getType(uri));
            srcPath=getFilePathFromUri(context,uri);
            Log.d("path",srcPath);
        } else {
            srcPath = uri.getPath();
            extractor.setDataSource(srcPath);
            retrieverSrc.setDataSource(srcPath);
            extension = getExtensionFromFilePath(srcPath);
        }

        int trackCount = extractor.getTrackCount();

        // Set up the orientation and starting time for extractor.


        String degreesString = retrieverSrc.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);


        String videoDurationStr = retrieverSrc.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
        int duration = Integer.parseInt(videoDurationStr);

        int startMs, endMs = 0;

        int timeDelta=duration-splitTime;
        if (timeDelta<0) timeDelta=-timeDelta;
        if (timeDelta<minClipTime) {
            MediaAction.toast(context, "No need to split. Share as it is");
            error = 1;
            return error;
        }


        int fileIndex = 0;
        boolean remain = true;

        while (remain) {

            startMs = endMs;
            endMs = startMs + splitTime;


            if (endMs > duration) {
                endMs = -1;
                remain = false;
                int clipTime=duration-startMs;

                if(clipTime<minClipTime){
                    Log.d(TAG, "Skipped last small clip");
                    continue;}
                Log.d(TAG, "End reached");
            }

            Log.d(TAG, "Start: " + startMs);
            Log.d(TAG, "End: " + endMs);
            //if(true) continue;

            fileIndex++;
            String splitFileName = "Video" + fileIndex + extension;
            String dstSplitPath = dstDirPath + splitFileName;
            splitFileNames.add(splitFileName);
            muxer = new MediaMuxer(dstSplitPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
            // Set up the tracks and retrieve the max buffer size for selected
            // tracks.
            HashMap<Integer, Integer> indexMap = new HashMap<>(trackCount);
            int bufferSize = -1;
            for (int i = 0; i < trackCount; i++) {
                MediaFormat format = extractor.getTrackFormat(i);
                String mime = format.getString(MediaFormat.KEY_MIME);
                boolean selectCurrentTrack = false;
                if (mime.startsWith("audio/")) {
                    selectCurrentTrack = true;
                } else if (mime.startsWith("video/")) {
                    selectCurrentTrack = true;
                }
                if (selectCurrentTrack) {
                    extractor.selectTrack(i);
                    int dstIndex = muxer.addTrack(format);
                    indexMap.put(i, dstIndex);
                    if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
                        int newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
                        bufferSize = newSize > bufferSize ? newSize : bufferSize;
                    }
                }
            }
            if (bufferSize < 0) {
                bufferSize = DEFAULT_BUFFER_SIZE;
            }

            if (degreesString != null) {
                int degrees = Integer.parseInt(degreesString);
                if (degrees >= 0) {
                    muxer.setOrientationHint(degrees);
                }
            }
            if (startMs > 0) {
                extractor.seekTo(startMs * 1000, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
            }
            // Copy the samples from MediaExtractor to MediaMuxer. We will loop
            // for copying each sample and stop when we get to the end of the source
            // file or exceed the end time of the trimming.
            int offset = 0;
            int trackIndex = -1;
            ByteBuffer dstBuf = ByteBuffer.allocate(bufferSize);
            MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
            try {
                muxer.start();
                while (true) {
                    bufferInfo.offset = offset;
                    bufferInfo.size = extractor.readSampleData(dstBuf, offset);
                    if (bufferInfo.size < 0) {
                        Log.d(TAG, "Saw input EOS.");
                        bufferInfo.size = 0;
                        break;
                    } else {
                        bufferInfo.presentationTimeUs = extractor.getSampleTime();
                        if (endMs > 0 && bufferInfo.presentationTimeUs > (endMs * 1000)) {
                            Log.d(TAG, "The current sample is over the trim end time.");
                            break;
                        } else {
                            bufferInfo.flags = extractor.getSampleFlags();
                            trackIndex = extractor.getSampleTrackIndex();
                            muxer.writeSampleData(indexMap.get(trackIndex), dstBuf,
                                    bufferInfo);
                            extractor.advance();
                        }
                    }
                }
                muxer.stop();

                //deleting the old file
                //File file = new File(srcPath);
                //file.delete();
            } catch (IllegalStateException e) {
                // Swallow the exception due to malformed source.
                Log.d(TAG, "The source video file is malformed");
                MediaAction.toast(context, "The source video file is malformed");
                error = 2;
            } finally {
                muxer.release();
            }
        }
    } catch (IOException e) {
        Log.d("error", e.getMessage());
        MediaAction.toast(context, "Something went wrong while accessing media");
        e.printStackTrace();
        error = 3;

    }catch (Exception e){
        Log.d("error", e.getMessage());
        MediaAction.toast(context, "Something went wrong while accessing media");
        e.printStackTrace();
        error = 4;
    }

    return error;
}

Я создал его, используя пример в this

Это полностью работает скважина в android 10 . Но в android 5.1 он выдает журнал, как показано ниже, и создает видеофайл с ошибкой воспроизведения, при разбиении некоторые файлы не все файлы .

 E/MPEG4Writer: timestampUs 33334 < lastTimestampUs 66667 for Video track

Как Чтобы решить эту проблему, сделайте эту функцию работающей во всех файлах в android 5.1?

...