Example #1
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();
        }
Example #2
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;
            }
        }