2014-07-10 2 views
0

Wireshark 및 VLC를 사용하여 RTP h264 스트림을 저장할 수 있음을 알고 있습니다. 그러나 비디오 스트리밍에 대해 더 많이 배우려면 직접 해보려합니다. 이 주제에 대한 좋은 독서 있도록 여러 관련 질문이 있습니다 배경으로 그와H264 RTP 패킷을 유용한 형태로 저장

How to process raw UDP packets so that they can be decoded by a decoder filter in a directshow source filter

Problem to Decode H264 video over RTP with ffmpeg (libavcodec)

How to convert H.264 UDP packets to playable media stream or file (defragmentation)

내가 현재 나는 곳이입니다 :

  • UTP를 통해 RTP 패킷을받을 수 있습니다.
  • 위의 질문에서 설명한대로 패킷을 구문 분석합니다.
  • \ x000001로 구분 된 파일에 패킷을 쓰고 위의 지침에 따라 NAL 바이트를 다시 추가합니다.
  • 파일의 시작 부분에 나는 내 코드의 RTSP 대화에서 얻은 SPS와 PPS를 서버와 (다시 정확한 바이트로 구분하여) 넣었다.

결국 NAL 프레임이 많은 파일로 끝납니다. 그런 다음 .mp4를 만들기 위해 .264 파일에서 ffmpeg를 실행 해 봅니다.

[H264 @ 0x15257a0] decode_slice_header 오류

[H264 @ 0x15257a0] 어떤 프레임이 몇 가지 오류가납니다!

[H264 @ 0x15257a0] PPS는

참조한 존재하지 않는 [H264 @ 0x15257a0] PPS 0이 아닌 기존

을 참조 [버퍼 @ 0x15e16a0] 잘못된 픽셀 형식 문자열 -1

나는이 문제를 알아낼 때까지 본질적으로 정지 상태에있다. 위의 링크 된 질문을 thouroughly 읽고 내가 VLC를 통해 연결하고 볼 수 있기 때문에 스트림을 확실히 볼 수 있으며 들어오는 패킷은 분명히 wireshark에 따라 H264 RTP 패킷입니다. VLC가 그것을 할 수 있다면 왜 안돼! 나는 나의 오류에 대한 어떤 통찰력과 그것들 사이의 불일치를 해결하는 세 가지 연결된 질문에 대한 요약을 매우 높이 평가할 것이다.

답변

0

How to process raw UDP packets so that they can be decoded by a decoder filter in a directshow source filter

그것은 답이 필요했다 참조하지만 프로세스는 다음과 같이이다 :

//Determine if the forbidden bit is set and the type of nal from the first byte 
      byte firstByte = packetData[offset]; 

      //bool forbiddenZeroBit = ((firstByte & 0x80) >> 7) != 0; 

      byte nalUnitType = (byte)(firstByte & Common.Binary.FiveBitMaxValue); 

      //o The F bit MUST be cleared if all F bits of the aggregated NAL units are zero; otherwise, it MUST be set. 
      //if (forbiddenZeroBit && nalUnitType <= 23 && nalUnitType > 29) throw new InvalidOperationException("Forbidden Zero Bit is Set."); 

      //Determine what to do 
      switch (nalUnitType) 
      { 
       //Reserved - Ignore 
       case 0: 
       case 30: 
       case 31: 
        { 
         return; 
        } 
       case 24: //STAP - A 
       case 25: //STAP - B 
       case 26: //MTAP - 16 
       case 27: //MTAP - 24 
        { 
         //Move to Nal Data 
         ++offset; 

         //Todo Determine if need to Order by DON first. 
         //EAT DON for ALL BUT STAP - A 
         if (nalUnitType != 24) offset += 2; 

         //Consume the rest of the data from the packet 
         while (offset < count) 
         { 
          //Determine the nal unit size which does not include the nal header 
          int tmp_nal_size = Common.Binary.Read16(packetData, offset, BitConverter.IsLittleEndian); 
          offset += 2; 

          //If the nal had data then write it 
          if (tmp_nal_size > 0) 
          { 
           //For DOND and TSOFFSET 
           switch (nalUnitType) 
           { 
            case 25:// MTAP - 16 
             { 
              //SKIP DOND and TSOFFSET 
              offset += 3; 
              goto default; 
             } 
            case 26:// MTAP - 24 
             { 
              //SKIP DOND and TSOFFSET 
              offset += 4; 
              goto default; 
             } 
            default: 
             { 
              //Read the nal header but don't move the offset 
              byte nalHeader = (byte)(packetData[offset] & Common.Binary.FiveBitMaxValue); 

              if (nalHeader > 5) 
              { 
               if (nalHeader == 6) 
               { 
                Buffer.WriteByte(0); 
                containsSei = true; 
               } 
               else if (nalHeader == 7) 
               { 
                Buffer.WriteByte(0); 
                containsPps = true; 
               } 
               else if (nalHeader == 8) 
               { 
                Buffer.WriteByte(0); 
                containsSps = true; 
               } 
              } 

              if (nalHeader == 1) containsSlice = true; 

              if (nalHeader == 5) isIdr = true; 

              //Done reading 
              break; 
             } 
           } 

           //Write the start code 
           Buffer.Write(NalStart, 0, 3); 

           //Write the nal header and data 
           Buffer.Write(packetData, offset, tmp_nal_size); 

           //Move the offset past the nal 
           offset += tmp_nal_size; 
          } 
         } 

         return; 
        } 
       case 28: //FU - A 
       case 29: //FU - B 
        { 
         /* 
         Informative note: When an FU-A occurs in interleaved mode, it 
         always follows an FU-B, which sets its DON. 
         * Informative note: If a transmitter wants to encapsulate a single 
          NAL unit per packet and transmit packets out of their decoding 
          order, STAP-B packet type can be used. 
         */ 
         //Need 2 bytes 
         if (count > 2) 
         { 
          //Read the Header 
          byte FUHeader = packetData[++offset]; 

          bool Start = ((FUHeader & 0x80) >> 7) > 0; 

          //bool End = ((FUHeader & 0x40) >> 6) > 0; 

          //bool Receiver = (FUHeader & 0x20) != 0; 

          //if (Receiver) throw new InvalidOperationException("Receiver Bit Set"); 

          //Move to data 
          ++offset; 

          //Todo Determine if need to Order by DON first. 
          //DON Present in FU - B 
          if (nalUnitType == 29) offset += 2; 

          //Determine the fragment size 
          int fragment_size = count - offset; 

          //If the size was valid 
          if (fragment_size > 0) 
          { 
           //If the start bit was set 
           if (Start) 
           { 
            //Reconstruct the nal header 
            //Use the first 3 bits of the first byte and last 5 bites of the FU Header 
            byte nalHeader = (byte)((firstByte & 0xE0) | (FUHeader & Common.Binary.FiveBitMaxValue)); 

            //Could have been SPS/PPS/SEI 
            if (nalHeader > 5) 
            { 
             if (nalHeader == 6) 
             { 
              Buffer.WriteByte(0); 
              containsSei = true; 
             } 
             else if (nalHeader == 7) 
             { 
              Buffer.WriteByte(0); 
              containsPps = true; 
             } 
             else if (nalHeader == 8) 
             { 
              Buffer.WriteByte(0); 
              containsSps = true; 
             } 
            } 

            if (nalHeader == 1) containsSlice = true; 

            if (nalHeader == 5) isIdr = true; 

            //Write the start code 
            Buffer.Write(NalStart, 0, 3); 

            //Write the re-construced header 
            Buffer.WriteByte(nalHeader); 
           } 

           //Write the data of the fragment. 
           Buffer.Write(packetData, offset, fragment_size); 
          } 
         } 
         return; 
        } 
       default: 
        { 
         // 6 SEI, 7 and 8 are SPS and PPS 
         if (nalUnitType > 5) 
         { 
          if (nalUnitType == 6) 
          { 
           Buffer.WriteByte(0); 
           containsSei = true; 
          } 
          else if (nalUnitType == 7) 
          { 
           Buffer.WriteByte(0); 
           containsPps = true; 
          } 
          else if (nalUnitType == 8) 
          { 
           Buffer.WriteByte(0); 
           containsSps = true; 
          } 
         } 

         if (nalUnitType == 1) containsSlice = true; 

         if (nalUnitType == 5) isIdr = true; 

         //Write the start code 
         Buffer.Write(NalStart, 0, 3); 

         //Write the nal heaer and data data 
         Buffer.Write(packetData, offset, count - offset); 

         return; 
        } 
관련 문제