Пример #1
0
        public static FlvInfo Read(string Path)
        {
            using (FileStream fs = File.OpenRead(Path))
            {
                FlvInfo aFlvInfo = new FlvInfo();
                fs.Read(aFlvInfo.Header.Type, 0, aFlvInfo.Header.Type.Length);
                aFlvInfo.Header.Version = (byte)fs.ReadByte();
                aFlvInfo.Header.Stream  = (byte)fs.ReadByte();
                fs.Read(aFlvInfo.Header.Length, 0, aFlvInfo.Header.Length.Length);
                byte[] previoustagsize = new byte[4];
                while (fs.Read(previoustagsize, 0, previoustagsize.Length) != 0)
                {
                    FLVTag Tag = new FLVTag();
                    Tag.PreviousTagSize = previoustagsize;
                    Tag.Type            = (byte)fs.ReadByte();
                    fs.Read(Tag.DataLength, 0, Tag.DataLength.Length);
                    fs.Read(Tag.Time, 0, Tag.Time.Length);
                    Tag.TimeEx = (byte)fs.ReadByte();
                    fs.Read(Tag.streamsID, 0, Tag.streamsID.Length);

                    byte[] tmp = new byte[4];
                    tmp[3] = 0;
                    tmp[2] = Tag.DataLength[0];
                    tmp[1] = Tag.DataLength[1];
                    tmp[0] = Tag.DataLength[2];
                    int n = System.BitConverter.ToInt32(tmp, 0);
                    fs.Seek(n, SeekOrigin.Current);
                    aFlvInfo.TagList.Add(Tag);
                }
                return(aFlvInfo);
            }
        }
Пример #2
0
        private bool ShouldFilterTag(FLVTag tag, TagsFilter filterTags)
        {
            if (tag == null)
            {
                return(true);
            }

            // if the timestamp is lower than the current time
            if (_currentTime != INVALID_TIME && tag.Timestamp < _currentTime)
            {
                tag.Timestamp = _currentTime;
                //return true;
            }

            switch (tag.Type)
            {
            case FLVTag.TagType.AUDIO:
            case FLVTag.TagType.AKAMAI_ENC_AUDIO:
                return((TagsFilter.AUDIO & filterTags) == 0 || (_alternateTime != INVALID_TIME && tag.Timestamp < _alternateTime));

            case FLVTag.TagType.VIDEO:
            case FLVTag.TagType.AKAMAI_ENC_VIDEO:
                return((TagsFilter.VIDEO & filterTags) == 0 || (_mediaTime != INVALID_TIME && tag.Timestamp < _mediaTime));
            }

            return(true);
        }
Пример #3
0
 private void UpdateTimes(FLVTag tag)
 {
     if (tag != null)
     {
         if (tag is FLVTagAudio)
         {
             _alternateTime = tag.Timestamp;
         }
         else
         {
             _mediaTime = tag.Timestamp;
         }
     }
 }
Пример #4
0
 public FLVTag GetNextTag(Media media, out uint lastTS)
 {
     lastTS = 0; FLVTag tag = null;
     if (FragmentsData[media].Count > 0)
     {
         var tagsStore = FragmentsData[media].Peek();
         lock (tagsStore) {
             if (tagsStore.Count > 0)
             {
                 lastTS = tagsStore.lastTS;
                 tag    = tagsStore.Dequeue();
             }
             if (tagsStore.Count < 1 && tagsStore.Complete)
             {
                 lock (FragmentsData) {
                     FragmentsData[media].Dequeue(); // delete empty TagsStore
                 }
             }
         }
     }
     return(tag);
 }
