⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 motcomp.c

📁 Nokia H.264/AVC Encoder/Decoder Usage Manual
💻 C
字号:
/*COPYRIGHT, LICENSE AND WARRANTY INFORMATIONThis software module has been originally developed by Nokia Corporation. Provided that a person, entity or a company willing to use the Software (hereinafter Licensee) comply with all the terms and conditions of this Statement and subject to the limitations set forth in this Statement Nokia grants to such Licensee a non-exclusive, sub-licensable, worldwide, limited license under copyrights owned by Nokia to use the Software for the sole purpose of creating, manufacturing, selling, marketing, or  distributing (including the right to make modifications to the Software) a fully compliant decoder implementation (hereinafter "Decoder") of ITU-T Recommendation H.264 / ISO/IEC International Standard 14496-10 and an encoder implementation producing output that is decodable with the Decoder.Nokia retains the ownership of copyrights to the Software. There is no patent nor other intellectual property right of Nokia licensed under this Statement (except the copyright license above). Licensee hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if patent licenses  are required, it is their responsibility to acquire the license before utilizing the Software.The license by Nokia is subject to that the Licensee grants to Nokia the non-exclusive, worldwide, royalty-free, perpetual and irrevocable covenant that the Licensee(s) shall not bring a suit before any court or administrative agency or otherwise assert a claim for infringement under the Licensee intellectual property rights that, but for a license, would be infringed by the Software against     (a)  Nokia or Nokia's Affiliate; or     (b)  other recipient of a license and covenant not to sue with respect         to the Software from Nokia; or    (c)  contractor, customer or distributor of a party listed above in a         or b,  which suit or claim is related to the Software or use thereof.The Licensee(s) further agrees to grant a reciprocal license to Nokia (as granted by Nokia to the Licensee(s) on the modifications made by Licensee(s) to the Software. THE SOFTWARE IS PROVIDED "AS IS" AND THE ORIGINAL DEVELOPER DISCLAIMS ANY AND ALL WARRANTIES WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. THOSE INTENDING TO USE THE SOFTWARE ARE EXPRESSLY ADVISED THAT ITS USE MAY INFRINGE EXISTING PATENTS AND BE SUBJECT TO ROYALTY PAYMENTS TO PATENT OWNERS. ANYONE USING THE SOFTWARE ON THE BASIS OF THIS LICENSE AGREES TO OBTAIN THE NECESSARY PERMISSIONS FROM ANY AND ALL APPLICABLE PATENT OWNERS FOR SUCH USE.IN NO EVENT SHALL THE ORIGINAL DEVELOPER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.This copyright, license and warranty information notice must be retained in all copies and derivative works of the Software or substantial portions thereof.*/#ifdef CHECK_MV_RANGE#include <stdio.h>#endif#include "globals.h"#include "motcomp.h"#include "framebuffer.h"#define ONEFOURTH1  20#define ONEFOURTH2  -5#define ONEFOURTH3  1static const int numModeMotVecs[MOT_NUM_MODES+1] = {  0, 1, 2, 2, 4, 8, 8, 16};static const int numModeMotVecs8x8[4] = {  1, 2, 2, 4};static const int blockShapes[MOT_NUM_MODES][2] = {  {4, 4},  {4, 2},  {2, 4},  {2, 2},  {2, 1},  {1, 2},  {1, 1}};static const int blockShapes8x8[][2] = {  {2, 2},  {2, 1},  {1, 2},  {1, 1}};#ifdef CHECK_MV_RANGEextern int maxVerticalMvRange;#endif/* * findPredMotVec * * Parameters: *      refTab                Table containing reference frame number *                            for the whole frame *      motVecs               Motion vectors for the whole frame *      blksPerLine           The number of blocks per line *      mbAvailBits           Availability of neighboring macroblocks *      blkX                  Horizontal block index *      blkY                  Vertical block index *      blkIdxX               Horizontal block index within macroblock *      blkIdxY               Vertical block index within macroblock *      shapeX                Width of the motion block in blocks *      shapeY                Height of the motion block in blocks * * Function: *      Find the prediction vector for the current motion block. * * Returns: *      Prediction vector * */static motVec_s findPredMotVec(int8 *refTab, motVec_s *vecs, int blksPerLine,                               int mbAvailBits, int blkIdxX, int blkIdxY,                               int shapeX, int shapeY){  static const motVec_s zeroVec = {0,0};  motVec_s const *vecA;  motVec_s const *vecB;  motVec_s const *vecC;  motVec_s vecX;  int refNum, refLeft, refUp, refUpRight;  int blkIdxXright;  /*   *       |       |   *     D | B     | C   *   ----+-------+----   *     A |       |   *       |   X   |   *       |       |   *   *   X is current block. Motion vectors from named   *   positions are used for prediction   */  /*   * Fetch vectors and reference frame numbers of blocks A, B and C   */  if (blkIdxX > 0 || (mbAvailBits & 1)) {    vecA    = &vecs[-1];    refLeft = refTab[-1];  }  else {    /* A is outside the picture  =>  A is zero  and ref is -1 */    vecA    = &zeroVec;    refLeft = -1;  }  if (blkIdxY > 0 || (mbAvailBits & 2)) {    vecB  = &vecs[-blksPerLine];    refUp = refTab[-blksPerLine];  }  else {    /* B is outside the picture  =>  B is zero and ref is -2 */    vecB  = &zeroVec;    refUp = -2;  }  blkIdxXright = blkIdxX+shapeX-1;  if ((blkIdxXright != BLK_PER_MB/2 && (blkIdxXright&blkIdxY) != 0) ||      (blkIdxY == 0 && (blkIdxXright < BLK_PER_MB-1 ? !(mbAvailBits & 2) : !(mbAvailBits & 4))))  {    /* C is outside the picture or is not available  =>  C = D */    if ((blkIdxY > 0 && (blkIdxX > 0 || (mbAvailBits & 1))) ||        (blkIdxY == 0 && (blkIdxX > 0 ? (mbAvailBits & 2) : (mbAvailBits & 8))))    {      vecC       = &vecs[-blksPerLine-1];      refUpRight = refTab[-blksPerLine-1];    }    else {      /* D is too outside the picture  =>  C is not available */      /* If both B abd C are not available then C = B = A  */      if (refUp == -2) {        vecC = vecB = vecA;        refUpRight = refUp = refLeft;      }      /* if only C is not available then C is zero */      else {        vecC       = &zeroVec;        refUpRight = -1;      }    }  }  else {    /* C is inside the picture and is available */    vecC       = &vecs[-blksPerLine+shapeX];    refUpRight = refTab[-blksPerLine+shapeX];  }  refNum = refTab[0];  /*   * If only one of the neighboring block has the same reference   * frame number as the  current block, predict from that block.   */  if (refLeft == refNum) {    if (refUp != refNum && refUpRight != refNum)      return *vecA;  }  else {    if (refUp == refNum) {      if (refUpRight != refNum)        return *vecB;    }    else if (refUpRight == refNum)      return *vecC;  }  /*   * Directional prediction for block sizes 8x16, 16x8   */  if (shapeX + shapeY == 6) {    if (shapeX == 2) {  /* Is it 8x16? */      if (blkIdxX == 0 && refLeft == refNum)        return *vecA;      else if (blkIdxX != 0 && refUpRight == refNum)        return *vecC;    }    else {              /* It is 16x8 */      if (blkIdxY == 0 && refUp == refNum)        return *vecB;      else if (blkIdxY != 0 && refLeft == refNum)        return *vecA;    }  }  /*   * If everything else fails, do median prediction.   */  /* Median of x co-ordinates */  if (vecB->x < vecA->x) {    if      (vecA->x < vecC->x) vecX.x = vecA->x; // vecB->x < vecA->x < vecC->x    else if (vecC->x < vecB->x) vecX.x = vecB->x; // vecC->x < vecB->x < vecA->x    else                        vecX.x = vecC->x; // vecB->x < vecC->x < vecA->x  }  else {  // vecA->x < vecB->x    if      (vecC->x < vecA->x) vecX.x = vecA->x; // vecC->x < vecA->x < vecB->x    else if (vecB->x < vecC->x) vecX.x = vecB->x; // vecA->x < vecB->x < vecC->x    else                        vecX.x = vecC->x; // vecA->x < vecC->x < vecB->x  }  /* Median of y co-ordinates */  if (vecB->y < vecA->y) {    if      (vecA->y < vecC->y) vecX.y = vecA->y; // vecB->y < vecA->y < vecC->y    else if (vecC->y < vecB->y) vecX.y = vecB->y; // vecC->y < vecB->y < vecA->y    else                        vecX.y = vecC->y; // vecB->y < vecC->y < vecA->y  }  else {  // vecA->y < vecB->y    if      (vecC->y < vecA->y) vecX.y = vecA->y; // vecC->y < vecA->y < vecB->y    else if (vecB->y < vecC->y) vecX.y = vecB->y; // vecA->y < vecB->y < vecC->y    else                        vecX.y = vecC->y; // vecA->y < vecC->y < vecB->y  }  return vecX;}/* * * mcpGetNumMotVecs: * * Parameters: *      mode                  Motion mode (16x16, 8x16, 16x8, 8x8) *      inter8x8modes         Subblocks modes (8x8, 4x8, 8x4, 4x4) * * Function: *      Get the number of motion vectors that need to be decoded for given *      MB mode and subblock modes. *       * Returns: *      Number of motion vectors. * */int mcpGetNumMotVecs(int interMode, int inter8x8modes[4]){  int numVecs;  if (interMode < MOT_8x8)    numVecs = numModeMotVecs[interMode];  else {    numVecs  = numModeMotVecs8x8[inter8x8modes[0]];    numVecs += numModeMotVecs8x8[inter8x8modes[1]];    numVecs += numModeMotVecs8x8[inter8x8modes[2]];    numVecs += numModeMotVecs8x8[inter8x8modes[3]];  }  return numVecs;}/* * * mcpClearMBmotion: * * Parameters: *      mbIdxX                MB horizontal location *      mbIdxY                MB vertical location *      picWidth              Frame buffer width in pixels *      refTab                Reference index buffer *      refNum                Reference frame index *      motVecs               Motion vector buffer * * Function: *      Set MB reference frame indices to refNum. *       * Returns: *      - */void mcpClearMBmotion(int mbIdxX, int mbIdxY, int picWidth, int8 *refTab,                      int refNum, motVec_s *motVecs){  int blksPerLine = picWidth/BLK_SIZE;  int blkIdxX, blkIdxY;  motVec_s *vecPtr;  int8 *refPtr;  vecPtr = &motVecs[mbIdxY*BLK_PER_MB*blksPerLine+mbIdxX*BLK_PER_MB];  refPtr = &refTab[mbIdxY*BLK_PER_MB*blksPerLine+mbIdxX*BLK_PER_MB];  for (blkIdxY = 0; blkIdxY < BLK_PER_MB; blkIdxY++) {    for (blkIdxX = 0; blkIdxX < BLK_PER_MB; blkIdxX++) {      vecPtr[blkIdxX].x = 0;      vecPtr[blkIdxX].y = 0;      refPtr[blkIdxX] = (int8)refNum;    }    vecPtr += blksPerLine;    refPtr += blksPerLine;  }}/* * * mcpPutVectors: * * Parameters: *      mbIdxX                MB horizontal location *      mbIdxY                MB vertical location *      ref                   Reference frame buffer list *      mode                  Motion mode (16x16, 8x16, 16x8, 8x8) *      subblockModes         Subblocks modes (8x8, 4x8, 8x4, 4x4) *      subblockRef           Subblocks reference indices *      picWidth              Frame buffer width in pixels *      refTab                Reference index buffer *      hasRef                Indicates whether MB has ref. other than 0 *      motVecs               Motion vector buffer *      mbAvailBIts           Availability of neighboring macroblocks *      diffVecs              Decoded delta vectors * * Function: *      Put decoded motion vectors to the motion vector buffer *       * Returns: *      - */void mcpPutVectors(int mbIdxX, int mbIdxY, int mode, int *subblockModes,                   int *subblockRef, int picWidth, int8 *refTab,                   int numRefFrames, motVec_s *motVecs, int mbAvailBits,                   int diffVecs[BLK_PER_MB*BLK_PER_MB][2]){  int blksPerLine;  int shapeX, shapeY;  int blkIdxX, blkIdxY;  motVec_s predVec;  int y;  int *inter8x8modes;  int blk8X, blk8Y;  int blkAddr;  int8 *refIdxPtr;  motVec_s *vecPtr;  int *diffVecPtr;  int refIdx, refIdx2;  int mvX, mvY;  blksPerLine = picWidth/BLK_SIZE;  blkAddr = mbIdxY*BLK_PER_MB*blksPerLine + mbIdxX*BLK_PER_MB;  refTab = &refTab[blkAddr];  motVecs = &motVecs[blkAddr];  /*   * Put ref. indices to the ref. index buffer.   */  refIdxPtr = refTab;  if (numRefFrames > 1 && mode <= MOT_8x8) {    /*     * Put reference indices for 16x16, 16x8, 8x16 or 8x8 blocks     */    shapeX = blockShapes[mode-1][0];    shapeY = blockShapes[mode-1][1];    for (blkIdxY = 0; blkIdxY < BLK_PER_MB; blkIdxY+=shapeY) {      refIdx  = *subblockRef++;      refIdx2 = (shapeX == 2) ? *subblockRef++ : refIdx;      for (y = 0; y < shapeY; y++) {        refIdxPtr[0] = (int8) refIdx;        refIdxPtr[1] = (int8) refIdx;        refIdxPtr[2] = (int8) refIdx2;        refIdxPtr[3] = (int8) refIdx2;        refIdxPtr += blksPerLine;      }    }  }  else {    /*     * All reference indices are zero     */    for (blkIdxY = 0; blkIdxY < BLK_PER_MB; blkIdxY++) {      refIdxPtr[0] = 0;      refIdxPtr[1] = 0;      refIdxPtr[2] = 0;      refIdxPtr[3] = 0;      refIdxPtr += blksPerLine;    }  }  /*   * Put motion vectors to the motion vector buffer.   */  diffVecPtr = diffVecs[0];  if (mode < MOT_8x8) {    /*     * Put motion vectors for 16x16, 16x8 and 8x16 blocks     */    shapeX = blockShapes[mode-1][0];  /* Width of mot. block in blocks */    shapeY = blockShapes[mode-1][1];  /* Height of mot. block in blocks */    for (blkIdxY = 0; blkIdxY < BLK_PER_MB; blkIdxY+=shapeY) {      for (blkIdxX = 0; blkIdxX < BLK_PER_MB; blkIdxX+=shapeX) {        blkAddr = blkIdxY*blksPerLine+blkIdxX;        vecPtr = &motVecs[blkAddr];        /* Get predicted vector */        predVec = findPredMotVec(refTab+blkAddr, vecPtr, blksPerLine,                                 mbAvailBits, blkIdxX, blkIdxY, shapeX, shapeY);        mvX = predVec.x + (*diffVecPtr++);        mvY = predVec.y + (*diffVecPtr++);#ifdef CHECK_MV_RANGE        if (mvX < -2048*4 || mvX > (2048*4-1)) {          printf("Horizontal MV component range violation %f\n", 0.25*mvX);        }        if (mvY < -maxVerticalMvRange*4 || mvY > (maxVerticalMvRange*4-1)) {          printf("Vertical MV component range violation %f\n", 0.25*mvY);        }#endif        for (y = 0; y < shapeY; y++) {          /* 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -