在项目开发过程中遇到一个问题,play之后,不能推送rtp数据包,跟踪代码调试发现,在获取H264视频数据,封包,发送,这条循环的链断开了,导致该问题的原因是:
在H264VideoStreamFramer.cpp中
unsigned H264VideoStreamParser::parse() { #if DEBUG_SHOWCHN printf("Parser() chn:%d\n", fchn); #endif try{ // The stream must start with a 0x00000001: if (!fHaveSeenFirstStartCode) { // Skip over any input bytes that precede the first 0x00000001: u_int32_t first4Bytes; while ((first4Bytes = test4Bytes()) != 0x00000001) { get1Byte(); setParseState(); // ensures that we progress over bad data } skipBytes(4); // skip this initial code setParseState(); fHaveSeenFirstStartCode = True; // from now on } if (fOutputStartCodeSize > 0 && curFrameSize() == 0 && !haveSeenEOF()) { // Include a start code in the output: save4Bytes(0x00000001); } // Then save everything up until the next 0x00000001 (4 bytes) or 0x000001 (3 bytes), or we hit EOF. // Also make note of the first byte, because it contains the "nal_unit_type": if (haveSeenEOF()) { // We hit EOF the last time that we tried to parse this data, so we know that any remaining unparsed data // forms a complete NAL unit, and that there's no 'start code' at the end: unsigned remainingDataSize = totNumValidBytes() - curOffset(); #ifdef DEBUG unsigned const trailingNALUnitSize = remainingDataSize; #endif while (remainingDataSize > 0) { u_int8_t nextByte = get1Byte(); if (!fHaveSeenFirstByteOfNALUnit) { fFirstByteOfNALUnit = nextByte; fHaveSeenFirstByteOfNALUnit = True; } saveByte(nextByte); --remainingDataSize; } #ifdef DEBUG u_int8_t nal_ref_idc = (fFirstByteOfNALUnit&0x60)>>5; u_int8_t nal_unit_type = fFirstByteOfNALUnit&0x1F; fprintf(stderr, "Parsed trailing %d-byte NAL-unit (nal_ref_idc: %d, nal_unit_type: %d (\"%s\"))\n", trailingNALUnitSize, nal_ref_idc, nal_unit_type, nal_unit_type_description[nal_unit_type]); #endif (void)get1Byte(); // forces another read, which will cause EOF to get handled for real this time return 0; } else { u_int32_t next4Bytes = test4Bytes(); if (!fHaveSeenFirstByteOfNALUnit) { fFirstByteOfNALUnit = next4Bytes>>24; fHaveSeenFirstByteOfNALUnit = True; } /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// //如果获取的H264数据不完整或错误 只有帧头 没有帧体curFrameSize()会等于0 while (next4Bytes != 0x00000001 && (next4Bytes&0xFFFFFF00) != 0x00000100) { // We save at least some of "next4Bytes". if ((unsigned)(next4Bytes&0xFF) > 1) { // Common case: 0x00000001 or 0x000001 definitely doesn't begin anywhere in "next4Bytes", so we save all of it: save4Bytes(next4Bytes); skipBytes(4); } else { // Save the first byte, and continue testing the rest: saveByte(next4Bytes>>24); skipBytes(1); } setParseState(); // ensures forward progress next4Bytes = test4Bytes(); } // Assert: next4Bytes starts with 0x00000001 or 0x000001, and we've saved all previous bytes (forming a complete NAL unit). // Skip over these remaining bytes, up until the start of the next NAL unit: if (next4Bytes == 0x00000001) { skipBytes(4); } else { skipBytes(3); } } u_int8_t nal_ref_idc = (fFirstByteOfNALUnit&0x60)>>5; u_int8_t nal_unit_type = fFirstByteOfNALUnit&0x1F; fHaveSeenFirstByteOfNALUnit = False; // for the next NAL unit that we parse #ifdef DEBUG fprintf(stderr, "Parsed %d-byte NAL-unit (nal_ref_idc: %d, nal_unit_type: %d (\"%s\"))\n", curFrameSize()-fOutputStartCodeSize, nal_ref_idc, nal_unit_type, nal_unit_type_description[nal_unit_type]); #endif switch (nal_unit_type) { case 6: { // Supplemental enhancement information (SEI) analyze_sei_data(); // Later, perhaps adjust "fPresentationTime" if we saw a "pic_timing" SEI payload??? ##### break; } case 7: { // Sequence parameter set // First, save a copy of this NAL unit, in case the downstream object wants to see it: usingSource()->saveCopyOfSPS(fStartOfFrame + fOutputStartCodeSize, fTo - fStartOfFrame - fOutputStartCodeSize); // Parse this NAL unit to check whether frame rate information is present: unsigned num_units_in_tick, time_scale, fixed_frame_rate_flag; analyze_seq_parameter_set_data(num_units_in_tick, time_scale, fixed_frame_rate_flag); if (time_scale > 0 && num_units_in_tick > 0) { usingSource()->fFrameRate = time_scale/(2.0*num_units_in_tick); #ifdef DEBUG fprintf(stderr, "Set frame rate to %f fps\n", usingSource()->fFrameRate); if (fixed_frame_rate_flag == 0) { fprintf(stderr, "\tWARNING: \"fixed_frame_rate_flag\" was not set\n"); } #endif } else { #ifdef DEBUG fprintf(stderr, "\tThis \"Sequence Parameter Set\" NAL unit contained no frame rate information, so we use a default frame rate of %f fps\n", usingSource()->fFrameRate); #endif } break; } case 8: { // Picture parameter set // Save a copy of this NAL unit, in case the downstream object wants to see it: usingSource()->saveCopyOfPPS(fStartOfFrame + fOutputStartCodeSize, fTo - fStartOfFrame - fOutputStartCodeSize); } } usingSource()->setPresentationTime(); #ifdef DEBUG unsigned long secs = (unsigned long)usingSource()->fPresentationTime.tv_sec; unsigned uSecs = (unsigned)usingSource()->fPresentationTime.tv_usec; //fprintf(stderr, "\tPresentation time: %lu.%06u\n", secs, uSecs); #endif // We check whether this NAL unit ends an 'access unit'. // (RTP streamers need to know this in order to figure out whether or not to set the "M" bit.) Boolean thisNALUnitEndsAccessUnit; if (haveSeenEOF() || nal_unit_type == 11/*End of stream*/) { // There is no next NAL unit, so we assume that this one ends the current 'access unit': thisNALUnitEndsAccessUnit = True; } else if ((nal_unit_type >= 6 && nal_unit_type <= 9) || (nal_unit_type >= 14 && nal_unit_type <= 18)) { // These NAL units usually *begin* an access unit, so we assume that they don't end one here: thisNALUnitEndsAccessUnit = False; } else { // We need to check the *next* NAL unit to figure out whether the current NAL unit ends an 'access unit': u_int8_t firstBytesOfNextNALUnit[2]; testBytes(firstBytesOfNextNALUnit, 2); u_int8_t const& next_nal_unit_type = firstBytesOfNextNALUnit[0]&0x1F; Boolean const nextNALUnitIsVCL = next_nal_unit_type <= 5 && nal_unit_type > 0; if (nextNALUnitIsVCL) { // The high-order bit of the 2nd byte tells us whether this is the start of a new 'access unit': thisNALUnitEndsAccessUnit = (firstBytesOfNextNALUnit[1]&0x80) != 0; } else if ((next_nal_unit_type >= 6 && next_nal_unit_type <= 9) || (next_nal_unit_type >= 14 && next_nal_unit_type <= 18)) { // The next NAL unit's type is one that usually appears at the start of an 'access unit', // so we assume that the current NAL unit ends an 'access unit': thisNALUnitEndsAccessUnit = True; } else { // The next NAL unit definitely doesn't start a new 'access unit', which means that the current NAL unit doesn't end one: thisNALUnitEndsAccessUnit = False; } } if (thisNALUnitEndsAccessUnit) { #ifdef DEBUG fprintf(stderr, "*****This NAL unit ends the current access unit*****\n"); #endif usingSource()->fPictureEndMarker = True; ++usingSource()->fPictureCount; // Note that the presentation time for the next NAL unit will be different: struct timeval& nextPT = usingSource()->fNextPresentationTime; // alias nextPT = usingSource()->fPresentationTime; double nextFraction = nextPT.tv_usec/1000000.0 + 1/usingSource()->fFrameRate; unsigned nextSecsIncrement = (long)nextFraction; nextPT.tv_sec += (long)nextSecsIncrement; nextPT.tv_usec = (long)((nextFraction - nextSecsIncrement)*1000000); } setParseState(); #if DEBUG_SHOWCHN printf("parse() return curFrameSize()=%d chn:%d\n", curFrameSize(), fchn); #endif /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// //如果返回的curFrameSize()等于0, 获取视频 封包 发送 这个循环的过程就终止了 //返回后使程序能循环转起来的回调函数调用不到了 所以增加如下代码 if (0 == curFrameSize()) { #if DEBUG_SHOWCHN printf("curFrameSize = 0 parse again chn:%d\n", fchn); #endif fHaveSeenFirstStartCode = false; parse(); } return curFrameSize(); } catch (int /*e*/) { #ifdef DEBUG //fprintf(stderr, "H264VideoStreamParser::parse() EXCEPTION (This is normal behavior - *not* an error)\n"); #endif return 0; // the parsing got interrupted } }
时间: 2024-10-13 10:41:11