【obs-studio开源项目从入门到放弃】obs高级输出内存泄露

文章目录

    • 前言
    • FFmpeg高级输出内存泄露
    • 内存泄露原因
    • 解决办法


前言

obs系列文章入口:obs-studio项目简介和架构

FFmpeg高级输出内存泄露

已解决
PR: obs-ffmpeg: Fix ffmpeg_output memory leak

obs高级输出的介绍: 【obs-studio开源项目从入门到放弃】obs 的高级输出 ffmpeg-output

最近长时间推流测试发现,obs的高级输出存在内存泄露。泄露速度不是很快,大约每分钟泄露1M多内存,12个小时泄露700多M。但是如果长时间录制或者使用FFmpeg高级输出推流,会因内存泄露导致崩溃。

【obs-studio开源项目从入门到放弃】obs高级输出内存泄露_第1张图片

内存泄露原因

obs-ffmpeg-output.c 在 receive_video()receive_audio() 都调用了av_packet_alloc() 来申请 AVPacket 内存空间,但是在process_packet() 使用完 AVpacket后,并没有调用 av_packet_free() 来释放内存,因此会产生内存泄露。

解决办法

修改源码 obs-ffmpeg-output.c av_interleaved_write_frame 使用完 packet后,调用 av_packet_free() 释放 packet的内存。

static int process_packet(struct ffmpeg_output *output)
{
	AVPacket *packet;
	bool new_packet = false;
	int ret;

	pthread_mutex_lock(&output->write_mutex);
	if (output->packets.num) {
		packet = output->packets.array[0];
		da_erase(output->packets, 0);
		new_packet = true;
	}
	pthread_mutex_unlock(&output->write_mutex);

	if (!new_packet)
		return 0;

	/*blog(LOG_DEBUG, "size = %d, flags = %lX, stream = %d, "
			"packets queued: %lu",
			packet.size, packet.flags,
			packet.stream_index, output->packets.num);*/

	if (stopping(output)) {
		uint64_t sys_ts = get_packet_sys_dts(output, packet);
		if (sys_ts >= output->stop_ts)
			return 0;
	}

	output->total_bytes += packet->size;

	ret = av_interleaved_write_frame(output->ff_data.output, packet);
	if (ret < 0) {
		//av_packet_free(&packet); //此处注释掉
		ffmpeg_log_error(LOG_WARNING, &output->ff_data,
				 "process_packet: Error writing packet: %s",
				 av_err2str(ret));
		return ret;
	}
	//=== 解决内存泄露:释放 packet 内存===
	av_packet_free(&packet);
	//===================================

	return 0;
}

av_packet_alloc 和 av_packet_free 源码

/**
 * Allocate an AVPacket and set its fields to default values.  The resulting
 * struct must be freed using av_packet_free().
 *
 * @return An AVPacket filled with default values or NULL on failure.
 *
 * @note this only allocates the AVPacket itself, not the data buffers. Those
 * must be allocated through other means such as av_new_packet.
 *
 * @see av_new_packet
 */
AVPacket *av_packet_alloc(void)
{
    AVPacket *pkt = av_malloc(sizeof(AVPacket));
    if (!pkt)
        return pkt;

    get_packet_defaults(pkt);

    return pkt;
}

/**
 * Free the packet, if the packet is reference counted, it will be
 * unreferenced first.
 *
 * @param pkt packet to be freed. The pointer will be set to NULL.
 * @note passing NULL is a no-op.
 */
void av_packet_free(AVPacket **pkt)
{
    if (!pkt || !*pkt)
        return;

    av_packet_unref(*pkt);
    av_freep(pkt);
}

你可能感兴趣的:(obs-studio入门到放弃,音视频)