Пример #5
0
        public ParsedContent Read(Stream stream)
        {
            var res       = new ParsedContent();
            var info      = new AtomCollection(Channel.ChannelInfo.Extra);
            var processed = false;
            var eos       = false;

            while (!eos)
            {
                var start_pos = stream.Position;
                try {
                    switch (state)
                    {
                    case ReaderState.Header:
                    {
                        var bin    = ReadBytes(stream, 13);
                        var header = new FileHeader(bin);
                        if (header.IsValid)
                        {
                            Logger.Info("FLV Header found");
                            fileHeader        = header;
                            bin               = header.Binary;
                            res.ContentHeader = new Content(position, bin);
                            res.Contents      = null;
                            info.SetChanInfoType("FLV");
                            info.SetChanInfoStreamType("video/x-flv");
                            info.SetChanInfoStreamExt(".flv");
                            res.ChannelInfo = new ChannelInfo(info);
                            position        = bin.Length;
                            tags.Clear();
                            state = ReaderState.Body;
                        }
                        else
                        {
                            throw new BadDataException();
                        }
                    }
                    break;

                    case ReaderState.Body:
                    {
                        var bin        = ReadBytes(stream, 11);
                        var read_valid = false;
                        var body       = new FLVTag(bin);
                        if (body.IsValidHeader)
                        {
                            body.ReadBody(stream);
                            body.ReadFooter(stream);
                            if (body.IsValidFooter)
                            {
                                read_valid = true;
                                bin        = body.Binary;
                                if (res.Contents == null)
                                {
                                    res.Contents = new List <Content>();
                                }
                                res.Contents.Add(new Content(position, bin));
                                tags.AddLast(new TagDesc {
                                        Timestamp = body.Timestamp / 1000.0, DataSize = body.DataSize
                                    });
                                var timespan = tags.Last.Value.Timestamp - tags.First.Value.Timestamp;
                                if (timespan >= 30.0)
                                {
                                    var sz = tags.Take(tags.Count - 1).Sum(t => t.DataSize);
                                    info.SetChanInfoBitrate((int)(sz * 8 / timespan + 900) / 1000);
                                    res.ChannelInfo = new ChannelInfo(info);
                                    while (tags.Count > 1)
                                    {
                                        tags.RemoveFirst();
                                    }
                                }
                                position += bin.Length;
                            }
                        }
                        if (!read_valid)
                        {
                            stream.Position = start_pos;
                            var header = new FileHeader(ReadBytes(stream, 13));
                            if (header.IsValid)
                            {
                                Logger.Info("New FLV Header found");
                                read_valid        = true;
                                fileHeader        = header;
                                bin               = header.Binary;
                                res.ContentHeader = new Content(0, bin);
                                res.Contents      = null;
                                info.SetChanInfoType("FLV");
                                info.SetChanInfoStreamType("video/x-flv");
                                info.SetChanInfoStreamExt(".flv");
                                res.ChannelInfo = new ChannelInfo(info);
                                tags.Clear();
                                position = bin.Length;
                            }
                        }
                        if (!read_valid)
                        {
                            throw new BadDataException();
                        }
                    }
                    break;
                    }
                    processed = true;
                }
                catch (EndOfStreamException) {
                    if (!processed)
                    {
                        throw;
                    }
                    stream.Position = start_pos;
                    eos             = true;
                }
                catch (BadDataException) {
                    stream.Position = start_pos + 1;
                }
            }
            return(res);
        }
Пример #6
0
        public void DownloadFragment(TagsStore tagsStore)
        {
            string fragmentUrl = media.GetFragmentUrl(fragIndex);

            Program.DebugLog("Fragment Url: " + fragmentUrl);

            byte[] data    = HTTP.TryGETData(fragmentUrl, out int retCode, out string status);
            int    retries = 0;

            while (retCode >= 500 && retries <= MaxRetriesLoad)
            {
                System.Threading.Thread.Sleep(1000);
                retries++;
                data = HTTP.TryGETData(fragmentUrl, out retCode, out status);
            }
            if (retCode != 200)
            {
                string msg = "Download fragment failed " + fragIndex + "/" + media.TotalFragments + " code: " + retCode + " status: " + status;
                Program.DebugLog(msg);
                if (Program.verbose)
                {
                    Program.Message(msg);
                }
                if (media.Bootstrap.live)
                {
                    //media.CurrentFragmentIndex = media.TotalFragments;
                    tagsStore.Complete = true;
                    Done(media);
                    return;
                }
                else
                {
                    throw new InvalidOperationException(status);
                }
            }

            Program.DebugLog("Downloaded: fragment=" + fragIndex + "/" + media.TotalFragments + " lenght: " + data.Length);

            var boxes = Box.GetBoxes(data);

            if (boxes.Find(i => i.Type == F4FConstants.BOX_TYPE_MDAT) is MediaDataBox mdat)
            {
                lock (tagsStore) {
                    FLVTag.GetVideoAndAudioTags(tagsStore, mdat.data);
                    tagsStore.ARFA     = boxes.Find(i => i.Type == F4FConstants.BOX_TYPE_AFRA) as AdobeFragmentRandomAccessBox;
                    tagsStore.Complete = true;
                }
                HDSDownloader.LiveIsStalled = false;
            }
            else if (media.Bootstrap.live)
            {
                HDSDownloader.LiveIsStalled = true;
            }
            else
            {
                throw new InvalidOperationException("No found mdat box in fragment " + fragIndex + "/" + media.TotalFragments);
            }

            if (Program.verbose)
            {
                Program.Message(string.Format("Media: {0}  Downloaded: {1}  Data size: {2}", media.label, fragIndex, data.Length));
            }

            media.CurrentFragmentIndex++;
            media.Downloaded++;

            Done(media);
        }
