📄 mfc_instance.c
字号:
////////////////////////////
/// STATE changing ///
////////////////////////////
if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_DEC_INITIALIZED))
MFCINST_STATE_TRANSITION(ctx, MFCINST_STATE_DEC_PIC_RUN_RING_BUF);
if (strm_leng) {
// If the input stream length is less than 'MFC_RING_BUF_PARTUNIT_SIZE',
// this block of input stream is considered as the last unit.
// MFC instance will not accept any more input stream data,
// when the state is changed to MFCINST_STATE_DEC_PIC_RUN_RING_BUF_LAST_UNITS.
// The state is now changing to MFCINST_STATE_DEC_PIC_RUN_RING_BUF_LAST_UNITS.
if (strm_leng < MFC_RING_BUF_PARTUNIT_SIZE) {
if (strm_leng & 0x1FF) {
garbage_size = strm_leng;
strm_leng = (strm_leng + 512) & 0xFFFFFE00;
garbage_size = strm_leng - garbage_size;
}
MFCINST_STATE_TRANSITION(ctx, MFCINST_STATE_DEC_PIC_RUN_RING_BUF_LAST_UNITS);
MfcSetEos(0);
}
else if (strm_leng == MFC_RING_BUF_PARTUNIT_SIZE) {
// state change to MFCINST_STATE_DEC_PIC_RUN_RING_BUF
MFCINST_STATE_TRANSITION(ctx, MFCINST_STATE_DEC_PIC_RUN_RING_BUF);
}
else { // strm_leng > MFC_RING_BUF_PARTUNIT_SIZE => ERROR !!
LOG_MSG(LOG_ERROR, "Decode_Stream", "Size of buffer fill is more than requested.\r\n");
return MFCINST_ERR_DEC_BUF_FILL_SIZE_WRONG;
}
MFCINST_STATE_BUF_FILL_REQ_CLEAR(ctx);
}
// Moving the BITS_WR_PTR value by the amount of strm_leng
mfc_sfr = (S3C6410_MFC_SFR *) GetMfcSfrVirAddr();
mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_WR_PTR += strm_leng;
if (strm_leng > 0 &&
((mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_WR_PTR - ctx->phyadrStrmBuf)
>= MFC_RING_BUF_SIZE)) {
mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_WR_PTR -= MFC_RING_BUF_SIZE;
}
if ( (strm_leng > 0) && (strm_leng < MFC_RING_BUF_PARTUNIT_SIZE) ) {
mfc_sfr = (S3C6410_MFC_SFR *) GetMfcSfrVirAddr();
offset = mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_WR_PTR - GetDataBufPhyAddr();
Mem_Set((char *)(GetDataBufVirAddr() + offset - garbage_size), 0, garbage_size);
}
//////////////////////////////////////////////////////////////////////
// //
// 13. Set the Parameters in the PARAM_BUF for PIC_RUN command. //
// //
//////////////////////////////////////////////////////////////////////
pPARAM_DEC_PIC_RUN = (S3C6410_MFC_PARAM_REG_DEC_PIC_RUN *) MfcGetCmdParamRegion();
pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_MODE = ctx->PostRotMode;
#if (MFC_ROTATE_ENABLE == 1)
if (ctx->PostRotMode & 0x0010) { // The bit of 'PostRotEn' is 1.
frame_size = ctx->buf_width * ctx->buf_height;
pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_ADDR_Y = ctx->phyadrFramBuf + ctx->frambufCnt * ((frame_size * 3) >> 1);
pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_ADDR_CB = pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_ADDR_Y + frame_size;
pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_ADDR_CR = pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_ADDR_Y + frame_size + (frame_size >> 2);
// Rotate Angle
switch (ctx->PostRotMode & 0x0003) {
case 0: // 0 degree counterclockwise rotate
case 2: // 180 degree counterclockwise rotate
pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_STRIDE = ctx->buf_width;
break;
case 1: // 90 degree counterclockwise rotate
case 3: // 270 degree counterclockwise rotate
pPARAM_DEC_PIC_RUN->DEC_PIC_ROT_STRIDE = ctx->buf_height;
break;
}
}
#endif
////////////////////////////////////////
// //
// 14. Issue the PIC_RUN command //
// //
////////////////////////////////////////
if (!MfcIssueCmd(ctx->inst_no, ctx->codec_mode, PIC_RUN)) {
LOG_MSG(LOG_TRACE, "Decode_Stream", "Frame num : %d, pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX : %d\n", pPARAM_DEC_PIC_RUN->RET_DEC_PIC_FRAME_NUM, pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX);
return MFCINST_ERR_DEC_PIC_RUN_CMD_FAIL; // BUFFER empty or full interrupt is raised.
}
if (pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX > 30) {
if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_DEC_PIC_RUN_RING_BUF_LAST_UNITS)
&& (pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX == 0xFFFFFFFF)) { // RET_DEC_PIC_IDX == -1
LOG_MSG(LOG_WARNING, "Decode_Stream", "End of Stream.\r\n");
return MFCINST_ERR_DEC_EOS;
}
else if (pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX == 0xFFFFFFFD) { // RET_DEC_PIC_IDX == -3
LOG_MSG(LOG_TRACE, "Decode_Stream", "No picture to be displayed.\r\n");
// return MFCINST_ERR_DEC_DECODE_NO_DISP;
}
else {
LOG_MSG(LOG_ERROR, "Decode_Stream", "Decoding Fail, ret = %d\r\n", pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX);
return MFCINST_ERR_DEC_DECODE_FAIL_ETC;
}
}
ctx->frame_num = pPARAM_DEC_PIC_RUN->RET_DEC_PIC_FRAME_NUM;
ctx->idx = pPARAM_DEC_PIC_RUN->RET_DEC_PIC_IDX;
#ifdef CNM_PM
if( pPARAM_DEC_PIC_RUN->RET_DEC_PIC_ERR_MB_NUM > 0 )
RETAILMSG( 1, (_T("Report2 MB Error num=%d\r\n"), pPARAM_DEC_PIC_RUN->RET_DEC_PIC_ERR_MB_NUM ) );
#endif
return MFCINST_RET_OK;
}
int MFCInst_Encode(MFCInstCtx *ctx, int *enc_data_size, int *header_size)
{
volatile S3C6410_MFC_PARAM_REG_ENC_PIC_RUN *pPARAM_ENC_PIC_RUN;
S3C6410_MFC_SFR *mfc_sfr;
int hdr_size, hdr_size2;
unsigned char *hdr_buf_tmp=NULL;
////////////////////////////
/// STATE checking ///
////////////////////////////
if (!MFCINST_STATE_CHECK(ctx, MFCINST_STATE_ENC_INITIALIZED) && !MFCINST_STATE_CHECK(ctx, MFCINST_STATE_ENC_PIC_RUN_LINE_BUF)) {
LOG_MSG(LOG_ERROR, "MFCInst_Encode", "MFC Encoder instance is not initialized or not using the line buffer.\r\n");
return MFCINST_ERR_STATE_CHK;
}
mfc_sfr = (S3C6410_MFC_SFR *) GetMfcSfrVirAddr();
// The 1st call of this function (MFCInst_Encode) will generate the stream header (mpeg4: VOL, h264: SPS/PPS).
//
if (MFCINST_STATE_CHECK(ctx, MFCINST_STATE_ENC_INITIALIZED)) {
if (ctx->codec_mode == MP4_ENC) {
// ENC_HEADER command //
MFCInst_EncHeader(ctx, 0, 0, ctx->phyadrStrmBuf, ctx->nStrmBufSize, &hdr_size); // VOL
// Backup the stream header in the temporary header buffer.
hdr_buf_tmp = (unsigned char *) malloc(hdr_size);
Mem_Cpy(hdr_buf_tmp, ctx->pStrmBuf, hdr_size);
}
else if (ctx->codec_mode == AVC_ENC) {
// ENC_HEADER command //
MFCInst_EncHeader(ctx, 0, 0, ctx->phyadrStrmBuf, ctx->nStrmBufSize, &hdr_size); // SPS
MFCInst_EncHeader(ctx, 1, 0, ctx->phyadrStrmBuf + (hdr_size + 3), ctx->nStrmBufSize-(hdr_size+3), &hdr_size2); // PPS
// Backup the stream header in the temporary header buffer.
hdr_buf_tmp = (unsigned char *) malloc(hdr_size + 3 + hdr_size2);
Mem_Cpy(hdr_buf_tmp, ctx->pStrmBuf, hdr_size);
Mem_Cpy(hdr_buf_tmp + hdr_size, (void *)((unsigned int)(ctx->pStrmBuf + (hdr_size + 3)) & 0xFFFFFFFC), hdr_size2);
hdr_size = hdr_size + hdr_size2;
}
}
// SEI message with recovery point
if ((ctx->enc_pic_option & 0x0F000000) && (ctx->codec_mode == AVC_ENC))
{
// ENC_HEADER command //
MFCInst_EncHeader(ctx, 4, ((ctx->enc_pic_option & 0x0F000000) >> 24), ctx->phyadrStrmBuf, ctx->nStrmBufSize, &hdr_size); // SEI
// Backup the stream header in the temporary header buffer.
hdr_buf_tmp = (unsigned char *) malloc(hdr_size);
Mem_Cpy(hdr_buf_tmp, ctx->pStrmBuf, hdr_size);
}
/*
* Set the address of each component of YUV420
*/
pPARAM_ENC_PIC_RUN = (S3C6410_MFC_PARAM_REG_ENC_PIC_RUN *) MfcGetCmdParamRegion();
pPARAM_ENC_PIC_RUN->ENC_PIC_SRC_ADDR_Y = ctx->phyadrFramBuf;
pPARAM_ENC_PIC_RUN->ENC_PIC_SRC_ADDR_CB = ctx->phyadrFramBuf + ctx->buf_width * ctx->height;
pPARAM_ENC_PIC_RUN->ENC_PIC_SRC_ADDR_CR = ctx->phyadrFramBuf + ((ctx->buf_width * ctx->height * 5) >> 2);
pPARAM_ENC_PIC_RUN->ENC_PIC_ROT_MODE = 0;
pPARAM_ENC_PIC_RUN->ENC_PIC_OPTION = (ctx->enc_pic_option & 0x0000FFFF);
pPARAM_ENC_PIC_RUN->ENC_PIC_BB_START = ctx->phyadrStrmBuf;
pPARAM_ENC_PIC_RUN->ENC_PIC_BB_SIZE = ctx->nStrmBufSize;
if (!MfcIssueCmd(ctx->inst_no, ctx->codec_mode, PIC_RUN)) {
return MFCINST_ERR_ENC_PIC_RUN_CMD_FAIL;
}
ctx->enc_pic_option = 0; // Reset the encoding picture option at every picture
ctx->idx = 0;
*enc_data_size = mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_WR_PTR - ctx->phyadrStrmBuf; // calculte encoded data size
*header_size = 0;
if (hdr_buf_tmp) {
memmove(ctx->pStrmBuf + hdr_size, ctx->pStrmBuf, *enc_data_size);
Mem_Cpy(ctx->pStrmBuf, hdr_buf_tmp, hdr_size);
Mem_Free(hdr_buf_tmp);
*enc_data_size += hdr_size;
*header_size = hdr_size;
}
////////////////////////////
/// STATE changing ///
////////////////////////////
// state change to MFCINST_STATE_ENC_PIC_RUN_LINE_BUF
MFCINST_STATE_TRANSITION(ctx, MFCINST_STATE_ENC_PIC_RUN_LINE_BUF);
return MFCINST_RET_OK;
}
// hdr_code == 0: SPS
// hdr_code == 1: PPS
// hdr_code == 4: SEI
int MFCInst_EncHeader(MFCInstCtx *ctx, int hdr_code, int hdr_num, unsigned int outbuf_physical_addr, int outbuf_size, int *hdr_size)
{
volatile S3C6410_MFC_PARAM_REG_ENC_HEADER *pPARAM_ENC_HEADER;
S3C6410_MFC_SFR *mfc_sfr;
if (!MFCINST_STATE_CHECK(ctx, MFCINST_STATE_ENC_INITIALIZED) && !MFCINST_STATE_CHECK(ctx, MFCINST_STATE_ENC_PIC_RUN_LINE_BUF)) {
LOG_MSG(LOG_ERROR, "MFCInst_EncHeader", "MFC Encoder instance is not initialized or not using the line buffer.\r\n");
return MFCINST_ERR_STATE_CHK;
}
if ((ctx->codec_mode != MP4_ENC) && (ctx->codec_mode != AVC_ENC)) {
return MFCINST_ERR_WRONG_CODEC_MODE;
}
/*
* Set the address of each component of YUV420
*/
pPARAM_ENC_HEADER = (S3C6410_MFC_PARAM_REG_ENC_HEADER *) MfcGetCmdParamRegion();
pPARAM_ENC_HEADER->ENC_HEADER_CODE = hdr_code;
pPARAM_ENC_HEADER->ENC_HEADER_BB_START = outbuf_physical_addr & 0xFFFFFFFC;
pPARAM_ENC_HEADER->ENC_HEADER_BB_SIZE = outbuf_size; //ctx->nStrmBufSize;
if (hdr_code == 4) // SEI recovery point
pPARAM_ENC_HEADER->ENC_HEADER_NUM = hdr_num; // recovery point value
mfc_sfr = (S3C6410_MFC_SFR *) GetMfcSfrVirAddr();
if (!MfcIssueCmd(ctx->inst_no, ctx->codec_mode, ENC_HEADER)) {
return MFCINST_ERR_ENC_HEADER_CMD_FAIL;
}
*hdr_size = mfc_sfr->BIT_STR_BUF_RW_ADDR[ctx->inst_no].BITS_WR_PTR - pPARAM_ENC_HEADER->ENC_HEADER_BB_START;
return MFCINST_RET_OK;
}
int MFCInst_EncParamChange(MFCInstCtx *ctx, unsigned int param_change_enable, unsigned int param_change_val)
{
volatile S3C6410_MFC_PARAM_REG_ENC_PARAM_CHANGE *pPARAM_ENC_PARAM_CHANGE;
int num_mbs; // Number of MBs
int slices_mb; // MB number of slice (only if SLICE_MODE_MULTIPLE is selected.)
pPARAM_ENC_PARAM_CHANGE = (S3C6410_MFC_PARAM_REG_ENC_PARAM_CHANGE *) MfcGetCmdParamRegion();
memset(pPARAM_ENC_PARAM_CHANGE, 0, sizeof(S3C6410_MFC_PARAM_REG_ENC_PARAM_CHANGE));
pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_ENABLE = param_change_enable;
// GOP_NUM
if (param_change_enable == (1 << 0)) {
if (param_change_val > 60) {
LOG_MSG(LOG_ERROR, "MFCInst_EncParamChange", "MFC Encoder Parameter change value is invalid.\r\n");
return MFCINST_ERR_ENC_PARAM_CHANGE_INVALID_VALUE;
}
pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_GOP_NUM = param_change_val;
}
// INTRA_QP
else if (param_change_enable == (1 << 1)) {
if (((ctx->codec_mode == MP4_DEC || ctx->codec_mode == H263_DEC) && (param_change_val == 0 || param_change_val > 31))
|| (ctx->codec_mode == AVC_DEC && param_change_val > 51)) {
LOG_MSG(LOG_ERROR, "MFCInst_EncParamChange", "MFC Encoder Parameter change value is invalid.\r\n");
return MFCINST_ERR_ENC_PARAM_CHANGE_INVALID_VALUE;
}
pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_INTRA_QP = param_change_val;
}
// BITRATE
else if (param_change_enable == (1 << 2)) {
if (param_change_val > 0x07FFF) {
LOG_MSG(LOG_ERROR, "MFCInst_EncParamChange", "MFC Encoder Parameter change value is invalid.\r\n");
return MFCINST_ERR_ENC_PARAM_CHANGE_INVALID_VALUE;
}
pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_BITRATE = param_change_val;
}
// F_RATE
else if (param_change_enable == (1 << 3)) {
pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_F_RATE = param_change_val;
}
// INTRA_REFRESH
else if (param_change_enable == (1 << 4)) {
if (param_change_val > ((ctx->width * ctx->height) >> 8)) {
LOG_MSG(LOG_ERROR, "MFCInst_EncParamChange", "MFC Encoder Parameter change value is invalid.\r\n");
return MFCINST_ERR_ENC_PARAM_CHANGE_INVALID_VALUE;
}
pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_INTRA_REFRESH = param_change_val;
}
// SLICE_MODE
else if (param_change_enable == (1 << 5)) {
// MB size is 16x16. -> width & height are divided by 16 to get number of MBs. (Division by 16 == shift right by 4-bit)
num_mbs = (ctx->width >> 4) * (ctx->height >> 4);
if (param_change_val > 256 || param_change_val > num_mbs) {
LOG_MSG(LOG_ERROR, "MFCInst_EncParamChange", "MFC Encoder Parameter change value is invalid.\r\n");
return MFCINST_ERR_ENC_PARAM_CHANGE_INVALID_VALUE;
}
if (param_change_val == 0) {
pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_SLICE_MODE = SLICE_MODE_ONE;
}
else {
slices_mb = (num_mbs / param_change_val);
ctx->enc_num_slices = param_change_val;
pPARAM_ENC_PARAM_CHANGE->ENC_PARAM_CHANGE_SLICE_MODE = SLICE_MODE_MULTIPLE | (1 << 1) | (slices_mb<< 2);;
}
}
if (!MfcIssueCmd(ctx->inst_no, ctx->codec_mode, ENC_PARAM_CHANGE)) {
return MFCINST_ERR_ENC_HEADER_CMD_FAIL;
}
return MFCINST_RET_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -