📄 sequence.c
字号:
seq->unusedShortTermFrameNum = nextFrameNum; seq->conceal = 1; /* If dpb was not full we can recover lost frames */ if (numOutput == 0) numOutput = concealFrames(seq); } else#endif { /* * Start filling in gaps in frame numbers */ seq->unusedShortTermFrameNum = nextFrameNum;#ifdef ERROR_CONCEALMENT seq->conceal = 0;#endif /* If dpb was not full (i.e. we did not have to output any pictures), */ /* we can generate non-existing frames. */ if (numOutput == 0) numOutput = generateNonExistingFrames(seq); } } if (numOutput == 0) /* If there are no pictures in output queue we can decode next slice */ return decodeSliceData(seq); else { /* Don't decode slice since it belongs to next picture and */ /* we don't have space for new picture. */ seq->isSliceDataDecodePending = 1; return SEQ_OK; } }}#ifdef ERROR_CONCEALMENT/* * * decodeSei: * * Parameters: * seq Sequence object * * Function: * Decode SEI message * * Returns: * SEQ_OK for ok, negative value for error */static int decodeSei(sequence_s *seq){ int payloadType; int payloadSize; int byte; int retCode; bitbuffer_s *bitbuf; sceneInfo_s *scene; bitbuf = seq->bitbuf; while (bibMoreRbspData(bitbuf)) { payloadType = 0; bibGetByte(bitbuf, &byte); while (byte == 0xff) { payloadType += byte; bibGetByte(bitbuf, &byte); } payloadType += byte; payloadSize = 0; bibGetByte(bitbuf, &byte); while (byte == 0xff) { payloadSize += byte; bibGetByte(bitbuf, &byte); } payloadSize += byte; switch (payloadType) { case SEI_TYPE_SCENE_INFO: seq->hasSceneInfo = 1; scene = seq->currSceneInfo; seq->currSceneInfo = seq->prevSceneInfo; seq->prevSceneInfo = scene; if ((retCode = seiSceneInfo(seq->currSceneInfo, bitbuf)) < 0) return retCode; seq->sceneInfoDecoded = 1; break; default: deb1f(stderr, "The decoder does not support the SEI message in type of %d\n", payloadType); bitbuf->bytePos += payloadSize; // skip the content of the SEI payload. break; } } return SEQ_OK;}#endif/* * * avcdDecodeOneNal: * * Parameters: * seq Sequence object * nalUnitBits Bits for NAL unit to be decoded * nalUnitLen Number of bytes in NAL unit * * Function: * Return output picture immediately if available. Otherwise finish any * pending tasks from previous call such as storing of current frame to * dpb, generation of non-existing frames (to fill in gaps in frame * numbers) and decoding of current slice data. If any of the tasks * did not exit the function, start decoding NAL unit. * * Returns: * AVCD_OK: Nal unit decoded and frame available * AVCD_OK_FRAME_NOT_AVAILABLE: Nal unit decoded, frame not available * AVCD_OK_STREAM_NOT_DECODED: Nal unit not decoded, frame available * AVCD_ERROR: Error occured * */int avcdDecodeOneNal(avcdDecoder_t *dec, void *nalUnitBits, int nalUnitLen, avcdYUVbuffer_s *outBuf){ sequence_s *seq = (sequence_s *)dec; int nalHeaderByte; int nalType; int nalRefIdc; int ret; /* * The following conditions are tested to see what is the current decoder state * and to act upon that state: * * - Check if picture can be output from output queue without further decoding. * - Check if dpb store is pending (i.e current picture was not be * stored to dpb during previous call because dpb was full). * - Check any non-existing frames should be generated (i.e there were gaps in * frame number). If non-existing frame(s) were generated, check output * queue again. * - Check for end of stream. If end of stream was reached then current picture * is finished if not yet finished. Check again whether picture can be output * from either output queue or dpb (check is internal to getOutputPic(...)). * - Check if slice decode is pending (i.e only header of the latest slice was * decoded during previous call and we now need to decode slice data) and if * so, decode slice data. * - Check any lost frames being recovered (i.e there were ref frames lost) * If lost frames were rescued, check output queue again. */ /* We can return immediately if there are queued output pics */ if (seq->numQueuedOutputPics > 0) { getOutputPic(seq, outBuf); return AVCD_OK_STREAM_NOT_DECODED; } /* Is current picture waiting to be moved to DPB? */ if (seq->isDpbStorePending) { if (dpbStorePicture(seq->dpb, seq->recoBuf, seq->outputQueue) != 0) { deb0f(stderr, "Error: dpb store failed\n"); return AVCD_ERROR; } seq->isDpbStorePending = 0; } /* Are there non-existing frames to be generated? */ /* Or are there any lost frames to be rescued? */ if (seq->unusedShortTermFrameNum >= 0) {#ifdef ERROR_CONCEALMENT if (seq->conceal) { ret = concealFrames(seq); if (ret < 0) return AVCD_ERROR; else if (ret != 0) { getOutputPic(seq, outBuf); return AVCD_OK_STREAM_NOT_DECODED; } } else#endif { ret = generateNonExistingFrames(seq); if (ret < 0) return AVCD_ERROR; else if (ret != 0) { getOutputPic(seq, outBuf); return AVCD_OK_STREAM_NOT_DECODED; } } } /* Check for end of stream */ if (nalUnitBits == 0 || nalUnitLen == 0) { if (!seq->isSeqFinished && seq->recoBuf != NULL) { if (finishCurrentPic(seq) < 0) return AVCD_ERROR; seq->isSeqFinished = 1; } /* Check for output */ if (getOutputPic(seq, outBuf)) return AVCD_OK; else return AVCD_OK_FRAME_NOT_AVAILABLE; } /* Decode slice data if slice decode is pending */ if (seq->isSliceDataDecodePending) { decodeSliceData(seq); return AVCD_OK_FRAME_NOT_AVAILABLE; } /* * Decode new NAL unit */ /* Initialize bitbuffer and get first byte containing NAL type and NAL ref idc */ if (bibInit(seq->bitbuf, (u_int8 *)nalUnitBits, nalUnitLen) < 0) return AVCD_ERROR; if (bibGetByte(seq->bitbuf, &nalHeaderByte)) return AVCD_ERROR; /* Decode NAL unit type and reference indicator */ nalType = nalHeaderByte & 0x1F; nalRefIdc = (nalHeaderByte & 0x60) >> 5; /* Decode NAL unit data */ switch (nalType) { case NAL_TYPE_CODED_SLICE: // 1 decodeSlice(seq, nalType, nalRefIdc); break; case NAL_TYPE_CODED_SLICE_P_A: // 2 case NAL_TYPE_CODED_SLICE_P_B: // 3 case NAL_TYPE_CODED_SLICE_P_C: // 4 deb1f(stderr, "Slice data partition NAL type (%i) not supported.\n", nalType); return AVCD_ERROR; break; case NAL_TYPE_CODED_SLICE_IDR: // 5 decodeSlice(seq, nalType, nalRefIdc); break; case NAL_TYPE_SEI: // 6#ifdef ERROR_CONCEALMENT decodeSei(seq);#else deb0f(stderr, "SEI NAL unit (6) skipped.\n");#endif break; case NAL_TYPE_SPS: // 7 if (psDecodeSPS(seq->bitbuf, seq->spsList) < 0) return AVCD_ERROR; break; case NAL_TYPE_PPS: // 8 if (psDecodePPS(seq->bitbuf, seq->ppsList) < 0) return AVCD_ERROR; break; case NAL_TYPE_PIC_DELIMITER: // 9 deb0f(stderr, "Picture Delimiter NAL unit (9) skipped.\n"); break; case NAL_TYPE_END_SEQ: // 10 deb0f(stderr, "End of Sequence NAL unit (10) skipped.\n"); break; case NAL_TYPE_END_STREAM: // 11 deb0f(stderr, "End of Stream NAL unit (11) skipped.\n"); break; case NAL_TYPE_FILLER_DATA: // 12 deb0f(stderr, "FIller Data NAL unit (12) skipped.\n"); break; default: /* Unspecied NAL types 0 and 24-31 */ if (nalType == 0 || (nalType >= 24 && nalType <= 31)) deb1f(stderr, "Unspecified NAL type: (%i)\n", nalType); /* Reserved NAL types 13-23 */ else deb1f(stderr, "Reserved NAL type (%i)\n", nalType); break; } /* * Check the output queue once again */ if (getOutputPic(seq, outBuf)) { if (seq->isSliceDataDecodePending) /* We have output picture, but current slice has not been decoded */ return AVCD_OK_STREAM_NOT_DECODED; else return AVCD_OK; } else { if (seq->isSliceDataDecodePending) { /* If queue is empty, there should be no slice data left for current slice */ deb0f(stderr, "Something wrong here...\n"); } return AVCD_OK_FRAME_NOT_AVAILABLE; }}#ifdef DECODE_ACCESS_UNITS/* * * findStartCode: * * Parameters: * ptr Pointer to byte stream * len Length of byte stream * offset Search start position * startCodeLen Return pointer for start code langth * * Function: * First next start code in byte stream * * Returns: * Start code position if found or length of byte stream if * start code was not found * */static int findStartCode(u_int8 *ptr, int len, int offset, int *startCodeLen){ int numZeros = 0; while (offset < len) { if (ptr[offset] == 0) numZeros++; else if (ptr[offset] == 1 && numZeros > 1) { *startCodeLen = numZeros + 1; return offset - numZeros; } else numZeros = 0; offset++; } return len;}/* * * avcdDecodeOneFrame: * * Parameters: * dec Sequence object * frameBitsPtr Bits for frame * frameBitsLen Number of bytes in frame * outBuf Output buffer * * Function: * Decode frame. * * Returns: * AVCD_OK: Frame decoded and frame available * AVCD_OK_FRAME_NOT_AVAILABLE: Frame decoded, frame not available * AVCD_OK_STREAM_NOT_DECODED: Frame not decoded, frame available * AVCD_ERROR: Error occured * */int avcdDecodeOneFrame(avcdDecoder_t *dec, void *frameBitsPtr, int frameBitsLen, avcdYUVbuffer_s *outBuf){ sequence_s *seq = (sequence_s *)dec; int isStreamEnd; int isFrameEnd; void *nalBitsPtr; int nalBitsLen; int numOutput; /* If previous frame was completely decoded, start decoding */ /* this frame from the beginning. */ if (seq->decResult != AVCD_OK_STREAM_NOT_DECODED) seq->streamPos = 0; /* Check if end of stream (Empty NAL unit) */ if (frameBitsPtr == 0 || frameBitsLen == 0) { seq->isSeqFinished = 1; isStreamEnd = 1; } else isStreamEnd = 0; isFrameEnd = 0; /* * Decode all NAL units of the frame one NAL unit at a time. * avcdDecodeOneNal() is called for each NAL unit. */ do { if (isStreamEnd) { nalBitsPtr = 0; nalBitsLen = 0; } else if (seq->decResult != AVCD_OK_STREAM_NOT_DECODED) { int nalStart; int nalStart2; int startCodeLen; int startCodeLen2; /* Find first start code */ nalStart = findStartCode(frameBitsPtr, frameBitsLen, seq->streamPos, &startCodeLen); if (nalStart != seq->streamPos) { deb0f(stderr, "Error in byte stream\n"); return AVCD_ERROR; } /* Find second start code */ nalStart2 = findStartCode(frameBitsPtr, frameBitsLen, nalStart+startCodeLen, &startCodeLen2); if (nalStart2-nalStart-startCodeLen < 1) { // 1 is minimum NAL unit length deb0f(stderr, "Error in byte stream\n"); return AVCD_ERROR; } /* Move stream pointer to next NAL unit */ seq->streamPos = nalStart2; nalBitsPtr = (u_int8 *)frameBitsPtr + nalStart; nalBitsLen = nalStart2-nalStart; } else { /* Previous NAL unit was not decoded -> give some non-zero input */ /* to avcdDecodeOneNal to finish decoding previous NAL unit. */ /* There is no need to give exact bit pointer in this case because */ /* avcdDecodeOneNal has stored pointer for unfinished NAL unit. */ nalBitsPtr = frameBitsPtr; nalBitsLen = 1; } /* Decode NAL unit and check result */ seq->decResult = avcdDecodeOneNal(dec, nalBitsPtr, nalBitsLen, outBuf); /* If there are no more bits in the stream and we got no frame, we */ /* know that all frames have been decoded and output. */ if (isStreamEnd && seq->decResult == AVCD_OK_FRAME_NOT_AVAILABLE) isFrameEnd = 1; /* If we have decoded all NAL units of the frame, we can go */ if (!isStreamEnd && seq->streamPos >= frameBitsLen) isFrameEnd = 1; /* Decode until we are at the end of frame or ouput picture is available */ } while (!isFrameEnd && seq->decResult == AVCD_OK_FRAME_NOT_AVAILABLE); /* * If we are not at the end of stream and there is no frame available * for output, we can finish current frame. */ if (!isStreamEnd && seq->decResult == AVCD_OK_FRAME_NOT_AVAILABLE) {#ifdef ERROR_CONCEALMENT pic_parameter_set_s *pps; pps = seq->ppsList[seq->currSlice->pic_parameter_set_id]; /* Check if we need to coceal macroblocks */ ercCheckAndConceal(seq->errConcealment, seq->recoBuf, seq->mbData, seq->dpb, pps);#endif /* Finish decoding of current picture */ numOutput = finishCurrentPic(seq); /* numOutput is the number of pictures in output queue */ /* If numOutput < 0, error occured */ if (numOutput < 0) return AVCD_ERROR; /* Check if frame is available for output */ if (getOutputPic(seq, outBuf)) seq->decResult = AVCD_OK; else seq->decResult = AVCD_OK_FRAME_NOT_AVAILABLE; } return seq->decResult;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -