예제 #1
0
 /// <summary>
 /// Update a payload presentation time
 /// </summary>
 bool SetPayloadPresentationTime(PayloadInfo pi, UInt32 presentationTime)
 {
     pi.PresentationTime = presentationTime;
     //change underlying data
     Buffer.BlockCopy(BitConverter.GetBytes(presentationTime), 0, _packet, pi.PresentationTimeOffset, sizeof(UInt32));
     return(true);
 }
예제 #2
0
        /// <summary>
        /// Correct presentation and send time stamps based on the stream info
        /// <param name="configuration">The ASF configuration</param>
        /// <param name="asfStream">The stream info</param>
        /// </summary>
        public bool SetStart(AsfFileConfiguration configuration, AsfStreamInfo asfStream)
        {
            if (asfStream.StreamType != AsfStreamType.asfAudio) //nothing to do for audio
            {
                //determine keyframe
                PayloadInfo keyframeInfo = (from payload in Payload where (payload.StreamId == configuration.AsfVideoStreamId && payload.IsKeyframeStart) select payload).LastOrDefault();

                if (keyframeInfo == null)
                {
                    return(false);
                }
                //now cut out everything before that presentation time
                for (int idx = 0; idx < Payload.Count; idx++)
                {
                    if (Payload[idx].StreamId == configuration.AsfVideoStreamId && !Payload[idx].IsKeyframeStart && Payload[idx].PresentationTime < keyframeInfo.PresentationTime)
                    {
                        byte streamId = Payload[idx].StreamId;

                        if (Payload[idx].MediaObjectNumber < keyframeInfo.MediaObjectNumber && asfStream.StreamType != AsfStreamType.asfUnaltered) //this is a B or P-frame that comes before the key frame, so it must be disabled
                        {
                            streamId += AsfConstants.ASF_PRIVATE_STREAM_OFFSET;
                        }

                        Payload[idx].StreamId = streamId;
                        Buffer.SetByte(_packet, Payload[idx].StreamIDOffset, streamId);

                        //fix media offset as well
                        UInt32 mediaOffset = 0;
                        Payload[idx].OffsetIntoMedia = mediaOffset;
                        Buffer.BlockCopy(BitConverter.GetBytes(mediaOffset), 0, _packet, Payload[idx].MediaOffset, sizeof(UInt32));
                    }
                }
            }
            return(true);
        }
예제 #3
0
        /// <summary>
        /// Move a payload to a private stream id
        /// </summary>
        void MovePayloadPrivate(PayloadInfo pi, uint presentationTime)
        {
            byte streamId = (byte)(pi.StreamId + AsfConstants.ASF_PRIVATE_STREAM_OFFSET);

            Buffer.SetByte(_packet, pi.StreamIDOffset, streamId);

            SetPayloadPresentationTime(pi, presentationTime);
        }
예제 #4
0
        /// <summary>
        /// Parse the ASF packet, extract presentation time, send time and payload information
        /// </summary>
        void ParsePacket()
        {
            //check error correction data, usually byte value 130 indicating error correction present, 2 bytes error correction data
            byte errorCorrection              = _packet[0];
            bool errorCorrectionPresent       = Convert.ToBoolean(errorCorrection & 128);
            byte errorCorrectionLengthType    = (byte)((errorCorrection ^ 128) >> 5);
            byte errorCorrectionDataFieldSize = (byte)(errorCorrection & 15);
            bool opaqueDataPresent            = Convert.ToBoolean(errorCorrection & 16);

            if (opaqueDataPresent)
            {
                throw new ArgumentException("Not a valid ASF packet");
            }

            if (errorCorrectionPresent)
            {
                if ((errorCorrectionLengthType == 0 && errorCorrectionDataFieldSize != 2) || (errorCorrectionLengthType != 0 && errorCorrectionDataFieldSize != 0))
                {
                    throw new ArgumentException("Not a valid ASF packet");
                }
            }

            byte errorCorrectionType  = _packet[1];
            byte errorCorrectionCycle = _packet[2];

            if (errorCorrectionType != 0 || errorCorrectionCycle != 0)
            {
                throw new ArgumentException("Cannot parse ASF packet with error correction data");
            }

            byte lengthTypeFlags = _packet[3];
            byte propertyFlags   = _packet[4];

            int    parsingOffset       = 5;
            UInt32 sequence            = 0;
            UInt32 packetSize          = 0;
            UInt32 paddingLength       = 0;
            bool   hasMultiplePayloads = false;

            if ((lengthTypeFlags & 1) == 1)
            {   //More than one payload in this packet
                hasMultiplePayloads = true;
            }
            if ((lengthTypeFlags & 2) == 2)
            {   //8-bit sequence field specified
                sequence       = _packet[parsingOffset];
                parsingOffset += 1;
            }
            else if ((lengthTypeFlags & 4) == 4)
            {   //16-bit sequence field specified
                sequence       = BitConverter.ToUInt16(_packet, parsingOffset);
                parsingOffset += 2;
            }
            else if ((lengthTypeFlags & 6) == 6)
            {   //32-bit sequence field specified
                sequence       = BitConverter.ToUInt32(_packet, parsingOffset);
                parsingOffset += 4;
            }

            if ((lengthTypeFlags & 8) == 8)
            {   //8-bit padding size specified
                paddingLength  = _packet[parsingOffset];
                parsingOffset += 1;
            }
            else if ((lengthTypeFlags & 16) == 16)
            {   //16-bit padding size specified
                paddingLength  = BitConverter.ToUInt16(_packet, parsingOffset);
                parsingOffset += 2;
            }
            else if ((lengthTypeFlags & 24) == 24)
            {   //32-bit padding size specified
                paddingLength  = BitConverter.ToUInt32(_packet, parsingOffset);
                parsingOffset += 4;
            }

            if ((lengthTypeFlags & 32) == 32)
            {   //8-bit packet size specified
                packetSize     = _packet[parsingOffset];
                parsingOffset += 1;
            }
            else if ((lengthTypeFlags & 64) == 64)
            {   //16-bit packet size specified
                packetSize     = BitConverter.ToUInt16(_packet, parsingOffset);
                parsingOffset += 2;
            }
            else if ((lengthTypeFlags & 96) == 96)
            {   //32-bit packet size specified
                packetSize     = BitConverter.ToUInt32(_packet, parsingOffset);
                parsingOffset += 4;
            }

            _sendTimeOffset = parsingOffset;
            SendTime        = BitConverter.ToUInt32(_packet, parsingOffset);
            parsingOffset  += 4;
            Duration        = BitConverter.ToUInt16(_packet, parsingOffset);
            parsingOffset  += 2;

            int payloadCount = 1;

            if (hasMultiplePayloads)
            {
                byte payloadFlags = _packet[parsingOffset];
                parsingOffset++;
                payloadCount = payloadFlags & 63;           // bits 0-5 are payload count
                int payLoadLengthType = payloadFlags & 192; // bits 6-7 are payLoadLengthType
            }

            for (int idx = 0; idx < payloadCount; idx++)
            {
                PayloadInfo pi = ParsePayLoad(idx + PayloadIdOffset, hasMultiplePayloads, paddingLength, ref parsingOffset);
                Payload.Add(pi);
            }
        }
예제 #5
0
        private PayloadInfo ParsePayLoad(int payloadId, bool hasMultiplePayloads, UInt32 paddingLength, ref int packetOffset)
        {
            byte streamID;
            bool isKeyFrame = false;

            PayloadInfo pi = new PayloadInfo();

            pi.PayloadId = payloadId;

            streamID = _packet[packetOffset];

            pi.StreamIDOffset = packetOffset;
            pi.StreamId       = (byte)(streamID & 0x7f); //127
            packetOffset++;
            isKeyFrame = (streamID & 0x80) == 0x80;

            byte mediaObjectNumber = _packet[packetOffset];

            pi.MediaObjectNumber       = mediaObjectNumber;
            pi.MediaObjectNumberOffset = packetOffset;

            packetOffset++;
            pi.MediaOffset = packetOffset;
            UInt32 offsetIntoMedia = BitConverter.ToUInt32(_packet, packetOffset);

            packetOffset      += 4;
            pi.OffsetIntoMedia = offsetIntoMedia;

            pi.IsKeyframeStart = isKeyFrame && offsetIntoMedia == 0;
            IsKeyFrame         = IsKeyFrame || pi.IsKeyframeStart; //we are only interested in the first packet part of a keyframe

            byte replicatedDataLength;                             //should be set to 1 for compressed data

            replicatedDataLength = _packet[packetOffset];
            packetOffset++;


            UInt32 mediaObjectSize  = 0;
            UInt32 presentationTime = 0;

            if (replicatedDataLength > 0)
            {
                mediaObjectSize = BitConverter.ToUInt32(_packet, packetOffset);
                packetOffset   += 4;

                pi.PresentationTimeOffset = packetOffset;
                presentationTime          = BitConverter.ToUInt32(_packet, packetOffset);
                pi.PresentationTime       = presentationTime;
                packetOffset += 4;

                //skip over extension field part of replicated data
                packetOffset += replicatedDataLength - sizeof(UInt32) - sizeof(UInt32);
            }
            UInt16 payLoadLength = 0;

            if (hasMultiplePayloads)
            {
                payLoadLength = BitConverter.ToUInt16(_packet, packetOffset);
                packetOffset += sizeof(UInt16);
            }
            else
            {
                payLoadLength = (UInt16)(_packet.Length - packetOffset - paddingLength);
            }
            pi.PayLoadLength = payLoadLength;

            //skip over payload data
            packetOffset += payLoadLength;
            return(pi);
        }
