利用ffmpeg解码h264流的代码

这里也直接给出代码:

h264dec.h:

#pragma once
#include "tdll.h"
#include "avcodec.h"
#include "postprocess.h"
//#include "EMVideoCodec.h"

class h264dec /*: public IH264Decoder*/
{
public:
	virtual bool InitH264Deocder(int width,int height);
	virtual bool H264Decode(unsigned char * inbuf, const int & inlen,unsigned char * outbuf,int & outlen);
	virtual void StopH264Decoder();
	virtual void ReleaseConnection();

public:
	h264dec(void);
	virtual ~h264dec(void);
private:
	Tdll *dll;

	bool LoadDllFun();
	void (*avcodec_init)(void);
	void (*avcodec_register_all)(void);
	AVCodecContext* (*avcodec_alloc_context)(void);
	AVFrame* (*avcodec_alloc_frame)(void);
	AVCodec *(*avcodec_find_decoder)(enum CodecID id);
	int (*avcodec_decode_video)(AVCodecContext *avctx, AVFrame *picture,int *got_picture_ptr,
								uint8_t *buf, int buf_size);
	int  (*avcodec_open)(AVCodecContext *avctx, AVCodec *codec);
	int  (*avcodec_close)(AVCodecContext *avctx);
	void (*av_free)(void *ptr);		
	
	bool InitPostproc(int w,int h);
	void ClosePostproc();
	pp_context_t *(*pp_get_context)(int width, int height, int flags);
	void (*pp_free_context)(pp_context_t *ppContext);
	void (*pp_free_mode)(pp_mode_t *mode);
	pp_mode_t *(*pp_get_mode_by_name_and_quality)(char *name, int quality);
	void  (*pp_postprocess)(uint8_t * src[3], int srcStride[3],
                 uint8_t * dst[3], int dstStride[3],
                 int horizontalSize, int verticalSize,
                 QP_STORE_T *QP_store,  int QP_stride,
		 pp_mode_t *mode, pp_context_t *ppContext, int pict_type);
private:
    AVCodec			*pdec;
    AVCodecContext	*pdecContext;
    AVFrame			*pdecFrame;
	int				m_width;
	int				m_height;

	Tdll* prodll;
    pp_context_t *pp_context;
    pp_mode_t    *pp_mode;
};

h264dec.cpp:

#include "StdAfx.h"
#include ".\h264dec.h"

h264dec::h264dec(void)
:dll(NULL)
,pdec(NULL)
,pdecContext(NULL)
,pdecFrame(NULL)
,pp_context(NULL)
,pp_mode(NULL)
,prodll(NULL)
{
}

h264dec::~h264dec(void)
{
}

bool h264dec::LoadDllFun()
{
	dll=new Tdll(L"libavcodec.dll");
	dll->loadFunction((void**)&avcodec_init,"avcodec_init");
	dll->loadFunction((void**)&avcodec_register_all,"avcodec_register_all");
	dll->loadFunction((void**)&avcodec_alloc_context,"avcodec_alloc_context");
	dll->loadFunction((void**)&avcodec_alloc_frame,"avcodec_alloc_frame");
	dll->loadFunction((void**)&avcodec_find_decoder,"avcodec_find_decoder");
	dll->loadFunction((void**)&avcodec_open,"avcodec_open");	
	dll->loadFunction((void**)&avcodec_decode_video,"avcodec_decode_video");
	dll->loadFunction((void**)&avcodec_close,"avcodec_close");
	dll->loadFunction((void**)&av_free,"av_free");
	if (!dll->ok)
		return false;

	prodll = new Tdll(L"postproc.dll");
	prodll->loadFunction((void**)&pp_get_context,"pp_get_context");
	prodll->loadFunction((void**)&pp_free_context,"pp_free_context");
	prodll->loadFunction((void**)&pp_free_mode,"pp_free_mode");
	prodll->loadFunction((void**)&pp_get_mode_by_name_and_quality,"pp_get_mode_by_name_and_quality");
	prodll->loadFunction((void**)&pp_postprocess,"pp_postprocess");
	if(!prodll->ok)
		return false;

	avcodec_init();
	avcodec_register_all();
	return true;
}

