ffmpeg 编码摄像机H264流

.h
#pragma once

#include "headers.h"

extern "C"
{
#include <libavcodec/avcodec.h>
#include "libavformat/avformat.h"
#include "libavutil/avutil.h"
#include "libswscale/swscale.h"
}

class CX264Encoder
{
public:
	CX264Encoder();
	virtual ~CX264Encoder();

public:
	bool InitEncoder(int nWidth, int nHeight, int nRate, int nFps);
	void UninitEncoder();

	// *pOutSize > 0  ==> success
	void Encode(BYTE* pInBuf, BYTE** ppOutBuf, int* pOutSize);

protected:
	AVFrame*		m_pRGBFrame;
	AVFrame*		m_pYUVFrame;
	AVCodecContext*	m_pCtx;
	AVCodec*		m_pCodecH264;
	SwsContext*		m_pSwsCtx;

	BYTE*			m_pYUVBuf;

	BYTE*			m_pOutBuf;
	int				m_nOutSize;
};


#include "X264Encoder.h"

#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "swscale.lib")

CX264Encoder::CX264Encoder()
{
	m_pRGBFrame = NULL;
	m_pYUVFrame = NULL;
	m_pCtx = NULL;
	m_pCodecH264 = NULL;
	m_pSwsCtx = NULL;
	m_pYUVBuf = NULL;
	m_pOutBuf = NULL;
	m_nOutSize = 0;
}

CX264Encoder::~CX264Encoder()
{
	UninitEncoder();
}

bool CX264Encoder::InitEncoder(int nWidth, int nHeight, int nRate, int nFps)
{
	avcodec_init();

	av_register_all();

	avcodec_register_all();

	m_pRGBFrame = avcodec_alloc_frame();
	m_pYUVFrame = avcodec_alloc_frame();
	if (!m_pRGBFrame || !m_pYUVFrame)
		return false;

	m_pCodecH264 = avcodec_find_encoder(CODEC_ID_H264);
	if (!m_pCodecH264)
		return false;

	m_pCtx = avcodec_alloc_context();
	if (!m_pCtx)
		return false;

	m_pCtx->bit_rate = nRate;
	m_pCtx->width = nWidth;
	m_pCtx->height = nHeight;
	m_pCtx->time_base.num = 1;
	m_pCtx->time_base.den = nFps;
	m_pCtx->gop_size = 10;		// 至少获取 10 帧编码才成功
	m_pCtx->max_b_frames = 1;
	m_pCtx->thread_count = 1;
	m_pCtx->pix_fmt = PIX_FMT_YUV420P;

	if (avcodec_open(m_pCtx, m_pCodecH264) < 0)
		return false;

	int nYUVSize = (nWidth * nHeight * 3) / 2;
	m_pYUVBuf = (BYTE*)malloc(nYUVSize);
	if (!m_pYUVBuf)
		return false;

	m_nOutSize = nWidth * nHeight * 3;
	m_pOutBuf = (BYTE*)malloc(m_nOutSize);
	if (!m_pOutBuf)
		return false;

	// 格式转换初始化 BGR -> YUV
	m_pSwsCtx = sws_getContext(
		nWidth, nHeight, PIX_FMT_BGR24/*PIX_FMT_RGB24*/,
		nWidth, nHeight, PIX_FMT_YUV420P,
		SWS_POINT, NULL, NULL, NULL);
	if (!m_pSwsCtx)
		return false;

	return true;

}

void CX264Encoder::UninitEncoder()
{
	if (m_pRGBFrame)
	{
		av_free(m_pRGBFrame);
		m_pRGBFrame = NULL;
	}

	if (m_pYUVFrame)
	{
		av_free(m_pYUVFrame);
		m_pYUVFrame = NULL;
	}

	if (m_pYUVBuf)
	{
		free(m_pYUVBuf);
		m_pYUVBuf = NULL;
	}

	if (m_pOutBuf)
	{
		free(m_pOutBuf);
		m_pOutBuf = NULL;
	}

	if (m_pCtx)
	{
		avcodec_close(m_pCtx);
		av_free(m_pCtx);
		m_pCtx = NULL;
	}
}

void  CX264Encoder::Encode(BYTE* pInBuf, BYTE** ppOutBuf, int* pOutSize)
{
	*ppOutBuf = NULL;
	*pOutSize = 0;

	int nWidth = m_pCtx->width;
	int nHeight = m_pCtx->height;

	avpicture_fill((AVPicture*)m_pRGBFrame, (uint8_t*)pInBuf, PIX_FMT_BGR24/*PIX_FMT_RGB24*/, nWidth, nHeight);
	avpicture_fill((AVPicture*)m_pYUVFrame, (uint8_t*)m_pYUVBuf, PIX_FMT_YUV420P, nWidth, nHeight);

	// BGR -> RGB
	/*m_pRGBFrame->data[0] += m_pRGBFrame->linesize[0] * (nHeight - 1);
	m_pRGBFrame->linesize[0] *= -1;
	m_pRGBFrame->data[1] += m_pRGBFrame->linesize[1] * (nHeight / 2 - 1);
	m_pRGBFrame->linesize[1] *= -1;
	m_pRGBFrame->data[2] += m_pRGBFrame->linesize[2] * (nHeight / 2 - 1);
	m_pRGBFrame->linesize[2] *= -1;*/

	// RGB -> YUV
	sws_scale(m_pSwsCtx, m_pRGBFrame->data, m_pRGBFrame->linesize, 0, nHeight, m_pYUVFrame->data, m_pYUVFrame->linesize);

	// YUV -> H264
	*pOutSize = avcodec_encode_video(m_pCtx, m_pOutBuf, m_nOutSize, m_pYUVFrame);
	*ppOutBuf = m_pOutBuf;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值