📄 mfc.c
字号:
Assert(picX > 0);
Assert(picY > 0);
oMfc.m_bDecRotEn[uProcessIdx] = bDecRotEn;
oMfc.m_uRotFrameIdx[uProcessIdx] = 0;
oMfc.m_uMp4DeblockFrameIdx[uProcessIdx] = 0;
oMfc.m_uFrameIndex[uProcessIdx] = 0;
// H.263 Annex J deblock is in-loop filter, otherwise deblock is out-loop filter
MFC_IsDecH263AnnexJOn(uProcessIdx, &oMfc.m_bAnnexJOn[uProcessIdx]);
oMfc.m_uFrameDelayCount[uProcessIdx] = mfcInp32(RET_DEC_SEQ_FRAME_DELAY);
//DbgMfc("Delay Frame num=%d\n", oMfc.m_uFrameDelayCount[uProcessIdx]);
MFC_GetDecRefFrameNum(uProcessIdx, &uNumOfRefReconFrame);
//DbgMfc("num of RefFrame = %d\n", uNumOfRefReconFrame);
uFrameBufNumTemp = (oMfc.m_bDecRotEn[uProcessIdx]) ? uNumOfRefReconFrame+2 : uNumOfRefReconFrame;
uFrameBufNum = (oMfc.m_bMp4DecDeblkMode[uProcessIdx] && !oMfc.m_bAnnexJOn[uProcessIdx]) ? uFrameBufNumTemp+2 : uFrameBufNumTemp;
uStride = (picX%16 == 0) ? picX : (picX+15)/16*16;
uHeight = (picY%16 == 0) ? picY : (picY+15)/16*16;
MFC_InitDecFrameBuffer(uProcessIdx, uFrameBufNum, uStride, uHeight, uFrameBufStAddr);
MFC_IssueCmdOfSetFrameBuffer(uProcessIdx, uNumOfRefReconFrame, uStride);
}
void MFC_InitProcessForOneFrameDecoding(
u32 uProcessIdx, MFC_CODEC_MODE eCodecMode, u32 uStreamBufStAddr, u32 uStreamBufSize,
u32 uFrameBufStAddr, bool bDecRotEn, bool bMp4DeblkEn, bool bH264ReorderEn, bool bFilePlayEn, bool bDynBufAllocEn)
{
u32 uFilePlayEn;
u32 uDynBufEn;
u32 uStreamBufSizeCeilingToKbMultiple;
u32 uMp4DecDeblkMode;
u32 uH264DecReorderMode;
bool stat;
float frameRate;
u32 picX, picY;
u32 uNumOfRefReconFrame;
u32 uStride;
u32 uHeight;
u32 uFrameBufNumTemp;
u32 uFrameBufNum;
Assert(uProcessIdx < MAX_PROCESS_NUM);
Assert(eCodecMode == MP4_DEC || eCodecMode == AVC_DEC || eCodecMode == VC1_DEC);
oMfc.m_eCodecMode[uProcessIdx] = eCodecMode;
uStreamBufSizeCeilingToKbMultiple = (uStreamBufSize+1023)/1024*1024;
oMfc.m_uStreamBufStAddr[uProcessIdx] = uStreamBufStAddr;
oMfc.m_uStreamBufEndAddr[uProcessIdx] = uStreamBufStAddr + uStreamBufSizeCeilingToKbMultiple;
oMfc.m_uStreamBufByteSize[uProcessIdx] = uStreamBufSizeCeilingToKbMultiple;
oMfc.m_uBitRdPtr[uProcessIdx] =
(uProcessIdx == 0) ? BITS_RD_PTR0 :
(uProcessIdx == 1) ? BITS_RD_PTR1 :
(uProcessIdx == 2) ? BITS_RD_PTR2 :
(uProcessIdx == 3) ? BITS_RD_PTR3 :
(uProcessIdx == 4) ? BITS_RD_PTR4 :
(uProcessIdx == 5) ? BITS_RD_PTR5 :
(uProcessIdx == 6) ? BITS_RD_PTR6 : BITS_RD_PTR7;
oMfc.m_uBitWrPtr[uProcessIdx] =
(uProcessIdx == 0) ? BITS_WR_PTR0 :
(uProcessIdx == 1) ? BITS_WR_PTR1 :
(uProcessIdx == 2) ? BITS_WR_PTR2 :
(uProcessIdx == 3) ? BITS_WR_PTR3 :
(uProcessIdx == 4) ? BITS_WR_PTR4 :
(uProcessIdx == 5) ? BITS_WR_PTR5 :
(uProcessIdx == 6) ? BITS_WR_PTR6 : BITS_WR_PTR7;
mfcOutp32(oMfc.m_uBitRdPtr[uProcessIdx], oMfc.m_uStreamBufStAddr[uProcessIdx]);
mfcOutp32(oMfc.m_uBitWrPtr[uProcessIdx], oMfc.m_uStreamBufStAddr[uProcessIdx]+uStreamBufSize);
mfcOutp32(DEC_SEQ_BIT_BUF_ADDR, oMfc.m_uStreamBufStAddr[uProcessIdx]);
mfcOutp32(DEC_SEQ_BIT_BUF_SIZE, oMfc.m_uStreamBufByteSize[uProcessIdx]/1024); // KB unit
oMfc.m_bMp4DecDeblkMode[uProcessIdx] = (eCodecMode == MP4_DEC) ? bMp4DeblkEn : false;
uMp4DecDeblkMode = (oMfc.m_bMp4DecDeblkMode[uProcessIdx]) ? MP4_DBK_ENABLE : MP4_DBK_DISABLE;
uH264DecReorderMode = (bH264ReorderEn) ? REORDER_ENABLE : REORDER_DISABLE;
uFilePlayEn = (bFilePlayEn) ? FILEPLAY_ENABLE : FILEPLAY_DISABLE;
uDynBufEn = (bDynBufAllocEn) ? DYNBUFALLOC_ENABLE : DYNBUFALLOC_DISABLE;
mfcOutp32(DEC_SEQ_OPTION, uMp4DecDeblkMode|uH264DecReorderMode|uFilePlayEn|uDynBufEn);
oMfc.m_bIsNoMoreStream[uProcessIdx] = false;
MFC_IssueCmd(uProcessIdx, SEQ_INIT);
stat = MFC_IsCmdFinished();
if(stat == false)
{
Disp("\n There is an error in the SEQ_INIT result\n");
return;
}
MFC_GetDecSrcFormat(&picX, &picY, &frameRate);
oMfc.m_uPicX[uProcessIdx] = picX;
oMfc.m_uPicY[uProcessIdx] = picY;
DbgMfc("%d x %d @%.2f Hz\n", picX, picY, frameRate);
Assert(picX > 0);
Assert(picY > 0);
oMfc.m_bDecRotEn[uProcessIdx] = bDecRotEn;
oMfc.m_uRotFrameIdx[uProcessIdx] = 0;
oMfc.m_uMp4DeblockFrameIdx[uProcessIdx] = 0;
oMfc.m_uFrameIndex[uProcessIdx] = 0;
// H.263 Annex J deblock is in-loop filter, otherwise deblock is out-loop filter
MFC_IsDecH263AnnexJOn(uProcessIdx, &oMfc.m_bAnnexJOn[uProcessIdx]);
// mfcInp32(RET_DEC_SEQ_FRAME_DELAY, oMfc.m_uFrameDelayCount[uProcessIdx]);
oMfc.m_uFrameDelayCount[uProcessIdx] = mfcInp32(RET_DEC_SEQ_FRAME_DELAY);
DbgMfc("Delay Frame num=%d\n", oMfc.m_uFrameDelayCount[uProcessIdx]);
MFC_GetDecRefFrameNum(uProcessIdx, &uNumOfRefReconFrame);
DbgMfc("num of RefFrame = %d\n", uNumOfRefReconFrame);
uFrameBufNumTemp = (oMfc.m_bDecRotEn[uProcessIdx]) ? uNumOfRefReconFrame+2 : uNumOfRefReconFrame;
uFrameBufNum = (oMfc.m_bMp4DecDeblkMode[uProcessIdx] && !oMfc.m_bAnnexJOn[uProcessIdx]) ? uFrameBufNumTemp+2 : uFrameBufNumTemp;
uStride = (picX%16 == 0) ? picX : (picX+15)/16*16;
uHeight = (picY%16 == 0) ? picY : (picY+15)/16*16;
MFC_InitDecFrameBuffer(uProcessIdx, uFrameBufNum, uStride, uHeight, uFrameBufStAddr);
MFC_IssueCmdOfSetFrameBuffer(uProcessIdx, uNumOfRefReconFrame, uStride);
}
void MFC_InitStreamBufferForOneFrameDecoding(u32 uProcessIdx, u32 uStreamBufStAddr, u32 uStreamBufSize)
{
mfcOutp32(DEC_PIC_BB_START,uStreamBufStAddr & 0xfffffffc);
mfcOutp32(DEC_PIC_START_BYTE,uStreamBufStAddr & 0x3);
mfcOutp32(DEC_PIC_CHUNK_SIZE,uStreamBufSize);
}
bool MFC_DecodeOneFrame(u32 uRunIdx, u32* uFrameIdx)
{
MFC_StartDecodingOneFrame(uRunIdx);
MFC_WaitForReady();
return MFC_DoPostProcessingOfDecoding(uRunIdx, false, uFrameIdx);
}
void MFC_StartDecodingOneFrame(u32 uRunIdx)
{
u32 i, j, uDbkFrameNum=0;
u32 uRotMode, uRotStride;
if (oMfc.m_bMp4DecDeblkMode[uRunIdx] && !oMfc.m_bAnnexJOn[uRunIdx]) // out-loop filter
{
uDbkFrameNum = 2;
i = oMfc.m_uRefFrameNum[uRunIdx] + oMfc.m_uMp4DeblockFrameIdx[uRunIdx];
mfcOutp32(DEC_PIC_DEBLOCK_ADDR_Y, oMfc.m_uFrameAddrY[uRunIdx][i]);
mfcOutp32(DEC_PIC_DEBLOCK_ADDR_CB, oMfc.m_uFrameAddrCb[uRunIdx][i]);
mfcOutp32(DEC_PIC_DEBLOCK_ADDR_CR, oMfc.m_uFrameAddrCr[uRunIdx][i]);
}
if (oMfc.m_bDecRotEn[uRunIdx]) // out-loop filter
{
j = oMfc.m_uRefFrameNum[uRunIdx] + uDbkFrameNum + oMfc.m_uRotFrameIdx[uRunIdx];
mfcOutp32(DEC_PIC_ROT_ADDR_Y, oMfc.m_uFrameAddrY[uRunIdx][j]);
mfcOutp32(DEC_PIC_ROT_ADDR_CB, oMfc.m_uFrameAddrCb[uRunIdx][j]);
mfcOutp32(DEC_PIC_ROT_ADDR_CR, oMfc.m_uFrameAddrCr[uRunIdx][j]);
uRotMode = mfcInp32(DEC_PIC_ROT_MODE);
uRotStride = (uRotMode&1) ? oMfc.m_uPicY[uRunIdx] : oMfc.m_uStride[uRunIdx]; // Rot90 or Rot270
MFC_SetDecRotStride(uRotStride);
//DbgMfc("rot stride = %d\n",uRotStride);
}
MFC_StartIssuingCmd(uRunIdx, PIC_RUN);
}
bool MFC_DoPostProcessingOfDecoding(u32 uRunIdx, bool isEmpty, u32* uFrameIdx)
{
u32 uDeblockFrameNum = 0;
if (isEmpty && oMfc.m_bIsNoMoreStream[uRunIdx] && oMfc.m_uFrameDelayCount[uRunIdx]-- == 0)
{
return false;
}
MFC_GetDecReconFrameIndex(uRunIdx, &oMfc.m_uFrameIndex[uRunIdx]);
if (oMfc.m_uFrameIndex[uRunIdx] == -1) // 0xffff_ffff
{
*uFrameIdx = oMfc.m_uFrameIndex[uRunIdx];
return false;
}
uDeblockFrameNum = 0;
if (oMfc.m_bMp4DecDeblkMode[uRunIdx] && !oMfc.m_bAnnexJOn[uRunIdx])
{
oMfc.m_uFrameIndex[uRunIdx] = oMfc.m_uRefFrameNum[uRunIdx] + oMfc.m_uMp4DeblockFrameIdx[uRunIdx];
oMfc.m_uMp4DeblockFrameIdx[uRunIdx] = (oMfc.m_uMp4DeblockFrameIdx[uRunIdx]+1)%2;
uDeblockFrameNum = 2;
}
// from 6th f/w (VC-1 path is different from other codec's.)
if (oMfc.m_bDecRotEn[uRunIdx] && oMfc.m_eCodecMode[uRunIdx] != VC1_DEC)
{
oMfc.m_uFrameIndex[uRunIdx] = oMfc.m_uRefFrameNum[uRunIdx] + uDeblockFrameNum + oMfc.m_uRotFrameIdx[uRunIdx];
oMfc.m_uRotFrameIdx[uRunIdx] = (oMfc.m_uRotFrameIdx[uRunIdx]+1)%2;
}
*uFrameIdx = oMfc.m_uFrameIndex[uRunIdx];
DbgMfc("%d ", oMfc.m_uFrameIndex[uRunIdx]);
return true;
}
void MFC_InitProcessForEncoding(
u32 uProcessIdx,
MFC_CODEC_MODE eEncMode,
u32 uStreamBufStAddr,
u32 uStreamBufSize,
u32 uDispWidth,
u32 uDispHeight,
bool bEncRot90En)
{
MFC_InitProcessForEncoding1(uProcessIdx, eEncMode, uStreamBufStAddr, uStreamBufSize,
uDispWidth, uDispHeight, bEncRot90En, false, false, false, false);
}
void MFC_InitProcessForEncoding1(
u32 uProcessIdx,
MFC_CODEC_MODE eEncMode,
u32 uStreamBufStAddr,
u32 uStreamBufSize,
u32 uDispWidth,
u32 uDispHeight,
bool bEncRot90En,
bool bMbBitReport,
bool bSliceInfoReport,
bool bAudEnable,
bool bSkipDisable)
{
u32 uRefFrameBufStAddr;
u32 uRefFrameNum;
u32 uWidth;
u32 uHeight;
u32 i;
u32 uLongerLength;
u32 uStride;
MFC_InitEncSeq(uProcessIdx, eEncMode, uStreamBufStAddr, uStreamBufSize, bEncRot90En,
bMbBitReport, bSliceInfoReport, bAudEnable, bSkipDisable);
uRefFrameBufStAddr = oMfc.m_uStreamBufEndAddr[uProcessIdx];
// No reordering. Double buffer used.
// FRAME BUFFER SET
// FRAME 0/1 : RECONSTRUCT (Post Processor input)
oMfc.m_uRefFrameNum[uProcessIdx] = 2;
uRefFrameNum = oMfc.m_uRefFrameNum[uProcessIdx];
uWidth = (bEncRot90En) ? uDispHeight : uDispWidth;
uHeight = (bEncRot90En) ? uDispWidth : uDispHeight;
MFC_InitEncFrameBuffer(uProcessIdx, uRefFrameNum, uWidth, uHeight, uRefFrameBufStAddr);
// Clear recon frame
for (i=0; i<uRefFrameNum; i++)
{
MFC_ClearFrameBuffer(uProcessIdx, i);
}
// set stride to max(h,w) instead of h
uLongerLength = (uDispWidth > uDispHeight) ? uDispWidth : uDispHeight;
uStride = (bEncRot90En) ? uLongerLength : uDispWidth;
MFC_IssueCmdOfSetFrameBuffer(uProcessIdx, uRefFrameNum, uStride);
}
void MFC_IssueCmdOfSetFrameBuffer(u32 uProcessIdx, u32 uNumOfRefReconFrame, u32 uStride)
{
u32 i;
// Reference and Recon frames start addr setting for Command "SET_FRAME_BUF"
for (i=0; i<uNumOfRefReconFrame; i++)
{
mfcOutp32(oMfc.m_uParameterBufStartAddr+i*3*4, oMfc.m_uFrameAddrY[uProcessIdx][i]);
mfcOutp32(oMfc.m_uParameterBufStartAddr+i*3*4+4, oMfc.m_uFrameAddrCb[uProcessIdx][i]);
mfcOutp32(oMfc.m_uParameterBufStartAddr+i*3*4+8, oMfc.m_uFrameAddrCr[uProcessIdx][i]);
}
mfcOutp32(SET_FRAME_BUF_NUM, uNumOfRefReconFrame);
mfcOutp32(SET_FRAME_BUF_STRIDE, uStride);
MFC_IssueCmd(uProcessIdx, SET_FRAME_BUF);
}
void MFC_EncodeOneFrame(u32 uProcessIdx, u32 uAddrOfSrcYFrame, u32* uRecFrameIdx)
{
MFC_StartEncodingOneFrame(uProcessIdx, uAddrOfSrcYFrame);
MFC_WaitForReady();
MFC_DoPostProcessingOfEncoding(uProcessIdx, uRecFrameIdx);
}
void MFC_StartEncodingOneFrame(u32 uProcessIdx, u32 uAddrOfSrcYFrame)
{
u32 uAddrOfSrcCbFrame, uAddrOfSrcCrFrame;
mfcOutp32(ENC_PIC_SRC_ADDR_Y, uAddrOfSrcYFrame);
uAddrOfSrcCbFrame = uAddrOfSrcYFrame+oMfc.m_uStride[uProcessIdx]*oMfc.m_uHeight[uProcessIdx];
mfcOutp32(ENC_PIC_SRC_ADDR_CB, uAddrOfSrcCbFrame);
uAddrOfSrcCrFrame = uAddrOfSrcYFrame+oMfc.m_uStride[uProcessIdx]*oMfc.m_uHeight[uProcessIdx]*5/4;
mfcOutp32(ENC_PIC_SRC_ADDR_CR, uAddrOfSrcCrFrame);
if (oMfc.m_eCodecMode[uProcessIdx] == MP4_ENC)
{
MFC_SetEncPicQs(MP4_ENC, oMfc.m_EncCfg[uProcessIdx].VopQuant);
}
else
{
MFC_SetEncPicQs(AVC_ENC, oMfc.m_EncCfg[uProcessIdx].PicQpY);
}
MFC_StartIssuingCmd(uProcessIdx, PIC_RUN);
}
void MFC_DoPostProcessingOfEncoding(u32 uProcessIdx, u32* uRecFrameIdx)
{
MFC_GetEncReconFrameIndex(&oMfc.m_uFrameIndex[uProcessIdx]);
*uRecFrameIdx = oMfc.m_uFrameIndex[uProcessIdx];
}
void MFC_InitEncSeq(
u32 uProcessIdx,
MFC_CODEC_MODE eEncMode,
u32 uStreamBufStAddr,
u32 uStreamBufSize,
bool bEncRot90En,
bool bMbBitReport,
bool bSliceInfoReport,
bool bAudEnable,
bool bSkipDisable)
{
u32 uSkipDisableBit;
u32 uMbBitReportBit;
u32 uSliceInfoReportBit;
u32 uAudEnableBit;
u32 uEncSeqOptionValue;
bool stat;
Assert(uProcessIdx < MAX_PROCESS_NUM);
Assert(eEncMode == AVC_ENC || eEncMode == MP4_ENC);
oMfc.m_eCodecMode[uProcessIdx] = eEncMode;
oMfc.m_uStreamBufStAddr[uProcessIdx] = uStreamBufStAddr;
oMfc.m_uStreamBufEndAddr[uProcessIdx] = uStreamBufStAddr + uStreamBufSize;
oMfc.m_uStreamBufByteSize[uProcessIdx] = uStreamBufSize;
oMfc.m_uBitRdPtr[uProcessIdx] =
(uProcessIdx == 0) ? BITS_RD_PTR0 :
(uProcessIdx == 1) ? BITS_RD_PTR1 :
(uProcessIdx == 2) ? BITS_RD_PTR2 :
(uProcessIdx == 3) ? BITS_RD_PTR3 :
(uProcessIdx == 4) ? BITS_RD_PTR4 :
(uProcessIdx == 5) ? BITS_RD_PTR5 :
(uProcessIdx == 6) ? BITS_RD_PTR6 : BITS_RD_PTR7;
oMfc.m_uBitWrPtr[uProcessIdx] =
(uProcessIdx == 0) ? BITS_WR_PTR0 :
(uProcessIdx == 1) ? BITS_WR_PTR1 :
(uProcessIdx == 2) ? BITS_WR_PTR2 :
(uProcessIdx == 3) ? BITS_WR_PTR3 :
(uProcessIdx == 4) ? BITS_WR_PTR4 :
(uProcessIdx == 5) ? BITS_WR_PTR5 :
(uProcessIdx == 6) ? BITS_WR_PTR6 : BITS_WR_PTR7;
mfcOutp32(oMfc.m_uBitWrPtr[uProcessIdx], oMfc.m_uStreamBufStAddr[uProcessIdx]);
mfcOutp32(oMfc.m_uBitRdPtr[uProcessIdx], oMfc.m_uStreamBufStAddr[uProcessIdx]+uStreamBufSize);
// ENCODER PARAMETER SET
// Qs will be set in the stage of PIC_RUN
if (oMfc.m_eCodecMode[uProcessIdx] == MP4_ENC)
{
// ShortVideoHeader - 0 : MPEG4 SP, 1 : MPEG4 short video header/H.263P3
MFC_SetEncCodStd(oMfc.m_EncCfg[uProcessIdx].ShortVideoHeader);
mfcOutp32(ENC_SEQ_MP4_PARA,
(oMfc.m_EncCfg[uProcessIdx].IntraDcVlcThr << 2) |
(oMfc.m_EncCfg[uProcessIdx].RevVlcEn << 1) |
oMfc.m_EncCfg[uProcessIdx].DataPartEn);
mfcOutp32(ENC_SEQ_263_PARA,
(oMfc.m_EncCfg[uProcessIdx].AnnexI << 3) |
(oMfc.m_EncCfg[uProcessIdx].AnnexJ << 2) |
(oMfc.m_EncCfg[uProcessIdx].AnnexK << 1) |
oMfc.m_EncCfg[uProcessIdx].AnnexT);
}
else if (oMfc.m_eCodecMode[uProcessIdx] == AVC_ENC)
{
MFC_SetEncCodStd(2); // 2 means H.264 Encoding
MFC_SetEnc264Parameter(
oMfc.m_EncCfg[uProcessIdx].ChromaQpOffset,
oMfc.m_EncCfg[uProcessIdx].ConstIntraPredFlag,
oMfc.m_EncCfg[uProcessIdx].DisableDeblk,
oMfc.m_EncCfg[uProcessIdx].DeblkOffsetA,
oMfc.m_EncCfg[uProcessIdx].DeblkOffsetB);
mfcOutp32(ENC_SEQ_FMO,
((oMfc.m_EncCfg[uProcessIdx].FmoType)<<5)|
((oMfc.m_EncCfg[uProcessIdx].NumOfSliceGroup)<<1)|
((oMfc.m_EncCfg[uProcessIdx].FmoEnable)<<0));
}
if (!bEncRot90En)
{
MFC_SetEncSrcFormat(oMfc.m_EncCfg[uProcessIdx].PicX, oMfc.m_EncCfg[uProcessIdx].PicY, oMfc.m_EncCfg[uProcessIdx].FrameRate);
}
else
{
MFC_SetEncSrcFormat(oMfc.m_EncCfg[uProcessIdx].PicY, oMfc.m_EncCfg[uProcessIdx].PicX, oMfc.m_EncCfg[uProcessIdx].FrameRate);
}
// DbgMfc("frame rate=%d, picX=%d, picY=%d\n",
// oMfc.m_EncCfg[uProcessIdx].FrameRate, oMfc.m_EncCfg[uProcessIdx].PicX, oMfc.m_EncCfg[uProcessIdx].PicY);
mfcOutp32(ENC_SEQ_SLICE_MODE,
(oMfc.m_EncCfg[uProcessIdx].SliceSizeNum << 2) |
(oMfc.m_EncCfg[uProcessIdx].SliceSizeMode << 1) |
oMfc.m_EncCfg[uProcessIdx].SliceMode);
MFC_SetEncGopNum(oMfc.m_EncCfg[uProcessIdx].GopPicNum);
uSkipDisableBit = (oMfc.m_bSkipDisable[uProcessIdx]) ? 1 : 0;
mfcOutp32(ENC_SEQ_RC_PARA,
(uSkipDisableBit << 31) |
(oMfc.m_EncCfg[uProcessIdx].RcInitDelay << 16) |
(oMfc.m_EncCfg[uProcessIdx].RcBitRate << 1) |
oMfc.m_EncCfg[uProcessIdx].RcEnable);
mfcOutp32(ENC_SEQ_RC_BUF_SIZE, oMfc.m_EncCfg[uProcessIdx].RcBufSize);
mfcOutp32(ENC_SEQ_INTRA_MB, oMfc.m_EncCfg[uProcessIdx].IntraRefreshNum);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -