// The video track is the track to which all other tracks should sync with.
        // SyncPoints are instances in time at which:
        // 1. the current video slice is an IFrame; or
        // 2. the current video slice is the beginning of a new block (in case the video track is all IFrames or no IFrames).
        // NOTE: This will only work if GenericMediaStream.CachingEnabled is true.
        public IEnumerable <ulong> EnumerateSyncPoints(IVideoTrack vTrack)
        {
            IMediaTrackSliceEnumerator sliceEnum = (IMediaTrackSliceEnumerator)vTrack.GetEnumerator();
            ulong lastTimeStamp = 0;

            while (sliceEnum.MoveNext())
            {
                Slice slice = sliceEnum.Current;
                if (slice == null)
                {
                    break;
                }
                if (slice.SliceType == SliceType.IFrame)
                {
                    var timeStamp = sliceEnum.CurrentTimeStampNew.Value;         // guaranteed as this is an iframe...
                    //Common.Logger.Instance.Info("[GenericRecodeWRC::SyncPoints] timeStamp [" + timeStamp + "]");
                    yield return(timeStamp);
                }

                if (sliceEnum.CurrentTimeStampNew.HasValue && sliceEnum.CurrentTimeStampNew.Value > 0)
                {
                    lastTimeStamp = sliceEnum.CurrentTimeStampNew.Value;
                }
            }

            //Common.Logger.Instance.Info("[GenericRecodeWRC::SyncPoints] timeStamp [" + lastTimeStamp + "]");
            yield return(lastTimeStamp);            // last slice is NOT an IFrame, but it is a syncpoint nevertheless
        }
Beispiel #2
0
        /// <summary>
        /// Look into a slice just to get width, height, and aspect ratio.
        /// NOTE: This is no longer used.
        /// </summary>
        private void GetScreenDimensions(IVideoTrack video)
        {
            if ((video.PayloadType == VideoPayloadType.unknown) || (video.PayloadType == VideoPayloadType.jpeg) || (video.PayloadType == VideoPayloadType.mjpeg))
            {
                return;
            }

            // this will only work for H.264 video source

            IMediaTrackSliceEnumerator slices = (IMediaTrackSliceEnumerator)video.GetEnumerator();

            slices.MoveNext();
            Slice slice       = slices.Current;;
            int   countToZero = slice.SliceSize;
            ulong totalSize   = 0UL;

            BinaryReader reader = new BinaryReader(new MemoryStream(slice.SliceBytes));

            while (countToZero > 4)
            {
                ulong naluLen = BE32(reader.ReadUInt32());
                long  nextPos = reader.BaseStream.Position + (long)naluLen;
                uint  typ     = reader.ReadByte();
                if ((naluLen > (ulong)countToZero) || (naluLen < 2))
                {
                    throw new Exception("Invalid video payload");
                }

                // access unit delimiter (aud) always comes first and its size is not added to total size because
                // it is be added back to the payload.
                if ((typ & 0x1Fu) == 9u)
                {
                    if (naluLen != 2)
                    {
                        throw new Exception("Wrong nalu delimiter length");
                    }
                    reader.ReadByte(); // discard (we don't need it here)
                }

                // if nalu type is Sequence Param Set, pick up width and height
                // also, build private codec data from this SPS
                // NOTE: it matters which video track this qbox belongs!
                if ((typ & 0x1Fu) == 7u)
                {
                    byte[] buf = new byte[naluLen];
                    reader.Read(buf, 1, (int)naluLen - 1);
                    totalSize += (4 + naluLen);
                    // parse the SPS bit stream, just to get the correct width and height of video.
                    BitReader            bitReader = new BitReader(new MemoryStream(buf));
                    SequenceParameterSet sps       = new SequenceParameterSet((uint)naluLen);
                    sps.Read(bitReader);
                    Width  = (int)sps.Width;
                    Height = (int)sps.Height;
                    if (sps.VUIParametersPresent)
                    {
                        AspectRatioX = sps.vuiParams.AspectRatioX;
                        AspectRatioY = sps.vuiParams.AspectRatioY;
                    }
                }

                countToZero -= ((int)naluLen + 4);
                reader.BaseStream.Position = nextPos;
            }
        }