1682 lines · 63.9 KB · C++
RawDownload
/*! * \copy *     Copyright (c)  2008-2013, Cisco Systems *     All rights reserved. * *     Redistribution and use in source and binary forms, with or without *     modification, are permitted provided that the following conditions *     are met: * *        * Redistributions of source code must retain the above copyright *          notice, this list of conditions and the following disclaimer. * *        * Redistributions in binary form must reproduce the above copyright *          notice, this list of conditions and the following disclaimer in *          the documentation and/or other materials provided with the *          distribution. * *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *     COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *     POSSIBILITY OF SUCH DAMAGE. * * *  Abstract *      current slice decoding * *  History *      07/10/2008 Created *      08/09/2013 Modified * *****************************************************************************/  #include "deblocking.h" #include "decode_slice.h" #include "parse_mb_syn_cavlc.h"#include "parse_mb_syn_cabac.h"#include "rec_mb.h"#include "mv_pred.h" #include "cpu_core.h" namespace WelsDec { int32_t WelsTargetSliceConstruction (PWelsDecoderContext pCtx) {  PDqLayer pCurLayer = pCtx->pCurDqLayer;  PSlice pCurSlice = &pCurLayer->sLayerInfo.sSliceInLayer;  PSliceHeader pSliceHeader = &pCurSlice->sSliceHeaderExt.sSliceHeader;   int32_t iTotalMbTargetLayer = pSliceHeader->pSps->uiTotalMbCount;   int32_t iCurLayerWidth  = pCurLayer->iMbWidth << 4;  int32_t iCurLayerHeight = pCurLayer->iMbHeight << 4;   int32_t iNextMbXyIndex = 0;  PFmo pFmo = pCtx->pFmo;   int32_t iTotalNumMb = pCurSlice->iTotalMbInCurSlice;  int32_t iCountNumMb = 0;  PDeblockingFilterMbFunc pDeblockMb;   if (!pCtx->bAvcBasedFlag && iCurLayerWidth != pCtx->iCurSeqIntervalMaxPicWidth) {    return -1;  }   iNextMbXyIndex   = pSliceHeader->iFirstMbInSlice;  pCurLayer->iMbX  = iNextMbXyIndex % pCurLayer->iMbWidth;  pCurLayer->iMbY  = iNextMbXyIndex / pCurLayer->iMbWidth;  pCurLayer->iMbXyIndex = iNextMbXyIndex;   if (0 == iNextMbXyIndex) {    pCurLayer->pDec->iSpsId = pSliceHeader->iSpsId;    pCurLayer->pDec->iPpsId = pSliceHeader->iPpsId;     pCurLayer->pDec->uiQualityId = pCurLayer->sLayerInfo.sNalHeaderExt.uiQualityId;  }   do {    if (iCountNumMb >= iTotalNumMb) {      break;    }     if (WelsTargetMbConstruction (pCtx)) {      WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,               "WelsTargetSliceConstruction():::MB(%d, %d) construction error. pCurSlice_type:%d",               pCurLayer->iMbX, pCurLayer->iMbY, pCurSlice->eSliceType);       return -1;    }     ++iCountNumMb;    if (!pCurLayer->pMbCorrectlyDecodedFlag[iNextMbXyIndex]) { //already con-ed, overwrite      pCurLayer->pMbCorrectlyDecodedFlag[iNextMbXyIndex] = true;      ++pCtx->iTotalNumMbRec;    }     if (pCtx->iTotalNumMbRec > iTotalMbTargetLayer) {      WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING,               "WelsTargetSliceConstruction():::pCtx->iTotalNumMbRec:%d, iTotalMbTargetLayer:%d",               pCtx->iTotalNumMbRec, iTotalMbTargetLayer);       return -1;    }     if (pSliceHeader->pPps->uiNumSliceGroups > 1) {      iNextMbXyIndex = FmoNextMb (pFmo, iNextMbXyIndex);    } else {      ++iNextMbXyIndex;    }    if (-1 == iNextMbXyIndex || iNextMbXyIndex >= iTotalMbTargetLayer) {	// slice group boundary or end of a frame      break;    }    pCurLayer->iMbX  = iNextMbXyIndex % pCurLayer->iMbWidth;    pCurLayer->iMbY  = iNextMbXyIndex / pCurLayer->iMbWidth;    pCurLayer->iMbXyIndex = iNextMbXyIndex;  } while (1);   pCtx->pDec->iWidthInPixel  = iCurLayerWidth;  pCtx->pDec->iHeightInPixel = iCurLayerHeight;   if ((pCurSlice->eSliceType != I_SLICE) && (pCurSlice->eSliceType != P_SLICE))    return 0;   pDeblockMb = WelsDeblockingMb;   if (1 == pSliceHeader->uiDisableDeblockingFilterIdc) {    return 0;//NO_SUPPORTED_FILTER_IDX  } else {    WelsDeblockingFilterSlice (pCtx, pDeblockMb);   }  // any other filter_idc not supported here, 7/22/2010   return 0;} int32_t WelsMbInterSampleConstruction (PWelsDecoderContext pCtx, PDqLayer pCurLayer,                                       uint8_t* pDstY, uint8_t* pDstU, uint8_t* pDstV, int32_t iStrideL, int32_t iStrideC) {  int32_t iMbXy = pCurLayer->iMbXyIndex;  int32_t i, iIndex, iOffset;   WelsChromaDcIdct (pCurLayer->pScaledTCoeff[iMbXy] + 256);	// 256 = 16*16  WelsChromaDcIdct (pCurLayer->pScaledTCoeff[iMbXy] + 320);	// 320 = 16*16 + 16*4   for (i = 0; i < 16; i++) { //luma    iIndex = g_kuiMbCountScan4Idx[i];    if (pCurLayer->pNzc[iMbXy][iIndex]) {      iOffset = ((iIndex >> 2) << 2) * iStrideL + ((iIndex % 4) << 2);      pCtx->pIdctResAddPredFunc (pDstY + iOffset, iStrideL, pCurLayer->pScaledTCoeff[iMbXy] + (i << 4));    }  }   for (i = 0; i < 4; i++) { //chroma    iIndex = g_kuiMbCountScan4Idx[i + 16]; //Cb    if (pCurLayer->pNzc[iMbXy][iIndex] || * (pCurLayer->pScaledTCoeff[iMbXy] + ((i + 16) << 4))) {      iOffset = (((iIndex - 16) >> 2) << 2) * iStrideC + (((iIndex - 16) % 4) << 2);      pCtx->pIdctResAddPredFunc (pDstU + iOffset, iStrideC, pCurLayer->pScaledTCoeff[iMbXy] + ((i + 16) << 4));    }     iIndex = g_kuiMbCountScan4Idx[i + 20]; //Cr    if (pCurLayer->pNzc[iMbXy][iIndex] || * (pCurLayer->pScaledTCoeff[iMbXy] + ((i + 20) << 4))) {      iOffset = (((iIndex - 18) >> 2) << 2) * iStrideC + (((iIndex - 18) % 4) << 2);      pCtx->pIdctResAddPredFunc (pDstV + iOffset, iStrideC , pCurLayer->pScaledTCoeff[iMbXy] + ((i + 20) << 4));    }  }   return 0;}int32_t WelsMbInterConstruction (PWelsDecoderContext pCtx, PDqLayer pCurLayer) {  int32_t iMbX = pCurLayer->iMbX;  int32_t iMbY = pCurLayer->iMbY;  uint8_t*  pDstY, *pDstCb, *pDstCr;   int32_t iLumaStride   = pCtx->pDec->iLinesize[0];  int32_t iChromaStride = pCtx->pDec->iLinesize[1];   pDstY  = pCurLayer->pDec->pData[0] + ((iMbY * iLumaStride + iMbX) << 4);  pDstCb = pCurLayer->pDec->pData[1] + ((iMbY * iChromaStride + iMbX) << 3);  pDstCr = pCurLayer->pDec->pData[2] + ((iMbY * iChromaStride + iMbX) << 3);   GetInterPred (pDstY, pDstCb, pDstCr, pCtx);  WelsMbInterSampleConstruction (pCtx, pCurLayer, pDstY, pDstCb, pDstCr, iLumaStride, iChromaStride);   pCtx->sBlockFunc.pWelsSetNonZeroCountFunc (    pCurLayer->pNzc[pCurLayer->iMbXyIndex]); // set all none-zero nzc to 1; dbk can be opti!  return 0;} void WelsLumaDcDequantIdct (int16_t* pBlock, int32_t iQp) {  const int32_t kiQMul = g_kuiDequantCoeff[iQp][0];#define STRIDE 16  int32_t i;  int32_t iTemp[16]; //FIXME check if this is a good idea  int16_t* pBlk = pBlock;  static const int32_t kiXOffset[4] = {0, STRIDE, STRIDE << 2,  5 * STRIDE};  static const int32_t kiYOffset[4] = {0, STRIDE << 1, STRIDE << 3, 10 * STRIDE};   for (i = 0; i < 4; i++) {    const int32_t kiOffset = kiYOffset[i];    const int32_t kiX1 = kiOffset + kiXOffset[2];    const int32_t kiX2 = STRIDE + kiOffset;    const int32_t kiX3 = kiOffset + kiXOffset[3];    const int32_t kiI4 = i << 2;	// 4*i    const int32_t kiZ0 = pBlk[kiOffset] + pBlk[kiX1];    const int32_t kiZ1 = pBlk[kiOffset] - pBlk[kiX1];    const int32_t kiZ2 = pBlk[kiX2] - pBlk[kiX3];    const int32_t kiZ3 = pBlk[kiX2] + pBlk[kiX3];     iTemp[kiI4]  = kiZ0 + kiZ3;    iTemp[1 + kiI4] = kiZ1 + kiZ2;    iTemp[2 + kiI4] = kiZ1 - kiZ2;    iTemp[3 + kiI4] = kiZ0 - kiZ3;  }   for (i = 0; i < 4; i++) {    const int32_t kiOffset = kiXOffset[i];    const int32_t kiI4 = 4 + i;    const int32_t kiZ0 = iTemp[i] + iTemp[4 + kiI4];    const int32_t kiZ1 = iTemp[i] - iTemp[4 + kiI4];    const int32_t kiZ2 = iTemp[kiI4] - iTemp[8 + kiI4];    const int32_t kiZ3 = iTemp[kiI4] + iTemp[8 + kiI4];     pBlk[kiOffset] = ((kiZ0 + kiZ3) * kiQMul + 2) >> 2; //FIXME think about merging this into decode_resdual    pBlk[kiYOffset[1] + kiOffset] = ((kiZ1 + kiZ2) * kiQMul + 2) >> 2;    pBlk[kiYOffset[2] + kiOffset] = ((kiZ1 - kiZ2) * kiQMul + 2) >> 2;    pBlk[kiYOffset[3] + kiOffset] = ((kiZ0 - kiZ3) * kiQMul + 2) >> 2;  }#undef STRIDE} int32_t WelsMbIntraPredictionConstruction (PWelsDecoderContext pCtx, PDqLayer pCurLayer, bool bOutput) {//seems IPCM should not enter this path  int32_t iMbXy = pCurLayer->iMbXyIndex;   WelsFillRecNeededMbInfo (pCtx, bOutput, pCurLayer);   if (IS_INTRA16x16 (pCurLayer->pMbType[iMbXy])) {    WelsLumaDcDequantIdct (pCurLayer->pScaledTCoeff[iMbXy], pCurLayer->pLumaQp[iMbXy]);    RecI16x16Mb (iMbXy, pCtx, pCurLayer->pScaledTCoeff[iMbXy], pCurLayer);     return 0;  }   if (IS_INTRA4x4 (pCurLayer->pMbType[iMbXy]))    RecI4x4Mb (iMbXy, pCtx, pCurLayer->pScaledTCoeff[iMbXy], pCurLayer);   return 0;} int32_t WelsMbInterPrediction (PWelsDecoderContext pCtx, PDqLayer pCurLayer) {  int32_t iMbX = pCurLayer->iMbX;  int32_t iMbY = pCurLayer->iMbY;  uint8_t*  pDstY, *pDstCb, *pDstCr;   int32_t iLumaStride   = pCtx->pDec->iLinesize[0];  int32_t iChromaStride = pCtx->pDec->iLinesize[1];   pDstY  = pCurLayer->pDec->pData[0] + ((iMbY * iLumaStride + iMbX) << 4);  pDstCb = pCurLayer->pDec->pData[1] + ((iMbY * iChromaStride + iMbX) << 3);  pDstCr = pCurLayer->pDec->pData[2] + ((iMbY * iChromaStride + iMbX) << 3);   GetInterPred (pDstY, pDstCb, pDstCr, pCtx);   return 0;} int32_t WelsTargetMbConstruction (PWelsDecoderContext pCtx) {  PDqLayer pCurLayer = pCtx->pCurDqLayer;  if (MB_TYPE_INTRA_PCM == pCurLayer->pMbType[pCurLayer->iMbXyIndex]) {    //already decoded and reconstructed when parsing    return 0;  } else if (IS_INTRA (pCurLayer->pMbType[pCurLayer->iMbXyIndex])) {    WelsMbIntraPredictionConstruction (pCtx, pCurLayer, 1);  } else if (IS_INTER (pCurLayer->pMbType[pCurLayer->iMbXyIndex])) { //InterMB    if (0 == pCurLayer->pCbp[pCurLayer->iMbXyIndex]) { //uiCbp==0 include SKIP      WelsMbInterPrediction (pCtx, pCurLayer);    } else {      WelsMbInterConstruction (pCtx, pCurLayer);    }  } else {    WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "WelsTargetMbConstruction():::::Unknown MB type: %d",             pCurLayer->pMbType[pCurLayer->iMbXyIndex]);    return -1;  }   return 0;} void WelsChromaDcIdct (int16_t* pBlock) {  int32_t iStride = 32;  int32_t iXStride = 16;  int32_t iStride1 = iXStride + iStride;  int16_t* pBlk = pBlock;  int32_t iA, iB, iC, iD, iE;   iA = pBlk[0];  iB = pBlk[iXStride];  iC = pBlk[iStride];  iD = pBlk[iStride1];   iE = iA - iB;  iA += iB;  iB = iC - iD;  iC += iD;   pBlk[0] = (iA + iC) >> 1;  pBlk[iXStride] = (iE + iB) >> 1;  pBlk[iStride] = (iA - iC) >> 1;  pBlk[iStride1] = (iE - iB) >> 1;} void WelsMap4x4NeighToSampleNormal (PWelsNeighAvail pNeighAvail, int32_t* pSampleAvail) {  if (pNeighAvail->iLeftAvail) {  //left    pSampleAvail[ 6] =      pSampleAvail[12] =        pSampleAvail[18] =          pSampleAvail[24] = 1;  }  if (pNeighAvail->iLeftTopAvail) { //top_left    pSampleAvail[0] = 1;  }  if (pNeighAvail->iTopAvail) { //top    pSampleAvail[1] =      pSampleAvail[2] =        pSampleAvail[3] =          pSampleAvail[4] = 1;  }  if (pNeighAvail->iRightTopAvail) { //top_right    pSampleAvail[5] = 1;  }} void WelsMap4x4NeighToSampleConstrain1 (PWelsNeighAvail pNeighAvail, int32_t* pSampleAvail) {  if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) {   //left    pSampleAvail[ 6] =      pSampleAvail[12] =        pSampleAvail[18] =          pSampleAvail[24] = 1;  }  if (pNeighAvail->iLeftTopAvail && IS_INTRA (pNeighAvail->iLeftTopType)) {  //top_left    pSampleAvail[0] = 1;  }  if (pNeighAvail->iTopAvail && IS_INTRA (pNeighAvail->iTopType)) {  //top    pSampleAvail[1] =      pSampleAvail[2] =        pSampleAvail[3] =          pSampleAvail[4] = 1;  }  if (pNeighAvail->iRightTopAvail && IS_INTRA (pNeighAvail->iRightTopType)) {  //top_right    pSampleAvail[5] = 1;  }}void WelsMap16x16NeighToSampleNormal (PWelsNeighAvail pNeighAvail, uint8_t* pSampleAvail) {  if (pNeighAvail->iLeftAvail) {    *pSampleAvail = (1 << 2);  }  if (pNeighAvail->iLeftTopAvail) {    *pSampleAvail |= (1 << 1);  }  if (pNeighAvail->iTopAvail) {    *pSampleAvail |= 1;  }} void WelsMap16x16NeighToSampleConstrain1 (PWelsNeighAvail pNeighAvail, uint8_t* pSampleAvail) {  if (pNeighAvail->iLeftAvail && IS_INTRA (pNeighAvail->iLeftType)) {    *pSampleAvail = (1 << 2);  }  if (pNeighAvail->iLeftTopAvail && IS_INTRA (pNeighAvail->iLeftTopType)) {    *pSampleAvail |= (1 << 1);  }  if (pNeighAvail->iTopAvail && IS_INTRA (pNeighAvail->iTopType)) {    *pSampleAvail |= 1;  }} int32_t ParseIntra4x4Mode (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, int8_t* pIntraPredMode,                           PBitStringAux pBs,                           PDqLayer pCurDqLayer) {  int32_t iSampleAvail[5 * 6] = { 0 }; //initialize as 0  int32_t iMbXy = pCurDqLayer->iMbXyIndex;  int32_t iFinalMode, i;   uint8_t uiNeighAvail = 0;  uint32_t uiCode;  int32_t iCode;  pCtx->pMap4x4NeighToSampleFunc (pNeighAvail, iSampleAvail);  uiNeighAvail = (iSampleAvail[6] << 2) | (iSampleAvail[0] << 1) | (iSampleAvail[1]);  for (i = 0; i < 16; i++) {    int32_t iPrevIntra4x4PredMode = 0;    if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {      WELS_READ_VERIFY (ParseIntraPredModeLumaCabac (pCtx, iCode));      iPrevIntra4x4PredMode = iCode;    } else {      WELS_READ_VERIFY (BsGetOneBit (pBs, &uiCode));      iPrevIntra4x4PredMode = uiCode;    }    const int32_t kiPredMode = PredIntra4x4Mode (pIntraPredMode, i);     int8_t iBestMode;    if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {      if (iPrevIntra4x4PredMode == -1)        iBestMode = kiPredMode;      else        iBestMode = iPrevIntra4x4PredMode + (iPrevIntra4x4PredMode >= kiPredMode);    } else {      if (iPrevIntra4x4PredMode) {        iBestMode = kiPredMode;      } else {        WELS_READ_VERIFY (BsGetBits (pBs, 3, &uiCode));        iBestMode = uiCode + (uiCode >= kiPredMode);      }    }     iFinalMode = CheckIntra4x4PredMode (&iSampleAvail[0], &iBestMode, i);    if (iFinalMode  == ERR_INVALID_INTRA4X4_MODE) {      return ERR_INFO_INVALID_I4x4_PRED_MODE;    }     pCurDqLayer->pIntra4x4FinalMode[iMbXy][g_kuiScan4[i]] = iFinalMode;     pIntraPredMode[g_kuiScan8[i]] = iBestMode;     iSampleAvail[g_kuiCache30ScanIdx[i]] = 1;  }  ST32 (&pCurDqLayer->pIntraPredMode[iMbXy][0], LD32 (&pIntraPredMode[1 + 8 * 4]));  pCurDqLayer->pIntraPredMode[iMbXy][4] = pIntraPredMode[4 + 8 * 1];  pCurDqLayer->pIntraPredMode[iMbXy][5] = pIntraPredMode[4 + 8 * 2];  pCurDqLayer->pIntraPredMode[iMbXy][6] = pIntraPredMode[4 + 8 * 3];  if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {    WELS_READ_VERIFY (ParseIntraPredModeChromaCabac (pCtx, uiNeighAvail, iCode));    if (iCode > MAX_PRED_MODE_ID_CHROMA) {      return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;    }    pCurDqLayer->pChromaPredMode[iMbXy] = iCode;  } else {    WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode    if (uiCode > MAX_PRED_MODE_ID_CHROMA) {      return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;    }    pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;  }   if (-1 == pCurDqLayer->pChromaPredMode[iMbXy]      || CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {    return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;  }   return ERR_NONE;} int32_t ParseIntra16x16Mode (PWelsDecoderContext pCtx, PWelsNeighAvail pNeighAvail, PBitStringAux pBs,                             PDqLayer pCurDqLayer) {  int32_t iMbXy = pCurDqLayer->iMbXyIndex;  uint8_t uiNeighAvail = 0; //0x07 = 0 1 1 1, means left, top-left, top avail or not. (1: avail, 0: unavail)  uint32_t uiCode;  int32_t iCode;  pCtx->pMap16x16NeighToSampleFunc (pNeighAvail, &uiNeighAvail);   if (CheckIntra16x16PredMode (uiNeighAvail,                               &pCurDqLayer->pIntraPredMode[iMbXy][7])) { //invalid iPredMode, must stop decoding    return ERR_INFO_INVALID_I16x16_PRED_MODE;  }  if (pCurDqLayer->sLayerInfo.pPps->bEntropyCodingModeFlag) {    WELS_READ_VERIFY (ParseIntraPredModeChromaCabac (pCtx, uiNeighAvail, iCode));    if (iCode > MAX_PRED_MODE_ID_CHROMA) {      return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;    }    pCurDqLayer->pChromaPredMode[iMbXy] = iCode;  } else {    WELS_READ_VERIFY (BsGetUe (pBs, &uiCode)); //intra_chroma_pred_mode    if (uiCode > MAX_PRED_MODE_ID_CHROMA) {      return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;    }    pCurDqLayer->pChromaPredMode[iMbXy] = uiCode;  }  if (-1 == pCurDqLayer->pChromaPredMode[iMbXy]      || CheckIntraChromaPredMode (uiNeighAvail, &pCurDqLayer->pChromaPredMode[iMbXy])) {    return ERR_INFO_INVALID_I_CHROMA_PRED_MODE;  }   return ERR_NONE;} int32_t WelsDecodeMbCabacISliceBaseMode0 (PWelsDecoderContext pCtx, uint32_t& uiEosFlag) {  PDqLayer pCurLayer		 = pCtx->pCurDqLayer;  PBitStringAux pBsAux		 = pCurLayer->pBitStringAux;  PSlice pSlice			 = &pCurLayer->sLayerInfo.sSliceInLayer;  PSliceHeader pSliceHeader		 = &pSlice->sSliceHeaderExt.sSliceHeader;  SWelsNeighAvail sNeighAvail;

Lines 1–500 of 1682.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t