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

📄 encoder.c

📁 Nokia H.264/AVC Encoder/Decoder Usage Manual
💻 C
📖 第 1 页 / 共 4 页
字号:
  if (fread(buf->y, sizeof(unsigned char), nPixels,   inFile->y) != nPixels)    return 0;  if (fread(buf->u, sizeof(unsigned char), nPixels/4, inFile->u) != nPixels/4)    return 0;  if (fread(buf->v, sizeof(unsigned char), nPixels/4, inFile->v) != nPixels/4)    return 0;  return 1;}static void writeCroppedFrameComponent(FILE *outFile,                                       unsigned char *frameBuf,                                       int bufWidth,                                       int leftOffset,                                       int topOffset,                                       int outWidth,                                       int outHeight){  int i;  for (i = topOffset; i < (topOffset + outHeight); i ++)  {    fwrite(frameBuf + i * bufWidth + leftOffset, sizeof(unsigned char),       outWidth, outFile);  }}/* * writeFrame: * * Parameters: *      buf                   Frame buffer *      seqParam              Encoding parameters *      outFile               Destination file * * Function: *      Writes frame to the file. *      The frame cropping is applied. *       * Returns: *      - */static void writeFrame(avceYUVbuffer_s  *buf,                        avceOpenParams_s *seqParam,                       videoFile_s      *outFile,                        int              frameIdx){  int nPixels;  int width, height;  width  = seqParam->picWidth -     seqParam->cropOffsets[0] - seqParam->cropOffsets[1];  height = seqParam->picHeight -     seqParam->cropOffsets[2] - seqParam->cropOffsets[3];  nPixels = width * height;  switch (outFile->format) {  case SEPARATE_YUV_FILES:    fseek(outFile->y, frameIdx * nPixels,   SEEK_SET);    fseek(outFile->u, frameIdx * nPixels/4, SEEK_SET);    fseek(outFile->v, frameIdx * nPixels/4, SEEK_SET);    break;  case COMBINED_YUV_FILE:    fseek(outFile->y, (frameIdx * nPixels * 3)/2, SEEK_SET);    break;  }  // take care of the frame cropping  writeCroppedFrameComponent(outFile->y, buf->y,     seqParam->picWidth,    seqParam->cropOffsets[0], seqParam->cropOffsets[2], width, height);  writeCroppedFrameComponent(outFile->u, buf->u,     seqParam->picWidth >> 1,    seqParam->cropOffsets[0] >> 1, seqParam->cropOffsets[2] >> 1, width >> 1, height >> 1);  writeCroppedFrameComponent(outFile->v, buf->v,     seqParam->picWidth >> 1,    seqParam->cropOffsets[0] >> 1, seqParam->cropOffsets[2] >> 1, width >> 1, height >> 1);}/** putBytesByteStream:** Parameters:*      stream          Bitsream file*      data            Data to be written*      len             Length of data** Function:*      Write bytes to bitstream file*      ** Returns:*      -**/void putBytesByteStream(FILE *stream, void *data, int len){  fwrite(data, len, 1, stream);}/* * main: * * Parameters: *      argc                  Number of parameters *      argv                  Parameter strings * * Function: *      Encoder main function * * Returns: *         0 ok *      <> 0 error */int main(int argc, char **argv){  userParam_s param;      /* Parameters from user */  avceOpenParams_s seqParam;    /* Parameters passed to encoder */  avceEncoder_t *encoder;    /* Encoder instance */  avceStatistics_s frmStat;  videoFile_s origFile;  videoFile_s recoFile;  int recoFlag;  FILE *stream;  FILE *cumuFp;  int srcPicNum, dstPicNum,numSkippedFrames=0;  int intraFlag, idrFlag;  int qp;  avceYUVbuffer_s origBuf, prevOrigBuf;  avceYUVbuffer_s recoBuf;  void *nalBuf;  int nalBufSize;  int result;  int targetFpsTimes1000;  int pType;  int nalRefIdc;  int intraComing;      /*                          * Old name: scenecutComing. The next frame will be intra coded.                          * Either a refreshed picture or a scene cut picture.                         */  int intraFrm;         /* Old name: scenecutFrm. Current frame is intra coded. */  int sceneId;          /* Newly defined var */  int scenecutComing;   /* Newly defined var: Indicates the coming of a scene cut picture */  int nextScFrameidx;   /* The skipped pic in the orig seq is counted by the idx */  int lastIdrFrm;       /* The frame idx of the last IDR picture */  /* Parse command line arguments  */  processCommands(argc, argv, &param, &seqParam);    targetFpsTimes1000 = seqParam.origFpsTimes1000/(param.frmSkip + 1);    /* Open video files */  recoFlag = openVideoFiles(&param, &origFile, &recoFile, &stream);    /* Initialize encoder constants common to all encoder instances */  avceLoad();    /*    * Open (encoder) sequence    */  seqParam.offsetForRefFrame = param.frmSkip + 1;  seqParam.numFrms = param.numFrms;  seqParam.intraFreq = param.intraFreq;  seqParam.idrFreq = param.idrFreq;  seqParam.numNonref = param.numNonref;    encoder = avceOpen(&seqParam,&nalBuf,&nalBufSize);  putBytesByteStream(stream, nalBuf, nalBufSize);    if (encoder == NULL) {      fprintf(stderr, "Could not open sequence\n");      exit(1);    }    /* Allocate memory for original frame data */    allocOrigFrame(&origBuf, seqParam.picWidth, seqParam.picHeight);      if (param.fScenecut) {      allocOrigFrame(& prevOrigBuf, seqParam.picWidth, seqParam.picHeight);    }    /*    * Encode sequence, one frame at a time    */       pType = 0;    // the first frame is always handled as the scene cut    nextScFrameidx = 0;    dstPicNum = 0;    intraComing = 1;    sceneId = -1;    scenecutComing = 1;    lastIdrFrm = -1;    while (dstPicNum < param.numFrms)    {      int i, groupLen;      int ltrCandidate;      if (intraComing)      {        intraComing = 0;        intraFrm = 1;        groupLen = 1;       // process this frame only      }      else      {        intraFrm = 0;        groupLen = param.numNonref + 1;        // group can not include next IDR         if (param.idrFreq > 0)        {          int nextIdr;          nextIdr = ROUND_UP(dstPicNum, param.idrFreq);          // if the next IDR refresh picture is too close to another IDR picture,          // it will not be a refresh IDR picture          if (param.minIdrDistance > 0 && lastIdrFrm >= 0) {            int nextSc = nextScFrameidx / (param.frmSkip + 1);            if (nextIdr - lastIdrFrm < param.minIdrDistance ||                nextSc  - nextIdr    < param.minIdrDistance)              nextIdr = nextSc;          }          if (nextIdr >= param.numFrms)            nextIdr = param.numFrms;          if (dstPicNum + groupLen - 1 >= nextIdr)            groupLen = nextIdr - dstPicNum;          if (groupLen == 0)            intraComing = 1;        }        // groupLen will be adjusted again if there is a scene cut        if ((param.fScenecut) && (groupLen > 0))        {          if ((dstPicNum != 0))          {            int pType;            // have a scene cut in the group? should be done backward            // but we want to use this process to generate a scene cut file also            pType = 0;            for (nextScFrameidx = dstPicNum;               nextScFrameidx < (dstPicNum + groupLen); nextScFrameidx ++)            {              srcPicNum = param.startFrm + nextScFrameidx * (param.frmSkip + 1);              readFrame(& origBuf, seqParam.picWidth, seqParam.picHeight,                & origFile, srcPicNum);              param.Sumuv = param.Sumy = 0;              pType = scdSceneCut(origBuf.y, origBuf.u, origBuf.v,                prevOrigBuf.y, prevOrigBuf.u, prevOrigBuf.v,                seqParam.picWidth, seqParam.picHeight, 4, & param.Sumy, & param.Sumuv);              if (pType)                break;            }          }          // this is the last frame in the group          srcPicNum = param.startFrm + (dstPicNum + groupLen - 1) * (param.frmSkip + 1);          // does the next scene cut fall within the group          if (srcPicNum >= nextScFrameidx * (param.frmSkip + 1))          {            intraComing = 1;            // the last frame whould be the one right before scene cut            groupLen = (nextScFrameidx - 1 - param.startFrm)/(param.frmSkip + 1) - dstPicNum + 1;            if (groupLen < 0)              // scene cut happens between this frame and the last encoded frame              groupLen = 0;          }        }      }      if (groupLen == 0)        // leave it to the next iteration        continue;      // decide number of pp frames,      for (i = 0; i < groupLen; i ++)      {        int srcPicIdx;        intraFlag = 0;        idrFlag   = 0;        if (i == 0)        {          intraFlag = idrFlag = (intraFrm) ? 1 : 0;          // for intraFrm, groupLen == 1          srcPicIdx = dstPicNum + groupLen - 1;          nalRefIdc = 1;          // store the last idr picture idx          if (idrFlag)            lastIdrFrm = srcPicIdx;          // create the scene info SEI message here          if ( scenecutComing && param.fScenecutSei) {            fprintf(stderr, "writing scene info sei (%d)\n", sceneId);            avceEncodeSceneInfo(encoder, sceneId, &nalBuf, &nalBufSize);            putBytesByteStream(stream, nalBuf, nalBufSize);          }        }        else        {          srcPicIdx = dstPicNum + i - 1;          nalRefIdc = 0;        }        // we many want to insert intra frame, not idr frame for testing        if (param.intraFreq > 0)        {          if ((srcPicIdx % param.intraFreq) == 0 && (intraFlag == 0))            intraFlag = 1;        }        // if there is no reference frame, this frame is always intra        if ((intraFlag == 0) && (seqParam.maxNumRefFrms == 0))          intraFlag = 1;        srcPicNum = param.startFrm + srcPicIdx * (param.frmSkip + 1);        if (! readFrame(& origBuf, seqParam.picWidth, seqParam.picHeight,          & origFile, srcPicNum))          break;        // use this frame as the previous frame in scene cut detection        if (i == 0 && param.fScenecut)        {          int lumaSize;          lumaSize = seqParam.picWidth * seqParam.picHeight;          memcpy(prevOrigBuf.y, origBuf.y,  lumaSize);          memcpy(prevOrigBuf.u, origBuf.u,  lumaSize/4);          memcpy(prevOrigBuf.v, origBuf.v,  lumaSize/4);        }        // decide the qp to use for the frame        // qpIntra is not used if intra frame is after q2Start        if ((dstPicNum + i) >= param.q2Start)          qp = param.qpInter2;        else          qp = intraFlag ? param.qpIntra : param.qpInter;        if (nalRefIdc == 0)          qp = param.qpNonref;        // will this frame used as long term reference frame        // this is a reference picture, however this should still be stored if this is not to be outputted        ltrCandidate = 0;        if (param.ltrFreq > 0)        {          if (((srcPicIdx - param.ltrStart) % param.ltrFreq) == 0)            ltrCandidate = 1;        }        // modify the frame number        if (idrFlag && (param.ltrIdr))          ltrCandidate = 1;              /* Encoder one frame */        result = avceEncodeOneFrame(encoder, &origBuf, &recoBuf,           intraFlag, idrFlag, scenecutComing, nalRefIdc, ltrCandidate, srcPicNum - param.startFrm,             qp, &nalBuf, &nalBufSize);        if (result == AVCE_ERROR) {          fprintf(stderr, "Error occured while encoding\n");          exit(1);        }        /* If frame was not skipped, bits are written to file */            if (result != AVCE_FRAME_SKIPPED) {                avceGetFrmStat(encoder, &frmStat);                // change output layout, easier to load it into excel to do data analysis          if (param.fInfo) {            if (srcPicNum == 0) {              int bits;              bits = avceGetBitsSPS(encoder) + avceGetBitsPPS(encoder) + 10*8;              printf(" %d\t %d\t %d \n", srcPicNum, (bits + frmStat.bits)/8, intraFlag);                  }            else              printf(" %d\t %d\t %d \n", srcPicNum, frmStat.bits/8, intraFlag);          }          else {            {        if(intraFlag ||idrFlag)                  printf("%3d(%s)\tbits\t%6d\tPsnrYUV\t%5.2f\t%5.2f\t%5.2f\tintraMb\t%d\t%5d  %1d\n",           srcPicNum, "I", frmStat.bits, frmStat.psnrY, frmStat.psnrU,           frmStat.psnrV, frmStat.numIntraMbs, frmStat.bufFullness, intraFlag);        else if(nalRefIdc == 1)        printf("%3d(%s)\tbits\t%6d\tPsnrYUV\t%5.2f\t%5.2f\t%5.2f\tintraMb\t%d\t%5d  %1d\n",           srcPicNum, "P", frmStat.bits, frmStat.psnrY, frmStat.psnrU,           frmStat.psnrV, frmStat.numIntraMbs, frmStat.bufFullness, intraFlag);        else if(nalRefIdc == 0)        printf("%3d(%s)\tbits\t%6d\tPsnrYUV\t%5.2f\t%5.2f\t%5.2f\tintraMb\t%d\t%5d  %1d\n",           srcPicNum, "p", frmStat.bits, frmStat.psnrY, frmStat.psnrU,           frmStat.psnrV, frmStat.numIntraMbs, frmStat.bufFullness, intraFlag);            }          }          putBytesByteStream(stream, nalBuf, nalBufSize);          if (recoFlag)          {            writeFrame(& recoBuf, & seqParam, & recoFile,               (srcPicNum - (numSkippedFrames*(param.frmSkip + 1)) - param.startFrm)/(param.frmSkip + 1));                }        }    else    {      if(intraFlag == 1)        intraComing = 1;      numSkippedFrames++;    }      }      dstPicNum += groupLen;      intraFrm = 0;      scenecutComing = 0;    }        fprintf(stderr," took %5.3f seconds                \n", (double)clock()/CLOCKS_PER_SEC);    /* Append short sequence statistics to -cumul file if file present */    if (strlen(param.cumuFileName) != 0) {      if ((cumuFp = fopen(param.cumuFileName, "a")) != NULL) {        printSeqStat(encoder, param.qpIntra, param.qpInter, targetFpsTimes1000, numSkippedFrames, cumuFp);        fclose(cumuFp);      }    }    /* Print a bit more detailed statistics */    if(!param.fInfo) dumpStatistics(encoder, targetFpsTimes1000, numSkippedFrames);      /* Close sequence */    avceClose(encoder);    /* Free memory of original frame data */    freeOrigFrame(&origBuf);    if (param.fScenecut)      freeOrigFrame(&prevOrigBuf);    /* Close video files */    closeFiles(&origFile, &recoFile, recoFlag, stream);              return 0;}

⌨️ 快捷键说明

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