ffmpeg的那些事儿

今天在做编解码时,遇到一个奇怪的问题,就是av_image_alloc 导致内存泄漏,这点比较纳闷,场景是这样的,在视频传输过程中,需要根据网速来切换码流大小哦,如果带宽不够自动切换低码流传输,于是我将采集的1080p的视频转化成yuv格式发送。

过程如下:

首先初始化编解码环境:

	if (_thumbCodecContext != nullptr && _thumbCodec != nullptr)
	{
		return 0;
	}
	int ret;
	AVCodecID codec_id = AV_CODEC_ID_MJPEG;
	int in_w = width, in_h = height;
	_width = width;
	_height = height;
	int framenum = 1;

	_thumbCodec = avcodec_find_encoder(codec_id);
	if (!_thumbCodec) {
		return 40;
	}
	_thumbCodecContext = avcodec_alloc_context3(_thumbCodec);
	if (!_thumbCodecContext) {
		return 40;
	}
	_thumbCodecContext->bit_rate = 1024 *1024 * 10;
	_thumbCodecContext->width = scaleWidth;
	_thumbCodecContext->height = scaleHeight;
	_thumbCodecContext->time_base.num = 1;
	_thumbCodecContext->time_base.den = 11;
	_thumbCodecContext->gop_size = 10;
	_thumbCodecContext->qcompress = 0.1;

	_thumbCodecContext->pix_fmt = AV_PIX_FMT_YUVJ420P;


	if (avcodec_open2(_thumbCodecContext, _thumbCodec, NULL) < 0) {
		return 40;
	}

	
	_pktJPG = av_packet_alloc();
	_thumbSwsContext = sws_getContext(in_w, in_h, AV_PIX_FMT_BGRA, _thumbCodecContext->width, _thumbCodecContext->height, AV_PIX_FMT_YUVJ420P, SWS_BICUBIC, NULL, NULL, NULL);
	return 0;

然后进行视频的缩放以及编码:

	static int pts = 1;
	if (pts > 65535)
	{
		pts = 1;
	}
//	AVPacket *pkt = av_packet_alloc();
//	avcodec_open2(_thumbCodecContext, _thumbCodec, nullptr);
//	av_init_packet(_pktJPG);
//	_pktJPG->data = nullptr;
//	_pktJPG->size = 0;
	int ret = 0;
	AVFrame*  _frameJPG = av_frame_alloc();
	if (!_frameJPG) {
		std::cout << "the frame jpg alloc is failure " << pts << " " << endl;

		return 40;
	}
	_frameJPG->format = _thumbCodecContext->pix_fmt;
	_frameJPG->width = _thumbCodecContext->width;
	_frameJPG->height = _thumbCodecContext->height;

	av_frame_get_buffer(_frameJPG, 1);

	/*ret = av_image_alloc(_frameJPG->data, _frameJPG->linesize, _thumbCodecContext->width, _thumbCodecContext->height,
		_thumbCodecContext->pix_fmt, 16);
	if (ret < 0) {
		std::cout << "the frame jpg data alloc is failure " << pts << " " << endl;

		return 40;
	}*/

	//AVFrame *_frameRGB = av_frame_alloc();
	//if (!_frameRGB) {
	//	std::cout << "the frame rgb alloc is failure " << pts << " " << endl;

	//	return 40;
	//}
	//_frameRGB->format = AV_PIX_FMT_BGRA;
	//_frameRGB->width = _width;
	//_frameRGB->height = _height;

	//ret = av_image_alloc(_frameRGB->data, _frameRGB->linesize, _width, _height,
	//	AV_PIX_FMT_BGRA, 32);

	//if (ret < 0) {
	//	std::cout << "the frame rgb data alloc is failure " << pts << " " << endl;

	//	return 40;
	//}
	//int file_size = 0;
	//_frameRGB->data[0] = (unsigned char *)src;
	//_frameRGB->data[0] += _frameRGB->linesize[0] * (_height - 1);
	//_frameRGB->linesize[0] *= -1;
	//_frameRGB->data[1] += _frameRGB->linesize[1] * (_height / 2 - 1);
	//_frameRGB->linesize[1] *= -1;
	//_frameRGB->data[2] += _frameRGB->linesize[2] * (_height / 2 - 1);
	//_frameRGB->linesize[2] *= -1;
	unsigned char *srcBuff[4] = { (unsigned char *)src,nullptr,nullptr,nullptr };
	int srcStride[4] = { 4 * _width,0,0,0 };
	sws_scale(_thumbSwsContext, (const uint8_t* const*)srcBuff, srcStride, 0, _height, _frameJPG->data, _frameJPG->linesize);

	_frameJPG->pts = pts++;
	avcodec_send_frame(_thumbCodecContext, _frameJPG);
	ret = avcodec_receive_packet(_thumbCodecContext, _pktJPG);
	if (ret < 0) {
		std::cout << "the frame jpg encode is failure " << pts << " " << endl;

		return 40;
	}
	size = _pktJPG->size;

	//
	memcpy(dst, _pktJPG->data, size);
//	av_freep(pkt);
	av_packet_unref(pkt);
	av_frame_unref(_frameJPG);
//	av_frame_unref(_frameRGB);
//	avcodec_close(_thumbCodecContext);
	av_frame_free(&_frameJPG);
//	av_frame_free(&_frameRGB);
//	av_frame_unref(_frameJPG);
//	av_frame_unref(_frameRGB);
	return 0;

这里我先将原来的码流进行缩放,然后进行编码,最后将裸码流拷贝出来即可。

一开始我将AVPacket的申请和管理放在每次编解码的时候,每次都会av_image_alloc后面在进行释放,此时会产生内存泄漏,而且相当大,基本相当于每次的原始码流。

更有奇葩的现象是这样,我将收到的原始裸流放到AVFrame中,通过sws_scale缩放倒另一个待编码AVFrame中,此时进行编码,会产生崩溃。大致意思是coremessaging.dll不能分配更多的内存,然后我直接将原始裸流进行缩放,此现象消失。

第三个问题是这样的,原始裸流存为AVFrame并缩放为目标AVFrame时,经过编码图像倒置。此时必须提前把原始裸流的

_frameRGB->data[0] = (unsigned char *)src;
    //_frameRGB->data[0] += _frameRGB->linesize[0] * (_height - 1);
    //_frameRGB->linesize[0] *= -1;
    //_frameRGB->data[1] += _frameRGB->linesize[1] * (_height / 2 - 1);
    //_frameRGB->linesize[1] *= -1;
    //_frameRGB->data[2] += _frameRGB->linesize[2] * (_height / 2 - 1);
    //_frameRGB->linesize[2] *= -1;

linesize 进行如下的操作,方可恢复正常。是因为rgb本来就是倒置扫描的,此时将linesize进行倒置即可。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值