예제 #1
0
        public bool FeedAudioData(InputStream pData, uint dataLength, ref RTPHeader rtpHeader)
        {
            if (_audioSequence == 0)
            {
                //this is the first packet. Make sure we start with a M packet
                if (!rtpHeader.M)
                {
                    return(true);
                }
                _audioSequence = rtpHeader.SEQ;
                return(true);
            }
            else
            {
                if (_audioSequence + 1 != rtpHeader.SEQ)
                {
                    WARN("Missing audio packet. Wanted: {0}; got: {1} on stream: {2}",
                         (_audioSequence + 1), rtpHeader.SEQ, Name);
                    _audioDroppedPacketsCount++;
                    _audioSequence = 0;
                    return(true);
                }
                else
                {
                    _audioSequence++;
                }
            }
            //1. Compute chunks count
            var chunksCount = pData.Reader.ReadUInt16();

            if ((chunksCount % 16) != 0)
            {
                FATAL("Invalid AU headers length: {0}", chunksCount);
                return(false);
            }
            chunksCount = (ushort)(chunksCount >> 4);

            //3. Feed the buffer chunk by chunk
            var cursor = 2u + 2u * chunksCount;
            var rtpTs  = ComputeRTP(ref rtpHeader.Timestamp, ref _audioLastRTP, ref _audioRTPRollCount);

            for (var i = 0; i < chunksCount; i++)
            {
                uint chunkSize;
                if (i != (chunksCount - 1))
                {
                    chunkSize = (uint)((pData.Reader.ReadUInt16()) >> 3);
                }
                else
                {
                    chunkSize = dataLength - cursor;
                }
                uint ts = (uint)((rtpTs + (ulong)i * 1024ul) * 1000 / Capabilities.Samplerate);
                if ((cursor + chunkSize) > dataLength)
                {
                    FATAL("Unable to feed data: cursor:{0}; chunkSize: {1}; dataLength: {2}; chunksCount: {3}",
                          cursor, chunkSize, dataLength, chunksCount);
                    return(false);
                }
                _audioPacketsCount++;
                _audioBytesCount += chunkSize;
                if (!FeedData(pData,
                              chunkSize + 2,
                              0,
                              chunkSize + 2,
                              ts, true))
                {
                    FATAL("Unable to feed data");
                    return(false);
                }
                cursor += chunkSize;
            }

            return(true);
        }
예제 #2
0
        public bool FeedVideoData(InputStream pData, uint dataLength, ref RTPHeader rtpHeader)
        {
            var firstByte  = pData.Reader.ReadByte();
            var secondByte = pData.Reader.ReadByte();

            pData.Position -= 1;
            //1. Check the counter first
            if (_videoSequence == 0)
            {
                //this is the first packet. Make sure we start with a M packet
                if (!rtpHeader.M)
                {
                    return(true);
                }
                _videoSequence = rtpHeader.SEQ;
                return(true);
            }

            if ((ushort)(_videoSequence + 1) != (ushort)rtpHeader.SEQ)
            {
                WARN("Missing video packet. Wanted: {0}; got: {1} on stream: {2}",
                     (ushort)(_videoSequence + 1), rtpHeader.SEQ, Name);
                _currentNalu.IgnoreAll();
                _videoDroppedPacketsCount++;
                _videoSequence = 0;
                return(true);
            }
            _videoSequence++;
            //2. get the nalu
            var  rtpTs    = ComputeRTP(ref rtpHeader.Timestamp, ref _videoLastRTP, ref _videoRTPRollCount);
            uint ts       = (uint)(rtpTs * 1000 / Capabilities.Avc.Rate);
            var  naluType = (byte)(firstByte & 0x1f);

            if (naluType <= 23)
            {
                //3. Standard NALU
                //FINEST("V: %08"PRIx32, rtpHeader._timestamp);
                _videoPacketsCount++;
                _videoBytesCount += dataLength;
                pData.Position   -= 1;
                return(FeedData(pData, dataLength, 0, dataLength, ts, false));
            }
            else
            {
                switch ((NaluType)naluType)
                {
                case NaluType.NALU_TYPE_FUA:
                    if (_currentNalu.GetAvaliableByteCounts() == 0)
                    {
                        _currentNalu.IgnoreAll();
                        if (secondByte >> 7 == 0)
                        {
                            WARN("Bogus nalu");
                            _currentNalu.IgnoreAll();
                            _videoSequence = 0;
                            return(true);
                        }
                        secondByte = (byte)((firstByte & 0xe0) | (secondByte & 0x1f));

                        pData.WriteByte(secondByte);
                        pData.Position -= 1;
                        pData.WriteTo(_currentNalu);

                        return(true);
                    }
                    else
                    {
                        pData.Position += 1;
                        pData.WriteTo(_currentNalu);
                        if (((secondByte >> 6) & 0x01) == 1)
                        {
                            //FINEST("V: %08"PRIx32, rtpHeader._timestamp);
                            _videoPacketsCount++;
                            _videoBytesCount += (ulong)_currentNalu.GetAvaliableByteCounts();
                            if (!FeedData(_currentNalu,
                                          (uint)_currentNalu.GetAvaliableByteCounts(),
                                          0,
                                          (uint)_currentNalu.GetAvaliableByteCounts(),
                                          ts,
                                          false))
                            {
                                FATAL("Unable to feed NALU");
                                return(false);
                            }
                            _currentNalu.IgnoreAll();
                        }
                        return(true);
                    }

                case NaluType.NALU_TYPE_STAPA:
                    var index = 1;
                    while (index + 3 < dataLength)
                    {
                        var length = pData.Reader.ReadUInt16();
                        index += 2;
                        if (index + length > dataLength)
                        {
                            WARN("Bogus STAP-A");
                            _currentNalu.IgnoreAll();
                            _videoSequence = 0;
                            return(true);
                        }
                        _videoPacketsCount++;
                        _videoBytesCount += length;
                        if (!FeedData(pData,
                                      length, 0,
                                      length,
                                      ts, false))
                        {
                            FATAL("Unable to feed NALU");
                            return(false);
                        }
                        index += length;
                    }
                    return(true);

                default:
                    WARN("invalid NAL: {0}", naluType);
                    _currentNalu.IgnoreAll();
                    _videoSequence = 0;
                    return(true);
                }
            }
        }