Пример #7
0
        public async Task ReadAsync(
            Stream stream,
            IRTMPContentSink sink,
            CancellationToken cancel_token)
        {
            int len = 0;
            var bin = new byte[13];

            try {
                len += await stream.ReadBytesAsync(bin, len, 13 - len, cancel_token).ConfigureAwait(false);
            }
            catch (EndOfStreamException) {
                return;
            }
            var header = new FLVFileHeader(bin);

            if (!header.IsValid)
            {
                throw new BadDataException();
            }
            sink.OnFLVHeader(header);
            len = 0;

            bool eos = false;

            while (!eos)
            {
                try {
                    len += await stream.ReadBytesAsync(bin, len, 11 - len, cancel_token).ConfigureAwait(false);

                    var read_valid = false;
                    var body       = new FLVTag(this, bin);
                    if (body.IsValidHeader)
                    {
                        if (await body.ReadTagBodyAsync(stream, cancel_token).ConfigureAwait(false))
                        {
                            len        = 0;
                            read_valid = true;
                            switch (body.Type)
                            {
                            case FLVTag.TagType.Audio:
                                sink.OnAudio(body.ToRTMPMessage());
                                break;

                            case FLVTag.TagType.Video:
                                sink.OnVideo(body.ToRTMPMessage());
                                break;

                            case FLVTag.TagType.Script:
                                sink.OnData(new DataAMF0Message(body.ToRTMPMessage()));
                                break;
                            }
                        }
                    }
                    else
                    {
                        len += await stream.ReadBytesAsync(bin, len, 13 - len, cancel_token).ConfigureAwait(false);

                        var new_header = new FLVFileHeader(bin);
                        if (new_header.IsValid)
                        {
                            read_valid = true;
                            sink.OnFLVHeader(header);
                        }
                    }
                    if (!read_valid)
                    {
                        int pos = 1;
                        for (; pos < len; pos++)
                        {
                            var b = bin[pos];
                            if ((b & 0xC0) == 0 && ((b & 0x1F) == 8 || (b & 0x1F) == 9 || (b & 0x1F) == 18))
                            {
                                break;
                            }
                        }
                        if (pos == len)
                        {
                            len = 0;
                        }
                        else
                        {
                            Array.Copy(bin, pos, bin, 0, len - pos);
                            len -= pos;
                        }
                    }
                }
                catch (EndOfStreamException) {
                    eos = true;
                }
            }
        }
Пример #8
0
        public bool Read(Stream stream, IRTMPContentSink sink)
        {
            var processed = false;
            var eos       = false;

            while (!eos)
            {
retry:
                var start_pos = stream.Position;
                try {
                    switch (state)
                    {
                    case ReaderState.Header:
                    {
                        var bin = ReadBytes(stream, 13, out eos);
                        if (eos)
                        {
                            goto error;
                        }
                        var header = new FLVFileHeader(bin);
                        if (header.IsValid)
                        {
                            sink.OnFLVHeader(header);
                            state = ReaderState.Body;
                        }
                        else
                        {
                            throw new BadDataException();
                        }
                    }
                    break;

                    case ReaderState.Body:
                    {
                        var bin = ReadBytes(stream, 11, out eos);
                        if (eos)
                        {
                            goto error;
                        }
                        var read_valid = false;
                        var body       = new FLVTag(this, bin);
                        if (body.IsValidHeader)
                        {
                            if (!body.ReadBody(stream))
                            {
                                eos = true; goto error;
                            }
                            if (!body.ReadFooter(stream))
                            {
                                eos = true; goto error;
                            }
                            if (body.IsValidFooter)
                            {
                                read_valid = true;
                                switch (body.Type)
                                {
                                case FLVTag.TagType.Audio:
                                    sink.OnAudio(body.ToRTMPMessage());
                                    break;

                                case FLVTag.TagType.Video:
                                    sink.OnVideo(body.ToRTMPMessage());
                                    break;

                                case FLVTag.TagType.Script:
                                    sink.OnData(new DataAMF0Message(body.ToRTMPMessage()));
                                    break;
                                }
                            }
                        }
                        else
                        {
                            stream.Position = start_pos;
                            var headerbin = ReadBytes(stream, 13, out eos);
                            if (eos)
                            {
                                goto error;
                            }
                            var header = new FLVFileHeader(headerbin);
                            if (header.IsValid)
                            {
                                read_valid = true;
                                sink.OnFLVHeader(header);
                            }
                        }
                        if (!read_valid)
                        {
                            stream.Position = start_pos + 1;
                            var b = stream.ReadByte();
                            while (true)
                            {
                                if (b < 0)
                                {
                                    eos = true;
                                    goto error;
                                }
                                if ((b & 0xC0) == 0 && ((b & 0x1F) == 8 || (b & 0x1F) == 9 || (b & 0x1F) == 18))
                                {
                                    break;
                                }
                                b = stream.ReadByte();
                            }
                            stream.Position = stream.Position - 1;
                            goto retry;
                        }
                    }
                    break;
                    }
                    processed = true;
                }
                catch (EndOfStreamException) {
                    stream.Position = start_pos;
                    eos             = true;
                }
                catch (BadDataException) {
                    stream.Position = start_pos + 1;
                }
error:
                if (eos)
                {
                    stream.Position = start_pos;
                    eos             = true;
                }
            }
            return(processed);
        }
