ffmpeg 解码摄像机H264流

.h:

#pragma once

#include "headers.h"

// #define _SDL_config_win32_h

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

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


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

public:
	bool InitDecoder(int nWidth, int nHeight, int nRate, int nFps);
	void UninitDecoder();

	void Decode(BYTE* pInBuf, int nInSize, BYTE** ppOutBuf, int* pOutSize, int* pWidth, int* pHeight);

protected:
	bool				m_bInit;

	AVCodec*			m_pCodecH264;
	AVCodecContext*		m_pCodecCtx;

	AVFrame*			m_pYUVFrame;
	AVFrame*			m_pRGBFrame;

	BYTE*				m_pOutBuf;
	int					m_nOutSize;
};

#include "X264Decoder.h"

CX264Decoder::CX264Decoder()
{
	m_bInit = false;

	m_pCodecH264 = NULL;
	m_pCodecCtx = NULL;
	m_pYUVFrame = NULL;
	m_pRGBFrame = NULL;
	m_pOutBuf = NULL;
	m_nOutSize = 0;
}

CX264Decoder::~CX264Decoder()
{
	UninitDecoder();
}

bool CX264Decoder::InitDecoder(int nWidth, int nHeight, int nRate, int nFps)
{
	if (m_bInit)
		return true;

	avcodec_init();

	av_register_all();

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

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

	m_pCodecCtx->time_base.num = 1;
	m_pCodecCtx->time_base.den = nFps;
	m_pCodecCtx->bit_rate = nRate;
	m_pCodecCtx->frame_number = 1;
	m_pCodecCtx->codec_type = CODEC_TYPE_VIDEO;
	m_pCodecCtx->width = nWidth;
	m_pCodecCtx->height = nHeight;
	//m_pCodecCtx->pix_fmt = PIX_FMT_RGB24;

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

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

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

	m_bInit = true;

	return true;
}

void CX264Decoder::UninitDecoder()
{
	if (m_pOutBuf)
	{
		free(m_pOutBuf);
		m_pOutBuf = NULL;
	}

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

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

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

	m_bInit = false;
}

void CX264Decoder::Decode(BYTE* pInBuf, int nInSize, BYTE** ppOutBuf, int* pOutSize, int* pWidth, int* pHeight)
{
	*ppOutBuf = NULL;

	if (!m_bInit) return;

	if (!pInBuf || nInSize <= 0)
		return;

	int nGotSize = 0;
	avcodec_decode_video(m_pCodecCtx, m_pYUVFrame, &nGotSize, pInBuf, nInSize);
	if (nGotSize <= 0)
		return;

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

	// calculate size
	//int nShift = 0;
	//int nOffset = 0;
	//int nLen = 0;
	//for (int i=0; i<3; ++i)
	//{
	//	nShift = (0 == i) ? 0 : 1;
	//	
	//	nOffset = m_pCodecCtx->height >> nShift;
	//	for (int j=0; j<nOffset; ++j)
	//		nLen += nOffset;
	//}

	// make sure that memory is enough
	int nNumBytes = avpicture_get_size(/*PIX_FMT_RGB24*/PIX_FMT_BGR24, nWidth, nHeight);
	if (nNumBytes > m_nOutSize)
	{
		if (m_pOutBuf)
		{
			free(m_pOutBuf);
			m_pOutBuf = NULL;
		}
		m_pOutBuf = (BYTE*)malloc(nNumBytes);
		if (!m_pOutBuf) return;

		m_nOutSize = nNumBytes;
	}

	if (!m_pOutBuf) return;

	memset(m_pOutBuf, 0, m_nOutSize);

	// to RGB24
	avpicture_fill((AVPicture*)m_pRGBFrame, m_pOutBuf, /*PIX_FMT_RGB24*/PIX_FMT_BGR24, nWidth, nHeight);
	SwsContext* pSwsCtx = sws_getContext(
		nWidth, nHeight, m_pCodecCtx->pix_fmt, 
		nWidth, nHeight, /*PIX_FMT_RGB24*/PIX_FMT_BGR24,
		SWS_BICUBIC, NULL, NULL, NULL);
	if (!pSwsCtx) return;

	sws_scale(pSwsCtx, m_pYUVFrame->data, m_pYUVFrame->linesize, 0, nHeight,
		m_pRGBFrame->data, m_pRGBFrame->linesize);

	sws_freeContext(pSwsCtx);

	*ppOutBuf = m_pOutBuf;
	*pOutSize = nNumBytes;
	*pWidth = nWidth;
	*pHeight = nHeight;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值