嵌入式就是瞎折腾。奉献一些过时的代码,让嵌入式的兄弟少折腾一些吧。
这一篇是怎么解码的,本篇用的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硬件解码,布布扣,bubuko.com
原文地址:http://blog.csdn.net/iamshaofa/article/details/37692987