Пример #9
0
		public static FlvInfo Read(string Path)
		{
			using (FileStream fs = File.OpenRead(Path))
			{
				FlvInfo aFlvInfo = new FlvInfo();
				fs.Read(aFlvInfo.Header.Type, 0, aFlvInfo.Header.Type.Length);
				aFlvInfo.Header.Version = (byte)fs.ReadByte();
				aFlvInfo.Header.Stream = (byte)fs.ReadByte();
				fs.Read(aFlvInfo.Header.Length, 0, aFlvInfo.Header.Length.Length);
				byte[] previoustagsize = new byte[4];
				while (fs.Read(previoustagsize, 0, previoustagsize.Length) != 0)
				{
					FLVTag Tag = new FLVTag();
					Tag.PreviousTagSize = previoustagsize;
					Tag.Type = (byte)fs.ReadByte();
					fs.Read(Tag.DataLength, 0, Tag.DataLength.Length);
					fs.Read(Tag.Time, 0, Tag.Time.Length);
					Tag.TimeEx = (byte)fs.ReadByte();
					fs.Read(Tag.streamsID, 0, Tag.streamsID.Length);

					byte[] tmp = new byte[4];
					tmp[3] = 0;
					tmp[2] = Tag.DataLength[0];
					tmp[1] = Tag.DataLength[1];
					tmp[0] = Tag.DataLength[2];
					int n = System.BitConverter.ToInt32(tmp, 0);
					fs.Seek(n, SeekOrigin.Current);
					aFlvInfo.TagList.Add(Tag);

				}
				return aFlvInfo;
			}
		}
Пример #10
0
 public ParsedContent Read(Stream stream)
 {
     var processed = false;
       var eos = false;
       while (!eos) {
     var start_pos = stream.Position;
     try {
       switch (state) {
       case ReaderState.Header:
     {
       var bin = ReadBytes(stream, 13);
       var header = new FileHeader(bin);
       if (header.IsValid) {
         Logger.Info("FLV Header found");
         contentBuffer.OnStart();
         state = ReaderState.Body;
       }
       else {
         throw new BadDataException();
       }
     }
     break;
       case ReaderState.Body:
     {
       var bin = ReadBytes(stream, 11);
       var read_valid = false;
       var body = new FLVTag(bin);
       if (body.IsValidHeader) {
         body.ReadBody(stream);
         body.ReadFooter(stream);
         if (body.IsValidFooter) {
           read_valid = true;
           switch (body.Type) {
           case FLVTag.TagType.Audio:
             contentBuffer.OnAudio(body.ToRTMPMessage());
             break;
           case FLVTag.TagType.Video:
             contentBuffer.OnVideo(body.ToRTMPMessage());
             break;
           case FLVTag.TagType.Script:
             contentBuffer.OnData(new RTMP.DataAMF0Message(body.ToRTMPMessage()));
             break;
           }
         }
       }
       if (!read_valid) {
         stream.Position = start_pos;
         var header = new FileHeader(ReadBytes(stream, 13));
         if (header.IsValid) {
           Logger.Info("New FLV Header found");
           read_valid = true;
           contentBuffer.OnStart();
         }
       }
       if (!read_valid) throw new BadDataException();
     }
     break;
       }
       processed = true;
     }
     catch (EndOfStreamException) {
       if (!processed) throw;
       stream.Position = start_pos;
       eos = true;
     }
     catch (BadDataException) {
       stream.Position = start_pos+1;
     }
       }
       return contentBuffer.GetContents();
 }
Пример #11
0
 public bool Read(Stream stream, IRTMPContentSink sink)
 {
     var processed = false;
     var eos = false;
     while (!eos) {
         retry:
         var start_pos = stream.Position;
         try {
             switch (state) {
             case ReaderState.Header:
                 {
                     var bin = ReadBytes(stream, 13, out eos);
                     if (eos) goto error;
                     var header = new FileHeader(bin);
                     if (header.IsValid) {
                         sink.OnFLVHeader();
                         state = ReaderState.Body;
                     }
                     else {
                         throw new BadDataException();
                     }
                 }
                 break;
             case ReaderState.Body:
                 {
                     var bin = ReadBytes(stream, 11, out eos);
                     if (eos) goto error;
                     var read_valid = false;
                     var body = new FLVTag(this, bin);
                     if (body.IsValidHeader) {
                         if (!body.ReadBody(stream)) { eos = true; goto error; }
                         if (!body.ReadFooter(stream)) {  eos = true; goto error; }
                         if (body.IsValidFooter) {
                             read_valid = true;
                             switch (body.Type) {
                             case FLVTag.TagType.Audio:
                                 sink.OnAudio(body.ToRTMPMessage());
                                 break;
                             case FLVTag.TagType.Video:
                                 sink.OnVideo(body.ToRTMPMessage());
                                 break;
                             case FLVTag.TagType.Script:
                                 sink.OnData(new DataAMF0Message(body.ToRTMPMessage()));
                                 break;
                             }
                         }
                     }
                     else {
                         stream.Position = start_pos;
                         var headerbin = ReadBytes(stream, 13, out eos);
                         if (eos) goto error;
                         var header = new FileHeader(headerbin);
                         if (header.IsValid) {
                             read_valid = true;
                             sink.OnFLVHeader();
                         }
                     }
                     if (!read_valid) {
                         stream.Position = start_pos+1;
                         var b = stream.ReadByte();
                         while (true) {
                             if (b<0) {
                                 eos = true;
                                 goto error;
                             }
                             if ((b & 0xC0)==0 && ((b & 0x1F)==8 || (b & 0x1F)==9 || (b & 0x1F)==18)) {
                                 break;
                             }
                             b = stream.ReadByte();
                         }
                         stream.Position = stream.Position-1;
                         goto retry;
                     }
                 }
                 break;
             }
             processed = true;
         }
         catch (EndOfStreamException) {
             stream.Position = start_pos;
             eos = true;
         }
         catch (BadDataException) {
             stream.Position = start_pos+1;
         }
     error:
         if (eos) {
             stream.Position = start_pos;
             eos = true;
         }
     }
     return processed;
 }
Пример #12
0
        public ParsedContent Read(Stream stream)
        {
            var processed = false;
            var eos       = false;

            while (!eos)
            {
                var start_pos = stream.Position;
                try {
                    switch (state)
                    {
                    case ReaderState.Header:
                    {
                        var bin    = ReadBytes(stream, 13);
                        var header = new FileHeader(bin);
                        if (header.IsValid)
                        {
                            Logger.Info("FLV Header found");
                            contentBuffer.OnStart();
                            state = ReaderState.Body;
                        }
                        else
                        {
                            throw new BadDataException();
                        }
                    }
                    break;

                    case ReaderState.Body:
                    {
                        var bin        = ReadBytes(stream, 11);
                        var read_valid = false;
                        var body       = new FLVTag(bin);
                        if (body.IsValidHeader)
                        {
                            body.ReadBody(stream);
                            body.ReadFooter(stream);
                            if (body.IsValidFooter)
                            {
                                read_valid = true;
                                switch (body.Type)
                                {
                                case FLVTag.TagType.Audio:
                                    contentBuffer.OnAudio(body.ToRTMPMessage());
                                    break;

                                case FLVTag.TagType.Video:
                                    contentBuffer.OnVideo(body.ToRTMPMessage());
                                    break;

                                case FLVTag.TagType.Script:
                                    contentBuffer.OnData(new RTMP.DataAMF0Message(body.ToRTMPMessage()));
                                    break;
                                }
                            }
                        }
                        if (!read_valid)
                        {
                            stream.Position = start_pos;
                            var header = new FileHeader(ReadBytes(stream, 13));
                            if (header.IsValid)
                            {
                                Logger.Info("New FLV Header found");
                                read_valid = true;
                                contentBuffer.OnStart();
                            }
                        }
                        if (!read_valid)
                        {
                            throw new BadDataException();
                        }
                    }
                    break;
                    }
                    processed = true;
                }
                catch (EndOfStreamException) {
                    if (!processed)
                    {
                        throw;
                    }
                    stream.Position = start_pos;
                    eos             = true;
                }
                catch (BadDataException) {
                    stream.Position = start_pos + 1;
                }
            }
            return(contentBuffer.GetContents());
        }
