bytedeco/javacv

Low GPU Utilization When Transcoding Videos Using javacv ffmpeg

Open

#2,189 opened on Feb 21, 2024

View on GitHub
 (0 comments) (0 reactions) (0 assignees)Java (1,583 forks)batch import
help wantedquestion

Repository metrics

Stars
 (6,985 stars)
PR merge metrics
 (No merged PRs in 30d)

Description

When I use the following code to transcode videos, I find that the GPU utilization is much lower compared to directly using cmd to call ffmpeg.

    public boolean convert(String inputFileUrl, String outPutUrl, String hlsBaseUrl, String segmentFilename, int hlsTime, ConvertObserver convertObserver) {
        MyFFmpegLogBack.setLevel(AV_LOG_INFO);
        MyFFmpegLogBack.set();
        try (FFmpegFrameGrabber grabber=new FFmpegFrameGrabber(inputFileUrl)){
            grabber.start();
            var videoBitrate = grabber.getVideoBitrate();
            grabber.setVideoCodecName("h264_cuvid");
            grabber.restart();
            String m3u8SaveUrl=outPutUrl+"index.m3u8";
            String segmentSaveFileUrl=(outPutUrl+hlsBaseUrl+segmentFilename).toString();
            try(FFmpegFrameRecorder recorder=new FFmpegFrameRecorder(m3u8SaveUrl,grabber.getImageWidth(),grabber.getImageHeight(), grabber.getAudioChannels())){
                recorder.setVideoCodecName("h264_nvenc");
                Integer selectedFormat = null;
                AVCodec enc = avcodec_find_encoder_by_name(recorder.getVideoCodecName());
                if(enc!=null){
                    IntPointer formats = enc.pix_fmts();
                    int i = 0;
                    while (true) {
                        int format = formats.get(i++);
                        // always prefer yuv420p, if available
                        if(format == avutil.AV_PIX_FMT_YUV420P) {
                            selectedFormat = avutil.AV_PIX_FMT_YUV420P;
                            break;
                        }
                        if(format ==  avutil.AV_PIX_FMT_NONE) {
                            selectedFormat = avcodec.avcodec_find_best_pix_fmt_of_list(formats, avutil.AV_PIX_FMT_YUV420P, 0, null);
                            break;
                        }
                    }
                }
                if(selectedFormat==null){
                    selectedFormat = avutil.AV_PIX_FMT_YUV420P;
                }
                recorder.setPixelFormat(selectedFormat);

                recorder.setVideoOption("threads", "10");
                recorder.setFormat("hls");
                recorder.setOption("hls_playlist_type","vod");
                recorder.setOption("hls_list_size", "0");
                recorder.setOption("hls_flags", "delete_segments");
                recorder.setOption("hls_delete_threshold", "1");
                recorder.setOption("hls_segment_type", "mpegts");
                recorder.setOption("hls_time", String.valueOf(hlsTime));
                recorder.setOption("hls_segment_filename",segmentSaveFileUrl);
                recorder.setFrameRate(25);
                recorder.setVideoBitrate(2000000);
                recorder.setGopSize(hlsTime);
                recorder.start();

                Frame capturedFrame;
                while (true) {
                    capturedFrame = grabber.grabFrame();
                    if (capturedFrame == null) {
                        log.info("success");
                        recorder.stop();
                        recorder.release();
                        grabber.stop();
                        grabber.release();
                        break;
                    }
                    recorder.record(capturedFrame);
                }
                return true;

            }catch (Exception e){
            }
        }catch (Exception e){
        }

        return false;
    }

i use nvidia-smi dmon to watch utilization this use javacv GPU Utilization: 1

this is use command line: 2

my gpu is Nvidia GTX2060SUPER

Contributor guide