嵌入式就是瞎折腾。奉献一些过时的代码,让嵌入式的兄弟少折腾一些吧。
这一篇是怎么解码的,本篇用的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; }