bytedeco/javacv

Low GPU Utilization When Transcoding Videos Using javacv ffmpeg

Open

#2189 aperta il 21 feb 2024

Vedi su GitHub
 (0 commenti) (0 reazioni) (0 assegnatari)Java (1583 fork)batch import
help wantedquestion

Metriche repository

Star
 (6985 star)
Metriche merge PR
 (Nessuna PR mergiata in 30 g)

Descrizione

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

Guida contributor