Пример #13
0
        public void StartDownload(string manifestUrl)
        {
            GetManifestAndSelectMedia(manifestUrl);
            Program.Message("Waiting first fragment...\r");
            // downloader already running in UpdateBootstrapInfo()
            DetermineAudioVideoPresentInDownloadedFragment();
            var        DecoderState = new DecoderLastState();
            bool       useAltAudio  = selectedMediaAlt != null;
            TagsFilter tagFilter    = TagsFilter.ALL;

            if (UpdateStatusTimer == null && !Program.isRedirected)
            {
                UpdateStatusTimer = new Timer(ShowDownloadStatus, null, 0, UpdateStatusInterval);
            }

            if (useAltAudio)
            {
                tagFilter = TagsFilter.VIDEO; // only video for main media if alternate media is selected
            }
            _currentTime       = INVALID_TIME;
            _mediaTime         = INVALID_TIME;
            _alternateTime     = INVALID_TIME;
            droppedAudioFrames = 0;
            droppedVideoFrames = 0;

            FLVTag mediaTag                 = null;
            FLVTag alternateTag             = null;
            bool   needSynchronizationAudio = true;

            if (!Program.ConsolePresent && Program.isRedirected)
            {
                Program.Message("Processing...");
            }
            // --------------- MAIN LOOP DECODE FRAGMENTS ----------------
            while (Downloader.TagsAvaliable(selectedMedia) || selectedMedia.Bootstrap.live)
            {
                if (mediaTag == null)
                {
                    mediaTag = Downloader.GetNextTag(selectedMedia);
                    if (mediaTag == null)
                    {
                        Thread.Sleep(100); // for decrease CPU load
                    }
                }

                if (useAltAudio && _mediaTime != INVALID_TIME && Downloader.TagsAvaliable(selectedMediaAlt))
                {
                    if (alternateTag == null)
                    {
                        alternateTag = Downloader.GetNextTag(selectedMediaAlt);
                    }

                    if (useAltAudio && alternateTag != null && alternateTag.IsAkamaiEncrypted)
                    {
                        if (AD2 == null)   // create and init only if need
                        {
                            AD2 = new AkamaiDecryptor();
                        }
                        AD2.DecryptFLVTag(alternateTag, manifest.baseURL, auth);
                    }

                    if (needSynchronizationAudio && (_mediaTime != INVALID_TIME || _alternateTime != INVALID_TIME))
                    {
                        uint alternateSynchronizationTime = _alternateTime != INVALID_TIME ? _alternateTime : _mediaTime;
                        alternateTag = Downloader.SeekAudioByTime(selectedMediaAlt, alternateSynchronizationTime);
                        if (alternateTag != null)
                        {
                            needSynchronizationAudio = false;
                        }
                    }
                }

                if (mediaTag != null && mediaTag.IsAkamaiEncrypted)
                {
                    if (AD1 == null)   // create and init only if need
                    {
                        AD1 = new AkamaiDecryptor();
                    }
                    AD1.DecryptFLVTag(mediaTag, manifest.baseURL, auth);
                }
                if (useAltAudio && alternateTag != null && alternateTag.IsAkamaiEncrypted)
                {
                    if (AD2 == null)   // create and init only if need
                    {
                        AD2 = new AkamaiDecryptor();
                    }
                    AD2.DecryptFLVTag(alternateTag, manifest.baseURL, auth);
                }

                if (ShouldFilterTag(mediaTag, tagFilter))
                {
                    if (mediaTag != null)
                    {
                        if (mediaTag is FLVTagVideo)
                        {
                            droppedVideoFrames++;
                        }
                        totalDroppedFrames++;
                    }
                    mediaTag = null;
                }
                else
                {
                    UpdateTimes(mediaTag);
                }

                if (ShouldFilterTag(alternateTag, TagsFilter.AUDIO))
                {
                    if (alternateTag != null)
                    {
                        droppedAudioFrames++;
                        totalDroppedFrames++;
                    }
                    alternateTag = null;
                }
                else
                {
                    UpdateTimes(alternateTag);
                }

                if (!useAltAudio)
                {
                    if (mediaTag != null)
                    {
                        _currentTime = mediaTag.Timestamp;
                        FLVFile.Write(mediaTag);
                        mediaTag = null;
                    }
                }
                else
                {
                    if (_mediaTime != INVALID_TIME || _alternateTime != INVALID_TIME)
                    {
                        if (alternateTag != null && (alternateTag.Timestamp >= _currentTime || _currentTime == INVALID_TIME) && (alternateTag.Timestamp <= _mediaTime))
                        {
                            _currentTime = alternateTag.Timestamp;
                            FLVFile.Write(alternateTag);
                            alternateTag = null;
                        }
                        else if (mediaTag != null && (mediaTag.Timestamp >= _currentTime || _currentTime == INVALID_TIME) && (mediaTag.Timestamp <= _alternateTime))
                        {
                            _currentTime = mediaTag.Timestamp;
                            FLVFile.Write(mediaTag);
                            mediaTag = null;
                        }
                    }
                }
                if ((duration > 0) && (FLVFile.LastTimestamp >= duration))
                {
                    Status = "Duration limit reached"; break;
                }
                if ((filesize > 0) && (FLVFile.Filesize >= filesize))
                {
                    Status = "File size limit reached"; break;
                }
            }
            DestroyUpdateStatusTimer();
            ShowDownloadStatus();
        }
Пример #14
0
        public static void FixTimestamp(DecoderLastState DecoderState, FLVTag tag)
        {
            uint lastTS  = DecoderState.prevVideoTS >= DecoderState.prevAudioTS ? DecoderState.prevVideoTS : DecoderState.prevAudioTS;
            uint fixedTS = lastTS + (uint)fixWindow;

            if ((DecoderState.baseTS == DecoderLastState.INVALID_TIMESTAMP) && ((tag.Type == FLVTag.TagType.AUDIO) || (tag.Type == FLVTag.TagType.VIDEO)))
            {
                DecoderState.baseTS = tag.Timestamp;
            }

            if ((DecoderState.baseTS > fixWindow) && (tag.Timestamp >= DecoderState.baseTS))
            {
                tag.Timestamp -= DecoderState.baseTS;
            }

            if (lastTS != DecoderLastState.INVALID_TIMESTAMP)
            {
                int timeShift = (int)(tag.Timestamp - lastTS);
                if (timeShift > fixWindow)
                {
                    Program.DebugLog(string.Format("Timestamp gap detected: PacketTS={0} LastTS={1} Timeshift={2}", tag.Timestamp, lastTS, timeShift));
                    if (DecoderState.baseTS < tag.Timestamp)
                    {
                        DecoderState.baseTS += (uint)(timeShift - fixWindow);
                    }
                    else
                    {
                        DecoderState.baseTS = (uint)(timeShift - fixWindow);
                    }
                    tag.Timestamp = fixedTS;
                }
                else
                {
                    lastTS = tag.Type == FLVTag.TagType.VIDEO ? DecoderState.prevVideoTS : DecoderState.prevAudioTS;
                    if ((lastTS != DecoderLastState.INVALID_TIMESTAMP) && (int)tag.Timestamp < (lastTS - fixWindow))
                    {
                        if ((DecoderState.negTS != DecoderLastState.INVALID_TIMESTAMP) && ((tag.Timestamp + DecoderState.negTS) < (lastTS - fixWindow)))
                        {
                            DecoderState.negTS = DecoderLastState.INVALID_TIMESTAMP;
                        }
                        if (DecoderState.negTS == DecoderLastState.INVALID_TIMESTAMP)
                        {
                            DecoderState.negTS = fixedTS - tag.Timestamp;
                            Program.DebugLog(string.Format("Negative timestamp detected: PacketTS={0} LastTS={1} NegativeTS={2}", tag.Timestamp, lastTS, DecoderState.negTS));
                            tag.Timestamp = (uint)fixedTS;
                        }
                        else
                        {
                            if ((tag.Timestamp + DecoderState.negTS) <= (lastTS + fixWindow))
                            {
                                tag.Timestamp += (uint)DecoderState.negTS;
                            }
                            else
                            {
                                DecoderState.negTS = fixedTS - tag.Timestamp;
                                Program.DebugLog(string.Format("Negative timestamp override: PacketTS={0} LastTS={1} NegativeTS={2}", tag.Timestamp, lastTS, DecoderState.negTS));
                                tag.Timestamp = (uint)fixedTS;
                            }
                        }
                    }
                }
            }
            if (tag is FLVTagAudio)
            {
                DecoderState.prevAudioTS = tag.Timestamp;
            }
            else
            {
                DecoderState.prevVideoTS = tag.Timestamp;
            }
        }
Пример #15
0
    public async Task ReadAsync(
      Stream stream,
      IRTMPContentSink sink,
      CancellationToken cancel_token)
    {
      int len = 0;
      var bin = new byte[13];
      try {
        len += await stream.ReadBytesAsync(bin, len, 13-len, cancel_token);
      }
      catch (EndOfStreamException) {
        return;
      }
      var header = new FileHeader(bin);
      if (!header.IsValid) throw new BadDataException();
      sink.OnFLVHeader();
      len = 0;

      bool eos = false;
      while (!eos) {
        try {
          len += await stream.ReadBytesAsync(bin, len, 11-len, cancel_token);
          var read_valid = false;
          var body = new FLVTag(this, bin);
          if (body.IsValidHeader) {
            if (await body.ReadTagBodyAsync(stream, cancel_token)) {
              len = 0;
              read_valid = true;
              switch (body.Type) {
              case FLVTag.TagType.Audio:
                sink.OnAudio(body.ToRTMPMessage());
                break;
              case FLVTag.TagType.Video:
                sink.OnVideo(body.ToRTMPMessage());
                break;
              case FLVTag.TagType.Script:
                sink.OnData(new DataAMF0Message(body.ToRTMPMessage()));
                break;
              }
            }
          }
          else {
            len += await stream.ReadBytesAsync(bin, len, 13-len, cancel_token);
            var new_header = new FileHeader(bin);
            if (new_header.IsValid) {
              read_valid = true;
              sink.OnFLVHeader();
            }
          }
          if (!read_valid) {
            int pos = 1;
            for (; pos<len; pos++) {
              var b = bin[pos];
              if ((b & 0xC0)==0 && ((b & 0x1F)==8 || (b & 0x1F)==9 || (b & 0x1F)==18)) {
                break;
              }
            }
            if (pos==len) {
              len = 0;
            }
            else {
              Array.Copy(bin, pos, bin, 0, len-pos);
              len -= pos;
            }
          }
        }
        catch (EndOfStreamException) {
          eos = true;
        }
      }

    }
Пример #16
0
 public ParsedContent Read(Stream stream)
 {
     var res = new ParsedContent();
       var info = new AtomCollection(Channel.ChannelInfo.Extra);
       var processed = false;
       var eos = false;
       while (!eos) {
     var start_pos = stream.Position;
     try {
       switch (state) {
       case ReaderState.Header:
     {
       var bin = ReadBytes(stream, 13);
       var header = new FileHeader(bin);
       if (header.IsValid) {
         Logger.Info("FLV Header found");
         fileHeader = header;
         bin = header.Binary;
         res.ContentHeader = new Content(position, bin);
         res.Contents = null;
         info.SetChanInfoType("FLV");
         info.SetChanInfoStreamType("video/x-flv");
         info.SetChanInfoStreamExt(".flv");
         res.ChannelInfo = new ChannelInfo(info);
         position = bin.Length;
         tags.Clear();
         state = ReaderState.Body;
       }
       else {
         throw new BadDataException();
       }
     }
     break;
       case ReaderState.Body:
     {
       var bin = ReadBytes(stream, 11);
       var read_valid = false;
       var body = new FLVTag(bin);
       if (body.IsValidHeader) {
         body.ReadBody(stream);
         body.ReadFooter(stream);
         if (body.IsValidFooter) {
           read_valid = true;
           bin = body.Binary;
           if (res.Contents==null) res.Contents = new List<Content>();
           res.Contents.Add(new Content(position, bin));
           tags.AddLast(new TagDesc { Timestamp=body.Timestamp/1000.0, DataSize=body.DataSize });
           var timespan = tags.Last.Value.Timestamp-tags.First.Value.Timestamp;
           if (timespan>=30.0) {
             var sz = tags.Take(tags.Count-1).Sum(t => t.DataSize);
             info.SetChanInfoBitrate((int)(sz*8/timespan+900)/1000);
             res.ChannelInfo = new ChannelInfo(info);
             while (tags.Count>1) tags.RemoveFirst();
           }
           position += bin.Length;
         }
       }
       if (!read_valid) {
         stream.Position = start_pos;
         var header = new FileHeader(ReadBytes(stream, 13));
         if (header.IsValid) {
           Logger.Info("New FLV Header found");
           read_valid = true;
           fileHeader = header;
           bin = header.Binary;
           res.ContentHeader = new Content(0, bin);
           res.Contents = null;
           info.SetChanInfoType("FLV");
           info.SetChanInfoStreamType("video/x-flv");
           info.SetChanInfoStreamExt(".flv");
           res.ChannelInfo = new ChannelInfo(info);
           tags.Clear();
           position = bin.Length;
         }
       }
       if (!read_valid) throw new BadDataException();
     }
     break;
       }
       processed = true;
     }
     catch (EndOfStreamException) {
       if (!processed) throw;
       stream.Position = start_pos;
       eos = true;
     }
     catch (BadDataException) {
       stream.Position = start_pos+1;
     }
       }
       return res;
 }