예제 #6
0
 /// <summary>
 /// Update a payload presentation time
 /// </summary>
 bool SetPayloadPresentationTime(PayloadInfo pi, UInt32 presentationTime)
 {
     pi.PresentationTime = presentationTime;
     //change underlying data
     Buffer.BlockCopy(BitConverter.GetBytes(presentationTime), 0, _packet, pi.PresentationTimeOffset, sizeof(UInt32));
     return true;
 }
예제 #7
0
        private PayloadInfo ParsePayLoad(int payloadId, bool hasMultiplePayloads, UInt32 paddingLength, ref int packetOffset)
        {
            byte streamID;
            bool isKeyFrame = false;

            PayloadInfo pi = new PayloadInfo();
            pi.PayloadId = payloadId;

            streamID = _packet[packetOffset];

            pi.StreamIDOffset = packetOffset;
            pi.StreamId = (byte)(streamID & 0x7f); //127
            packetOffset++;
            isKeyFrame = (streamID & 0x80) == 0x80;

            byte mediaObjectNumber = _packet[packetOffset];
            pi.MediaObjectNumber = mediaObjectNumber;
            pi.MediaObjectNumberOffset = packetOffset;

            packetOffset++;
            pi.MediaOffset = packetOffset;
            UInt32 offsetIntoMedia = BitConverter.ToUInt32(_packet, packetOffset);
            packetOffset += 4;
            pi.OffsetIntoMedia = offsetIntoMedia;

            pi.IsKeyframeStart = isKeyFrame && offsetIntoMedia == 0;
            IsKeyFrame = IsKeyFrame || pi.IsKeyframeStart; //we are only interested in the first packet part of a keyframe

            byte replicatedDataLength; //should be set to 1 for compressed data
            replicatedDataLength = _packet[packetOffset];
            packetOffset++;

            UInt32 mediaObjectSize = 0;
            UInt32 presentationTime = 0;
            if (replicatedDataLength > 0)
            {
                mediaObjectSize = BitConverter.ToUInt32(_packet, packetOffset);
                packetOffset += 4;

                pi.PresentationTimeOffset = packetOffset;
                presentationTime = BitConverter.ToUInt32(_packet, packetOffset);
                pi.PresentationTime = presentationTime;
                packetOffset += 4;

                //skip over extension field part of replicated data
                packetOffset += replicatedDataLength - sizeof(UInt32) - sizeof(UInt32);
            }
            UInt16 payLoadLength = 0;
            if (hasMultiplePayloads)
            {
                payLoadLength = BitConverter.ToUInt16(_packet, packetOffset);
                packetOffset += sizeof(UInt16);
            }
            else
            {
                payLoadLength = (UInt16)(_packet.Length - packetOffset - paddingLength);
            }
            pi.PayLoadLength = payLoadLength;

            //skip over payload data
            packetOffset += payLoadLength;
            return pi;
        }
예제 #8
0
        /// <summary>
        /// Move a payload to a private stream id
        /// </summary>
        void MovePayloadPrivate(PayloadInfo pi, uint presentationTime)
        {
            byte streamId = (byte)(pi.StreamId + AsfConstants.ASF_PRIVATE_STREAM_OFFSET);
            Buffer.SetByte(_packet, pi.StreamIDOffset, streamId);

            SetPayloadPresentationTime(pi, presentationTime);
        }