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

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

 

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

头文件

#ifndef _HW_MPV2_DECODER
#define _HW_MPV2_DECODER

class 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;
}





 

 

你可能感兴趣的:(嵌入式专题: S5PV210 - MFC硬件解码)