標籤:使用 檔案 os width io 代碼
嵌入式就是瞎折騰。奉獻一些過時的代碼,讓嵌入式的兄弟少折騰一些吧。
這一篇是怎麼解碼的,本篇用的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;}