【AVD】FFmpeg av_packet_unref() 不严谨导致的一次内存泄漏,每次 6MB

391 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

  AVPacket pkt;
  av_init_packet(&pkt);
  while (av_read_frame(format_context_, &pkt) >= 0) {
    if (pkt.stream_index == streamidx) {
      avcodec_send_packet(codec_context_, &pkt);
      while ((ret = avcodec_receive_frame(codec_context_, frame_)) != 0) {
        if (ret == AVERROR_EOF) break;
        avcodec_send_packet(codec_context_, nullptr);
      }
      av_packet_unref(&pkt);
      break;
    } 
  }

这么写有问题吗? 有!严重的内存泄漏。每次循环会有 6MB 内存没有被释放。av_read_frame 会产生 6MB 的堆内存。如果不进行 av_packet_unref,则会导致内存泄漏。即使是同一个栈变量 pkt,即使出了这个栈变量的作用范围、这个栈变量被系统收回,那些每次产生的 6MB 堆内存们,也不会被收回。 泄漏的原因在于,当 ·av_read_frame() < 0 时,它也产生了堆内存,也需要用 av_packet_unref 进行释放;当 pkt.stream_idx != streamidx 时,也需要用 av_packet_unref 进行释放。 所以,正确的写法如下:

  AVPacket pkt;
  av_init_packet(&pkt);
  while (av_read_frame(format_context_, &pkt) >= 0) {
    if (pkt.stream_index == streamidx) {
      avcodec_send_packet(codec_context_, &pkt);
      while ((ret = avcodec_receive_frame(codec_context_, frame_)) != 0) {
        if (ret == AVERROR_EOF) break;
        avcodec_send_packet(codec_context_, nullptr);
      }
      av_packet_unref(&pkt);
      break;
    } else {
      av_packet_unref(&pkt);
    }
  }
  av_packet_unref(&pkt);