Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

there may be a memory leak in the av_read_frame code #763

Open
zhhades opened this issue Jun 20, 2024 · 0 comments
Open

there may be a memory leak in the av_read_frame code #763

zhhades opened this issue Jun 20, 2024 · 0 comments

Comments

@zhhades
Copy link

zhhades commented Jun 20, 2024

Hello, first of all, thank you for your dedication to the open source industry. Currently, I am using javacpp1.5.10 & ffmpeg-platform 1.5.10 & ffmpeg-platform-gpl 1.5.10 & Cuda 12.1-8.9-1.5.9 for video stream decoding development work. In the following code, I have found that there may be a memory leak. Can you help me take a look?

<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacpp</artifactId>
    <version>1.5.10</version>
</dependency>
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>ffmpeg-platform</artifactId>
    <version>6.1.1-1.5.10</version>
</dependency>

<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>ffmpeg-platform-gpl</artifactId>
    <version>6.1.1-1.5.10</version>
</dependency>

<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>cuda</artifactId>
    <version>12.1-8.9-1.5.9</version>
</dependency>
public void doDecoder() throws NeedRetryException {

    AVFormatContext pFormatCtx = null;
    AVCodecContext pCodecCtx = null;
    AVPacket packet = av_packet_alloc();
    AVDictionary options = new AVDictionary(null);
    try {
        
        // due to network limitations, the TCP protocol must be used
        av_dict_set(options, "rtsp_transport", "tcp", 0);
        av_dict_set(options, "buffer_size", "2048000", 0);
        pFormatCtx = getFormatContext(decoderTask.getVideoUrl(), options);
        int videoStreamIndex = getVideoStreamIndex(pFormatCtx);
        if (videoStreamIndex < 0) {
            log.error("video streams has no stream video");
            return;
        }
        pCodecCtx = getCodecContext(pFormatCtx, videoStreamIndex, useGpu,options);
        if (null == pCodecCtx) {
            return;
        }
        int ret = 0;
        while (( ret = av_read_frame(pFormatCtx, packet))>=0) {
            try {
                if (packet.stream_index() == videoStreamIndex) {
                    ret = avcodec_send_packet(pCodecCtx,packet);
                    // to  test the mem leak , annotate this line
                    // decode(seiInfo,frameNumber,pCodecCtx,executorService);
                }
            }catch (Exception e){
                // ignore
            }finally {
                av_packet_unref(packet);
            }
        }
        av_packet_unref(packet);
        if (ret == AVERROR_EOF()) {
            if(decoderTask.getFileFlag()){
                decode(seiInfo,frameNumber,pCodecCtx,executorService);
            }else {
                throw new NeedRetryException("av_read_frame res "+ ret);
            }
        }
        log.warn("video split task[{}] run finished", JSONObject.toJSONString(decoderTask));
    } catch (NeedRetryException needRetryException) {
        throw needRetryException;
    } catch (Exception e) {
        log.error("video split  bizId = {}, error[{}]", decoderTask.getBizId(), e.getMessage());
    } finally {
        release(true, packet, null, pCodecCtx, pFormatCtx, null, null);
    }
}


private AVFormatContext getFormatContext(String url, AVDictionary avDictionary) {
    AVFormatContext pFormatCtx = new AVFormatContext(null);

    if (avformat_open_input(pFormatCtx, url, null, avDictionary) != 0) {
        log.error("open media stream has error");
        throw new NeedRetryException("open media stream has error");
    }

    if (avformat_find_stream_info(pFormatCtx, (PointerPointer<Pointer>) null) < 0) {
        log.error("avformat_find_stream_info has error");
        throw new NeedRetryException("read media stream has error");
    }
    return pFormatCtx;
}

public static int getVideoStreamIndex(AVFormatContext pFormatCtx) {
    int videoStream = -1;
    for (int i = 0; i < pFormatCtx.nb_streams(); i++) {
        if (pFormatCtx.streams(i).codecpar().codec_type() == AVMEDIA_TYPE_VIDEO) {
            videoStream = i;
            break;
        }
    }
    return videoStream;
}


public static AVCodecContext getCodecContext(AVFormatContext pFormatCtx, int videoStreamIndex,Boolean useGpu,AVDictionary dictionary) {
    AVCodec pCodec;

    AVCodecContext pCodecCtx = avcodec_alloc_context3(null);
    avcodec_parameters_to_context(pCodecCtx, pFormatCtx.streams(videoStreamIndex).codecpar());

    if(useGpu){
        int codecId = pCodecCtx.codec_id();
        if(codecId == AV_CODEC_ID_H264){
            pCodec = avcodec_find_decoder_by_name("h264_cuvid");
        }else if (codecId == AV_CODEC_ID_H265) {
            pCodec=  avcodec_find_decoder_by_name("hevc_cuvid");
        }else {
            pCodec = avcodec_find_decoder(pCodecCtx.codec_id());
        }
    }else {
        pCodec = avcodec_find_decoder(pCodecCtx.codec_id());
    }

    if (pCodec == null) {
        return null;
    }
    if (avcodec_open2(pCodecCtx, pCodec,dictionary) < 0) {
        return null;
    }

    return pCodecCtx;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants