📄 decoder.c
字号:
/* * * readBytesFromFile: * * Parameters: * str Bitbuffer object * * Function: * Read bytes from the bistream file * * Returns: * Number of bytes read * */static int readBytesFromFile(byteStream_s *str){ int n; if (str->bitbufLen - str->bitbufDataLen < NALBUF_BLOCK_SIZE) { /* Buffer is too small -> allocate bigger buffer */ str->bitbuf = realloc(str->bitbuf, str->bitbufLen+NALBUF_BLOCK_SIZE); if (str->bitbuf == NULL) { fprintf(stderr, "Cannot resize bitbuffer\n"); exit(1); } str->bitbufLen += NALBUF_BLOCK_SIZE; } /* Read block of data */ n = (int)fread(str->bitbuf + str->bitbufDataLen, 1, NALBUF_BLOCK_SIZE, str->fn); str->bytesRead += n; str->bitbufDataLen += n; return n;}/* * * findStartCode: * * Parameters: * str Bitbuffer object * * Function: * First next start code in AVC byte stream * * Returns: * Length of start code * * str->bitbufDataPos will point to first byte that follows start code */static int findStartCode(byteStream_s *str){ int numZeros; int startCodeFound; int i; int currByte; numZeros = 0; startCodeFound = 0; i = str->bitbufDataPos; while (!startCodeFound) { if (i == str->bitbufDataLen) { /* We are at the end of data -> read more from the bitstream file */ int n = readBytesFromFile(str); if (n == 0) /* End of bitstream -> stop search */ break; } /* Find sequence of 0x00 ... 0x00 0x01 */ while (i < str->bitbufDataLen) { currByte = str->bitbuf[i]; i++; if (currByte > 1) /* If current byte is > 1, it cannot be part of a start code */ numZeros = 0; else if (currByte == 0) /* If current byte is 0, it could be part of a start code */ numZeros++; else { /* currByte == 1 */ if (numZeros > 1) { /* currByte == 1. If numZeros > 1, we found a start code */ startCodeFound = 1; break; } numZeros = 0; } } } str->bitbufDataPos = i; if (startCodeFound) return (numZeros + 1); else return 0;}/* * * getNalunitBits_ByteStream: * * Parameters: * strIn Bytestream pointer * * Function: * Read one NAL unit from bitstream file. * * Returns: * 1: No errors * 0: Could not read bytes (end of file) */int getNalunitBits_ByteStream(void *strIn){ byteStream_s *str; int numRemainingBytes; int startCodeLen; int nalUnitStartPos; str = (byteStream_s *)strIn; /* * Copy valid data to the beginning of the buffer */ numRemainingBytes = str->bitbufDataLen - str->bitbufDataPos; if (numRemainingBytes > 0) { memcpy(str->bitbuf, str->bitbuf + str->bitbufDataPos, numRemainingBytes); } /* Update bitbuffer variables */ str->bitbufDataLen = numRemainingBytes; str->bitbufDataPos = 0; /* * Find NAL unit boundaries */ /* Find first start code */ startCodeLen = findStartCode(str); if (startCodeLen == 0) return 0; /* Start address of the NAL unit */ nalUnitStartPos = str->bitbufDataPos - startCodeLen; /* Find second start code */ startCodeLen = findStartCode(str); /* Set data pointer to the beginning of the second start code */ /* (i.e. to the end of the NAL unit) */ if (startCodeLen != 0) str->bitbufDataPos -= startCodeLen; str->bitbufNalunit = str->bitbuf + nalUnitStartPos; str->bitbufNalunitLen = str->bitbufDataPos; return 1;}/* * * postProcessFrame: * * Parameters: * recoBuf Decoded picture * recoFile Reconstruction file * globalStat Statistics * cropFlag True if cropping enabled * * Function: * Note that it can be called only after a whole frame is decoded * * Returns: * - */static void postProcessFrame(avcdYUVbuffer_s *recoBuf, videoFile_s *recoFile, statOverall_s *globalStat, userParam_s *param){ /* Write reconstruction to file */ if (recoFile->enabled) writeFrame(recoBuf, recoFile, param->cropFlag); /* update statistics */ if (recoBuf->picType == 1) { /* An Intra picture */ globalStat->numBitsI += recoBuf->numDecodedBits; globalStat->numIframes += 1; } else { globalStat->numBitsP += recoBuf->numDecodedBits; globalStat->numPframes += 1; } /* Output statistics for the picture */ printf("%d\tbits = %d, \tPSNR Y = %5.2f, \tU = %5.2f, \tV = %5.2f\n", globalStat->numIframes + globalStat->numPframes - 1, recoBuf->numDecodedBits, 0.0, 0.0, 0.0);}#ifndef DECODE_ACCESS_UNITS/* * * main: * * Parameters: * argc Number of parameters * argv Parameter strings * * Function: * Decoder main function * * Returns: * 0 ok * <> 0 error * */int main(int argc, char **argv){ userParam_s param; avcdDecoder_t *decoder; byteStream_s strByte; videoFile_s recoFile; avcdYUVbuffer_s recoBuf; FILE *cumuFp; statOverall_s globalStat; int result, seqEndFlag; /* Parse command line arguments */ if (!parseArg(argc, argv, ¶m)) { usage(); exit(1); } /* Open video & bitstream files */ openFiles(¶m, &recoFile, &strByte); /* Zero out statistics */ memset(&globalStat, 0, sizeof(statOverall_s)); /* Open sequence */ decoder = avcdOpen(param.ecAlg); if (decoder == NULL) { fprintf(stderr, "Could not open sequence\n"); exit(1); } /* * Main decoder loop. Frames are decoded until there are no more frames. */ seqEndFlag = 0; result = AVCD_OK; while (!seqEndFlag) { /* result == AVCD_OK_STREAM_NOT_DECODED -> don't update bitbuffer */ if (result != AVCD_OK_STREAM_NOT_DECODED) { if (!getNalunitBits_ByteStream(&strByte)) { strByte.bitbufNalunit = 0; strByte.bitbufNalunitLen = 0; } } /* Decode one NAL unit */ result = avcdDecodeOneNal(decoder, strByte.bitbufNalunit, strByte.bitbufNalunitLen, &recoBuf); switch (result) { case AVCD_OK: case AVCD_OK_STREAM_NOT_DECODED: postProcessFrame(&recoBuf, &recoFile, &globalStat, ¶m); break; case AVCD_OK_FRAME_NOT_AVAILABLE: if (strByte.bitbufNalunit == 0 && strByte.bitbufNalunitLen == 0) seqEndFlag = 1; break; case AVCD_ERROR: default: fprintf(stderr, "Error occured in AVC decoder\n"); seqEndFlag = 1; break; } } /* Close sequence */ avcdClose(decoder); /* Close video & bitstream files */ closeFiles(&recoFile, &strByte); /* Print decoding time */ printf("took %3.3f seconds\n", (double)clock()/CLOCKS_PER_SEC); /* Append short sequence statistics to -cumul file if file present */ if (param.cumuFile != NULL) { if ((cumuFp = fopen(param.cumuFile, "a")) != NULL) { printSeqStat(&globalStat, 0, 0, cumuFp); fclose(cumuFp); } } /* print a brief report */ printf("Total frames being decoded: %d\nI: %d, P: %d\n", globalStat.numIframes + globalStat.numPframes, globalStat.numIframes, globalStat.numPframes); printf("Total bits: %d\nI: %d, P: %d\n", globalStat.numBitsI + globalStat.numBitsP, globalStat.numBitsI, globalStat.numBitsP); return 0;}#else#define NUM_SLICES_PER_PICTURE 1/* * * main: * * Parameters: * argc Number of parameters * argv Parameter strings * * Function: * This main function calls avcdDecodeOneFrame() instead of avcdDecodeOneNal() * * Returns: * 0 ok * <> 0 error * */int main(int argc, char **argv){ userParam_s param; avcdDecoder_t *decoder; byteStream_s strByte; videoFile_s recoFile; avcdYUVbuffer_s recoBuf; int firstSliceFlag; FILE *cumuFp; statOverall_s globalStat; int result, seqEndFlag; char tmpBuf[30000]; char *tmpPtr; int tmpBufLen; int frameNum = 0; int numSlices; /* Parse command line arguments */ if (!parseArg(argc, argv, ¶m)) { usage(); exit(1); } /* Open video & bitstream files */ openFiles(¶m, &recoFile, &strByte); /* Zero out statistics */ memset(&globalStat, 0, sizeof(statOverall_s)); /* Open sequence */ decoder = avcdOpen(); if (decoder == NULL) { fprintf(stderr, "Could not open sequence\n"); exit(1); } /* * Main decoder loop. Frames are decoded until there are no more frames. */ firstSliceFlag = 1; seqEndFlag = 0; result = AVCD_OK; tmpPtr = 0; tmpBufLen = 0; while (!seqEndFlag) { /* * Get one frame NAL units. */ /* result == AVCD_OK_STREAM_NOT_DECODED -> don't update bitbuffer */ if (result != AVCD_OK_STREAM_NOT_DECODED) { tmpPtr = tmpBuf; tmpBufLen = 0; numSlices = 0; do { if (!getNalunitBits_ByteStream(&strByte)) { if (tmpBufLen == 0) tmpPtr = 0; break; } memcpy(tmpPtr+tmpBufLen, strByte.bitbufNalunit, strByte.bitbufNalunitLen); tmpBufLen += strByte.bitbufNalunitLen; if (!((strByte.bitbufNalunit[4]&31) == 7 || (strByte.bitbufNalunit[4]&31) == 8)) numSlices++; } while (numSlices < NUM_SLICES_PER_PICTURE); } /* * Decode NAL units. */ result = avcdDecodeOneFrame(decoder, tmpPtr, tmpBufLen, &recoBuf); switch (result) { case AVCD_OK: case AVCD_OK_STREAM_NOT_DECODED: postProcessFrame(&recoBuf, &recoFile, &globalStat, ¶m); break; case AVCD_OK_FRAME_NOT_AVAILABLE: if (tmpPtr == 0 && tmpBufLen == 0) seqEndFlag = 1; break; case AVCD_ERROR: default: fprintf(stderr, "Error occured in AVC decoder\n"); seqEndFlag = 1; break; } frameNum++; } /* Close sequence */ avcdClose(decoder); /* Close video & bitstream files */ closeFiles(&recoFile, &strByte); /* Print decoding time */ printf("took %3.3f seconds\n", (double)clock()/CLOCKS_PER_SEC); /* Append short sequence statistics to -cumul file if file present */ if (param.cumuFile != NULL) { if ((cumuFp = fopen(param.cumuFile, "a")) != NULL) { printSeqStat(&globalStat, 0, 0, cumuFp); fclose(cumuFp); } } /* print a brief report */ printf("Total frames being decoded: %d\nI: %d, P: %d\n", globalStat.numIframes + globalStat.numPframes, globalStat.numIframes, globalStat.numPframes); printf("Total bits: %d\nI: %d, P: %d\n", globalStat.numBitsI + globalStat.numBitsP, globalStat.numBitsI, globalStat.numBitsP); return 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -