ffmpeg缩放和格式转换yuv数据

ffmpeg缩放和格式转换yuv数据


下面代码是实现用ffmpeg将yuv的宽高或者yuv格式变更的代码。
例如:352*288->720*576(采用双三次或双线性差值),yuv420p->yuv422p

int VideoScaleYuvZoom(int Is_flip,int in_width ,int in_height,int in_pix_fmt ,
					  int out_width ,int out_height,int out_pix_fmt,uint8_t * buf)
{
	//
	AVFrame * pInputFrame = NULL;
	AVFrame * pOutputFrame = NULL;
	static int sws_flags = SWS_BICUBIC; //差值算法,双三次
	struct SwsContext * img_convert_ctx = NULL;
	uint8_t * m_pVideoOutput_ZoomBuf = NULL;
	int m_pVideoOutput_Zoomsize = 0;

	//分配一个AVFrame并设置默认值-输入
	pInputFrame = avcodec_alloc_frame(); 
	if (pInputFrame == NULL)
	{
		printf("分配pInputFrame 帧失败\n");
		return -1;
	}

	//分配一个AVFrame并设置默认值-输出
	pOutputFrame = avcodec_alloc_frame(); 
	if (pOutputFrame == NULL)
	{
		printf("分配picture 帧失败\n");
		return -1;
	}
	m_pVideoOutput_Zoomsize = avpicture_get_size((AVPixelFormat)out_pix_fmt, out_width,out_height);
	m_pVideoOutput_ZoomBuf =( uint8_t *)calloc(1,m_pVideoOutput_Zoomsize * 3 * sizeof(char)); //最大分配的空间,能满足yuv的各种格式
	avpicture_fill((AVPicture *)pOutputFrame, (unsigned char *)m_pVideoOutput_ZoomBuf, (AVPixelFormat)out_pix_fmt,out_width, out_height); //内存关联

	//设置转换context
	if (img_convert_ctx == NULL)   
	{
		img_convert_ctx = sws_getContext(in_width, in_height, 
			(AVPixelFormat)in_pix_fmt,
			out_width, 
			out_height,
			(AVPixelFormat)out_pix_fmt,
			sws_flags, NULL, NULL, NULL);
		if (img_convert_ctx == NULL)
		{
			fprintf(stderr, "Cannot initialize the conversion context\n");
			return -1;
		}
	}
	//
	//开始转换
	avpicture_fill((AVPicture *)pInputFrame, (unsigned char *)buf, (AVPixelFormat)in_pix_fmt,in_width, in_height); //内存关联

	//摄像头图像倒置问题
	if (Is_flip)
	{
		if ((AVPixelFormat)in_pix_fmt == AV_PIX_FMT_BGR24 ||  //RGB系列的
			(AVPixelFormat)in_pix_fmt ==  AV_PIX_FMT_RGB24)
		{
			pInputFrame->data[0] += pInputFrame->linesize[0]*(in_height -1);
			pInputFrame->linesize[0] *= -1;
		}
		else if ((AVPixelFormat)in_pix_fmt == AV_PIX_FMT_YUV420P) //yuv420系列
		{
			pInputFrame->data[0] += pInputFrame->linesize[0]*(in_height -1);
			pInputFrame->linesize[0] *= -1;
			pInputFrame->data[1] += pInputFrame->linesize[1]*(in_height/2 -1);
			pInputFrame->linesize[1] *= -1;
			pInputFrame->data[2] += pInputFrame->linesize[2]*(in_height/2 -1);
			pInputFrame->linesize[2] *= -1;
		}
		else
		{
				//可扩展
		}
	}

	sws_scale(img_convert_ctx, pInputFrame->data, pInputFrame->linesize,         
		0, in_height, pOutputFrame->data, pOutputFrame->linesize);

	//将新转换的视频返回
	memcpy(buf,m_pVideoOutput_ZoomBuf,m_pVideoOutput_Zoomsize);

	//
	if (pInputFrame)
	{
		avcodec_free_frame(&pInputFrame);
		pInputFrame = NULL;
	}
	if (pOutputFrame)
	{
		avcodec_free_frame(&pOutputFrame);
		pOutputFrame = NULL;
	}
	if (m_pVideoOutput_ZoomBuf)
	{
		free(m_pVideoOutput_ZoomBuf);
	}
	if (img_convert_ctx)
	{
		sws_freeContext(img_convert_ctx);
		img_convert_ctx = NULL;
	}
	//
	return m_pVideoOutput_Zoomsize;
}

交流请加QQ群:62054820
QQ:379969650

你可能感兴趣的:(ffmpeg,朱韦刚的流媒体技术专栏)