首页 > 代码库 > 嵌入式专题: S5PV210 - MFC硬件解码

嵌入式专题: S5PV210 - MFC硬件解码

嵌入式就是瞎折腾。奉献一些过时的代码,让嵌入式的兄弟少折腾一些吧。

 

这一篇是怎么解码的,本篇用的MPEG2VIDEO解码。

头文件

#ifndef _HW_MPV2_DECODER#define _HW_MPV2_DECODERclass HwMpv2Decoder{public:	HwMpv2Decoder();	~HwMpv2Decoder();	int Open(unsigned int width, unsigned int height);	void Close();	int Decode(int keyframe, void* data, int len, void** phyY, void** phyCbCr, bool save);private:	int InitCodec(void* data, int len);private:	void* m_pHandle;	void* m_pVirInBuf; // 解码芯片的缓冲区	int   m_nMaxFrameSize; // 最大的输入帧大小	bool  m_bInitOK;public:	char* pYuvPicture;	int   nYuvSize;	int nImgWidth, nImgHeight;	int nBufWidth, nBufHeight;	//void* pPhyY, *pPhyC; // 初始化时得到的物理地址};#endif


cpp文件

#include <stdio.h>#include <string.h>#include "HwMpv2Decoder.h"#include "../mfc/SsbSipMfcApi.h"#include "../mfc/MfcConvert.h"#include "../osapi/osapi.h"HwMpv2Decoder::HwMpv2Decoder(){	m_pHandle = NULL;}HwMpv2Decoder::~HwMpv2Decoder(){	Close();}int HwMpv2Decoder::Open(unsigned int width, unsigned int height){	// 打开设备	m_pHandle = SsbSipMfcDecOpen();	if(m_pHandle == NULL)	{		gLogger.e("failed to open mfc device!\n");		return -1;	}	m_nMaxFrameSize = 1024 * 1024;	// 获取缓冲区	void* phyInBuf = NULL;	m_pVirInBuf = SsbSipMfcDecGetInBuf(m_pHandle, &phyInBuf, m_nMaxFrameSize);	if(m_pVirInBuf == NULL)	{		gLogger.e("failed to get virtual buffer address!\n");		return -1;	}	// 初始化	unsigned char seqhdr[12] = 		{ 0 ,0 ,1 ,0xB3 ,0x40 ,0x03 ,0x00 ,0x13 ,0xFF ,0xFF ,0xE0 ,0x88};  	seqhdr[4] = width >> 4;	seqhdr[5] = width << 4;	seqhdr[5] +=  height >> 8;	seqhdr[6] = height;	if(InitCodec(seqhdr, sizeof(seqhdr)) < 0)	{		printf("Failed to init hardware codec !\n");		return -1;	}	// 未初化	m_bInitOK = false;	printf("HW decoder init ok !\n");	return 0;}void HwMpv2Decoder::Close(){	if(m_pHandle)	{		// 关闭设备		SsbSipMfcDecClose(m_pHandle);		m_pHandle = NULL;	}}int HwMpv2Decoder::InitCodec(void* data, int len){	gLogger.d("try to init device ...\n");	memcpy (m_pVirInBuf, data, len);	SSBSIP_MFC_ERROR_CODE ret = SsbSipMfcDecInit(m_pHandle, MPEG2_DEC, len);	if(ret != MFC_RET_OK)	{		gLogger.e("failed to init mfc, try again!\n");		return -1;	}	else	{		// 检查是否初始化成功,检测分辨率		SSBSIP_MFC_DEC_OUTPUT_INFO out;		SSBSIP_MFC_DEC_OUTBUF_STATUS status = SsbSipMfcDecGetOutBuf(m_pHandle, &out);		if(out.img_width <= 0 || out.img_height <= 0)		{			gLogger.e("mfc bad image size, should init again!\n");			return -1;		}		// 保存图片尺寸及缓冲区尺寸		nImgWidth = out.img_width;		nImgHeight = out.img_height;		nBufWidth = out.buf_width;		nBufHeight = out.buf_height;		gLogger.i("image size: %dx%d \n", out.img_width, out.img_height);		// 保存初始化时、输出缓存的物理地址, 外界可能要使用 // 		pPhyY = out.YPhyAddr;// 		pPhyC = out.CPhyAddr;	}	return 0;}int HwMpv2Decoder::Decode(int keyframe, void* data, int len, void** phyY, void** phyCbCr, bool save){// 	if(!m_bInitOK)// 	{// 		if(keyframe)  m_bInitOK = true;// 		else return 0;// 	}	memcpy(m_pVirInBuf, data, len);	SSBSIP_MFC_ERROR_CODE ret = SsbSipMfcDecExe(m_pHandle, len);	if(ret != MFC_RET_OK)	{		gLogger.e("mfc exe failed: %d \n", ret);		return -1;	}	SSBSIP_MFC_DEC_OUTPUT_INFO out;	SSBSIP_MFC_DEC_OUTBUF_STATUS status;	status = SsbSipMfcDecGetOutBuf(m_pHandle, &out);	if(status == MFC_GETOUTBUF_DISPLAY_DECODING 		|| status == MFC_GETOUTBUF_DISPLAY_ONLY)	{		//printf("status: %d \n", status);	   // UV像素             		*phyY = out.YPhyAddr;		*phyCbCr = out.CPhyAddr;// 		*phyY = out.YVirAddr;// 		*phyCbCr = out.CVirAddr;		if(save)		{			int y_size = 512 * 320;			int uv_size = y_size / 2;			unsigned char* y = new unsigned char[y_size]; 			unsigned char* uv = new unsigned char[uv_size];			Y_tile_to_linear_4x2(y, (unsigned char*)out.YVirAddr, out.buf_width, out.buf_height);			CbCr_tile_to_linear_4x2(uv, (unsigned char*)out.CVirAddr, out.buf_width, out.buf_height);			static int count = 0;			char filename[64];			sprintf(filename, "NV12-T.%d", count++);			FILE* fp = fopen(filename, "wb");			fwrite(y, 1, y_size, fp);			fwrite(uv, 1, uv_size, fp);			fclose(fp);			printf("save to picture: %s \n", filename);			//printf("haha\n");			delete [] y;			delete [] uv;		}		return 1;	}	return 0;}