嵌入式专题: 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硬件解码

时间: 2024-12-28 12:55:53

嵌入式专题: S5PV210 - MFC硬件解码的相关文章

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

先说一下编码的例子好像找不到了,只提供一下解码的例子吧.淡疼的三星要是能以YUV420P为基本图像格式就好了,这样结合FFmpeg来开发,各种应用都比较方法.再设计一个RGB/YUV硬件转码单元,最好. #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include "../mfc/SsbSipMfcApi.h" #includ

嵌入式专题: S5PV210 - MPEG4解码(MFC)

解码比编码要省心一些,唯一让人操心的是,在初始化的时候要用编码器生成的head数据来初始化的.就是说,在编码的时候,是生成一个head数据,这个数据是用来在解码的时候用的. #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include "../mfc/SsbSipMfcApi.h" #include "../mfc/

嵌入式专题: UVC摄像头摄像

所谓的CMOS摄像头,驱动往往是一坨shit,想做摄像头应用,还是上UVC摄像头吧. 这个类里展示UVC摄像头的各种参数的设置.需要注意的是,如果帧率上不去,往往是由于曝光时间太长导致.这个关系是这样的,曝光越长,图片成像质量越好,但帧率自然就下去了. #ifndef _UVC_CAMERA_H #define _UVC_CAMERA_H class UvcCamera { public: UvcCamera(); ~UvcCamera(); int Open(const char* dev,

嵌入式专题: 双网卡wifi组建NAT上外网

条件: 开发板上双网卡,其中一个是usb wifi,提供wifi路由功能.另一个网口可以上外网. 目标:普通PC/手机能够连此wifi路由,上外网. 1. Wifi AP USB Wifi部分:勿用多言,此使用Realtek 8188 UC版本,这款Wifi的官方软件自带了驱动程序相应的应用软件.应该就是RTL8188C_8192C_USB_linux_v4.0.2_9000.20130911.zip这个程序包,里面有3个部分,一个是驱动,一个是hostapd,一个是wpa_supplicant

嵌入式专题: S5PV210 - MPEG4编码

我想说不台的平台,如tiny210和x210.它们的头文件是有稍微区别的. 我这个是x210下的代码.但都须要注意的是NV12T与NV12的问题,默认要求输入的图片是NV12T,经过调整之后,能够同意用NV12. 即便如此.NV12格式的图片也不好拿到啊. #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include "../mfc/S

【嵌入式Linux+ARM】硬件相关基础知识(门电路_UART_I2C_SPI)

比较基本的一些知识,就算再怎么水,一些基本的电路常识还是需要懂的,需要自己慢慢的积累,实际工作中需要好好积累硬件相关的知识: 正文开始: 1.门电路 与门.或门.非门的几个标志需要记住,特别是后面两个不要混淆,自己画了一遍: 实际电路中可以组合使用:如与非门.或非门等复杂电路. 这些是比较简单的,做个简单的复习: 与门:1 1-->1      1 0-->0      0 1-->0     0 0-->0 或门:1 1-->1      1 0-->1      0

解密H264、AAC硬件解码的关键扩展数据处理

通过上一篇文章,我们用ffmpeg分离出一个多媒体容器中的音视频数据,但是很可能这些数据是不能被正确解码的.为什么呢?因为在解码这些数据之前,需要对解码器做一些配置,典型的就是目前流行的高清编码"黄金搭档"组合H264 + AAC的搭配.本文将讲述H264和AAC的关键解码配置参数的解析,如果没有这些配置信息,数据帧往往不完整,导致了解码器不能解码. H264的配置信息解析 前面我们知道,ffmpeg的avformat_find_stream_info函数可以取得音视频媒体多种,比如播

解密硬件解码关键技术

通过上一篇文章,我们用ffmpeg分离出一个多媒体容器中的音视频数据,但是很可能这些数据是不能被正确解码的.为什么呢?因为在解码这些数据之前,需要对解码器做一些配置,典型的就是目前流行的高清编码“黄金搭档”组合H264 + AAC的搭配.本文将讲述H264和AAC的关键解码配置参数的解析,如果没有这些配置信息,数据帧往往不完整,导致了解码器不能解码. H264的配置信息解析 前面我们知道,ffmpeg的avformat_find_stream_info函数可以取得音视频媒体多种,比如播放持续时间

硬件解码关键技术剖析

通过上一篇文章,我们用ffmpeg分离出一个多媒体容器中的音视频数据,但是很可能这些数据是不能被正确解码的.为什么呢?因为在解码这些数据之前,需要对解码器做一些配置,典型的就是目前流行的高清编码"黄金搭档"组合H264 + AAC的搭配.本文将讲述H264和AAC的关键解码配置参数的解析,如果没有这些配置信息,数据帧往往不完整,导致了解码器不能解码. H264的配置信息解析 前面我们知道,ffmpeg的avformat_find_stream_info函数可以取得音视频媒体多种,比如播