bool h264dec::InitH264Deocder(int width,int height)
{
	if(!LoadDllFun())
		return false;
	if(!InitPostproc(width,height))
		return false;

	m_width=width;
	m_height=height;
	pdec = avcodec_find_decoder(CODEC_ID_H264);
	if (pdec == NULL )  
		return false;

	pdecContext = avcodec_alloc_context();
	pdecFrame = avcodec_alloc_frame();

	pdecContext->width  = width;
	pdecContext->height = height;
	pdecContext->pix_fmt = PIX_FMT_YUV420P;
	/* open it */
	if (avcodec_open(pdecContext, pdec) < 0) 
	{
		return false;
	}
	return true;
}

bool h264dec::InitPostproc(int w,int h)
{
	int i_flags = 0;
    i_flags |= PP_CPU_CAPS_MMX | PP_CPU_CAPS_MMX2 | PP_FORMAT_420;
    pp_context = pp_get_context( w, h, i_flags );
	if(!pp_context)
		return false;
    pp_mode = pp_get_mode_by_name_and_quality( "default", 6 );
	if(!pp_mode)
		return false;
	return true;
}

bool h264dec::H264Decode(unsigned char * inbuf, const int & inlen,unsigned char * outbuf,int & outlen)
{
	int got_frame;
	BYTE* showImage[3];
	int showheight[3],showLx[3];

    int len;
	len=avcodec_decode_video(pdecContext, pdecFrame, &got_frame, inbuf, inlen);
	if(len < 0)
		return false;

	if(got_frame)
	{
		showImage[0]=outbuf;
		showImage[1]=showImage[0]+m_width*m_height;
		showImage[2]=showImage[1]+m_width*m_height/4;
		showLx[0]=m_width;showLx[1]=m_width>>1;showLx[2]=m_width>>1;
		showheight[0]=m_height;showheight[1]=m_height>>1;showheight[2]=m_height>>1;
		pp_postprocess(pdecFrame->data,pdecFrame->linesize,showImage,showLx,m_width,m_height,pdecFrame->qscale_table,
			pdecFrame->qstride,pp_mode,pp_context,pdecFrame->pict_type);
		//GetImage(	pdecFrame->data,
		//			showImage,
		//			pdecFrame->linesize,
		//			showLx,
		//			showheight);
		outlen=m_width*m_height*3/2;
	}
	else
	{
		outlen = 0;
	}

	return true;
}

void h264dec::StopH264Decoder()
{
	if (pdecContext != NULL) 
	{     
		avcodec_close(pdecContext);
		av_free( pdecContext );
		pdecContext = NULL;
		if(pdecFrame){
			av_free(pdecFrame);
			pdecFrame = NULL;
		}
	}
	if(dll){
		delete dll;
		dll=0;
	}

	ClosePostproc();
}

void h264dec::ClosePostproc()
{
	if(pp_mode){
		pp_free_mode( pp_mode );
		pp_mode=0;
	}
	if(pp_context){
		pp_free_context(pp_context);
		pp_context=0;
	}
	if(prodll){
		delete prodll;
		prodll=0;
	}
}

void h264dec::ReleaseConnection()
{
	delete this;
}

tdll.h:

#ifndef _TDLL_
#define _TDLL_

class Tdll
{
private:
	HMODULE hdll;
	void loadDll(const char *dllName);
public:
	bool ok;
	Tdll(const TCHAR *dllName1)
	{
		hdll=LoadLibrary(dllName1);
		if (!hdll)
		{
			hdll=NULL;
		}
		ok=(hdll!=NULL);
	};
	~Tdll()
	{
		if (hdll)
			FreeLibrary(hdll);
	}
	void loadFunction(void **fnc,const char *name)
	{
		*fnc=GetProcAddress(hdll,name);
		ok&=(*fnc!=NULL);
	};
};  

#endif

main.cpp:

#include "stdafx.h"
#include "h264dec.h"
#include "postprocess.h"

#define INBUF_SIZE 100 * 1024;


static int FindStartCode (unsigned char *Buf, int zeros_in_startcode)
{
	int info;
	int i;

	info = 1;
	for (i = 0; i < zeros_in_startcode; i++)
	{
		if(Buf[i] != 0)
			info = 0;
	}

	if(Buf[i] != 1)
		info = 0;
	return info;
}

static bool Check_StartCode(unsigned char *Buf, int pos)
{
	int info3 = 0;

	info3 = FindStartCode(&Buf[pos-4], 3);
	return info3 == 1;

}

static int getNextNal(FILE* inpf, unsigned char* Buf)
{
	int pos = 0;
	int StartCodeFound = 0;
	int info2 = 0;
	int info3 = 0;

	int nCount = 0;
	while(!feof(inpf) && ++nCount <= 4)
	{
		Buf[pos++]=fgetc(inpf);
	}

	if(!Check_StartCode(Buf, pos))
	{
		return 0;
	}


	while(!feof(inpf) && (Buf[pos++]=fgetc(inpf))==0);

	while (!StartCodeFound)
	{
		if (feof (inpf))
		{
			//			return -1;
			return pos-1;
		}
		Buf[pos++] = fgetc (inpf);

		StartCodeFound = Check_StartCode(Buf, pos);
	}

	fseek (inpf, -4, SEEK_CUR);
	return pos - 4;
}

int main(int argc, char* argv[])
{
	if (argc != 5)
	{
		printf("please input: PP_Demo.exe filename1[input] Width Height filename2[output]\n");
	}
	
	//params set
	unsigned short usWidth = atoi(argv[2]);
	unsigned short usHeight = atoi(argv[3]);
	
	//create dec&pp
	h264dec *pdec = new h264dec;
	if(!pdec->InitH264Deocder(usWidth, usHeight))
	{
		return false;
	}



	unsigned char *p_In_Frame = new unsigned char[usWidth * usHeight * 3/2];
	unsigned char *p_Out_Frame = new unsigned char[usWidth * usHeight * 3/2];
	FILE* ifp = fopen(argv[1],"rb");
	FILE* ofp = fopen(argv[4],"wb");

	bool b_continue = true;
	int nReadUnit = usWidth * usHeight * 3/2;
	while(!feof(ifp))
	{
		int nCount = getNextNal(ifp, p_In_Frame);

		if(nCount == 0)
		{
			continue;
		}
		
		unsigned char *ptr = p_In_Frame;
		int n_Outlen = 0;
		pdec->H264Decode(ptr, nCount, p_Out_Frame, n_Outlen);
		
		if(n_Outlen > 0)
		{
			fwrite(p_Out_Frame, 1, n_Outlen, ofp);
		}
	}


	//realse
	delete []p_In_Frame;
	delete []p_Out_Frame;
	pdec->StopH264Decoder();
	pdec->ReleaseConnection();
	fclose(ifp);
	fclose(ofp);

	return 0;
}

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
FFmpeg是一个强大的多媒体处理框架,它可以用于视频和音频的编码、解码处理等任务。H264是常见的视频编码标准,而GDR(Graphics Device Render)通常指的是GPU加速解码。在FFmpeg中,如果你想要使用GPU进行H264解码,你需要利用FFmpeg中的硬件加速功能,如libavcodec中的H264 decoder和libavfilter中的GPU filters。 以下是一个简单的示例,展示如何在FFmpeg中使用GDR解码H264视频: ```cpp #include <ffplay.h> // 包含FFmpeg的播放器API int main(int argc, char** argv) { AVFormatContext* ctx = NULL; AVPacket pkt; AVStream* stream; AVCodecContext* codec_ctx; AVFrame frame; // 初始化FFmpeg av_register_all(); avformat_network_init(); // 打开输入文件 if (argc != 2) { fprintf(stderr, "Usage: %s <input_file>\n", argv); return 1; } if (avformat_open_input(&ctx, argv, NULL, NULL) != 0) { perror("Opening file"); return 1; } // 查找H264视频 for (int i = 0; i < ctx->nb_streams; i++) { stream = ctx->streams[i]; if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO && stream->codec->codec_id == AV_CODEC_ID_H264) { break; } } // 获取视频解码上下文 codec_ctx = stream->codec; // 启动解码器 if (avcodec_open2(codec_ctx, NULL, NULL) < 0) { perror("Opening codec"); return 1; } // 初始化帧 av_frame_alloc(&frame); // 创建一个FFmpeg播放器实例 FFPacketContext packet_ctx; FFParseContext parse_ctx; av_register_all(); ff_parse_init(&parse_ctx); avformat_network_init(); FFParseAVFormatContext parse_ctx_with_format = { .avformat_ctx = ctx }; // 进入主循环 while (1) { // 从输入读取数据 if (av_read_frame(ctx, &pkt) >= 0) { // 使用GPU解码 if (avcodec_decode_video2(codec_ctx, &frame, &pkt.isAccepted, &pkt) == 0) { // 处理解码后的帧 // frame data can be accessed here } else { printf("Error decoding frame\n"); } av_packet_unref(&pkt); } else { if (pkt.data) av_free(pkt.data); break; } } // 关闭资源 avcodec_close(codec_ctx); avformat_close_input(&ctx); av_frame_free(&frame); return 0; } ```
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值