DebugLog() 공개 정적인 메소드

public static DebugLog ( string msg ) : void
msg string
리턴 void
예제 #1
0
        private void Media_AfterUpdateBootstrap(object sender, EventArgs e)
        {
            Media media = sender as Media;

            if (media == null)
            {
                return;
            }

            if (fromTimestamp > 0 && media.Bootstrap != null && !media.Bootstrap.live)
            {
                media.SetCurrentFragmentIndexByTimestamp(fromTimestamp);
            }

            if (Program.debug)
            {
                Program.DebugLog("Segment Tables:");
                for (int i = 0; i < media.Bootstrap.segmentRunTables.Count; i++)
                {
                    Program.DebugLog(String.Format("  Table {0} (Count={1})", i + 1, media.Bootstrap.segmentRunTables[i].segmentFragmentPairs.Count));
                    Program.DebugLog("       FirstSegment FragPerSegment FragmentsAccrued");
                    foreach (var p in media.Bootstrap.segmentRunTables[i].segmentFragmentPairs)
                    {
                        Program.DebugLog(String.Format("       {0,-12} {1,-14} {2,-16}", p.firstSegment, p.fragmentsPerSegment, p.fragmentsAccrued));
                    }
                }
                Program.DebugLog("Fragment Tables:");
                for (int i = 0; i < media.Bootstrap.fragmentRunTables.Count; i++)
                {
                    Program.DebugLog(String.Format("  Table {0} (Count={1})", i + 1, media.Bootstrap.fragmentRunTables[i].fragmentDurationPairs.Count));
                    Program.DebugLog("       FirstFragment Duration DurationAccrued DiscontinuityIndicator");
                    foreach (var p in media.Bootstrap.fragmentRunTables[i].fragmentDurationPairs)
                    {
                        Program.DebugLog(String.Format("       {0,-13} {1,-8} {2,-15} {3,-22}", p.firstFragment, p.duration, p.durationAccrued, p.discontinuityIndicator));
                    }
                }
                Program.DebugLog("Start fragment : " + media.CurrentFragmentIndex);
                Program.DebugLog("Total fragments: " + media.TotalFragments + "\n");
            }

            // Add all fragments to download queue
            for (uint fragIndex = media.CurrentFragmentIndex; fragIndex <= media.TotalFragments; fragIndex++)
            {
                FragmentDurationPair fragmentInfo = media.Bootstrap.GetFragmentInfo(fragIndex);
                if (fragmentInfo == null)
                {
                    throw new InvalidOperationException("No info for fragment " + fragIndex);
                }

                if (fragmentInfo.discontinuityIndicator != 0)
                {
                    Program.DebugLog("Skipping fragment " + fragIndex + " due to discontinuity, Type: " + fragmentInfo.discontinuityIndicator);
                    continue;
                }

                Downloader.AddMediaFragmentToDownload(media, fragIndex);
            }
        }
예제 #2
0
        public void KDF()
        {
            // Decrypt packet salt
            if (ecmID != prevEcmID)
            {
                byte[] saltHmacKey = sha1.ComputeHash(F4FOldMethod.AppendBuf(sessionKey, packetIV));
                if (debug)
                {
                    Program.DebugLog("SaltHmacKey  : " + Hexlify(saltHmacKey));
                }
                shaSalt.Key = saltHmacKey;
                saltAesKey  = F4FOldMethod.BlockCopy(shaSalt.ComputeHash(hmacData1), 0, 16);
                if (debug)
                {
                    Program.DebugLog("SaltAesKey   : " + Hexlify(saltAesKey));
                }
                prevEcmID = ecmID;
            }
            if (debug)
            {
                Program.DebugLog("EncryptedSalt: " + Hexlify(packetSalt));
            }

            byte[] decryptedSalt = AesDecrypt(packetSalt, saltAesKey, packetIV);
            if (decryptedSalt == null)
            {
                Program.Quit("<c:Red>Error ocurred while decription salt of fagment.");
            }
            if (debug)
            {
                Program.DebugLog("DecryptedSalt: " + Hexlify(decryptedSalt));
            }
            decryptBytes = F4FOldMethod.ReadInt32(ref decryptedSalt, 0);
            if (debug)
            {
                Program.DebugLog("DecryptBytes : " + decryptBytes);
            }
            byte[] decryptedSalt2 = F4FOldMethod.BlockCopy(decryptedSalt, 4, 16);
            if (debug)
            {
                Program.DebugLog("DecryptedSalt: " + Hexlify(decryptedSalt2));
            }
            // Generate final packet decryption key
            byte[] finalHmacKey = sha1.ComputeHash(decryptedSalt2);
            if (debug)
            {
                Program.DebugLog("FinalHmacKey : " + Hexlify(finalHmacKey));
            }
            finalsha.Key = finalHmacKey;
            packetKey    = F4FOldMethod.BlockCopy(finalsha.ComputeHash(hmacData2), 0, 16);
            if (debug)
            {
                Program.DebugLog("PacketKey    : " + Hexlify(packetKey));
            }
        }
예제 #3
0
 public static HttpWebResponse GetResponseNoException(HttpWebRequest req)
 {
     try {
         return((HttpWebResponse)req.GetResponse());
     } catch (WebException we) {
         Program.DebugLog("Error downloading the link: " + req.RequestUri + "\r\nException: " + we.Message);
         var resp = we.Response as HttpWebResponse;
         if (resp == null)
         {
             Program.Quit("<c:Red>" + we.Message + " (Request status: <c:Magenta>" + we.Status + "</c>)");
         }
         //throw;
         return(resp);
     }
 }
예제 #4
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);
        }
예제 #5
0
        public byte[] Decrypt(byte[] data, long pos, string baseUrl, string auth)
        {
            if (debug)
            {
                Program.DebugLog("\n----- Akamai Decryption Start -----");
            }
            byte[] decryptedData = new byte[0];
            // Parse packet header
            using (MemoryStream ms = new MemoryStream(data)) {
                ms.Position = pos;
                using (HDSBinaryReader br = new HDSBinaryReader(ms)) {
                    int b = br.ReadByte();
                    ecmVersion = (b >> 4);
                    if (ecmVersion != 11)
                    {
                        ecmVersion = b;
                    }
                    ecmID          = br.ReadInt32();
                    ecmTimestamp   = (uint)br.ReadInt32();
                    kdfVersion     = br.ReadInt16();
                    dccAccReserved = br.ReadByte();

                    if (debug)
                    {
                        Program.DebugLog("ECM Version  : " + ecmVersion + ", ECM ID: " + ecmID + ", ECM Timestamp: " + ecmTimestamp + ", KDF Version: " + kdfVersion + ", DccAccReserved: " + dccAccReserved);
                    }
                    b = br.ReadByte();

                    bool iv  = ((b & 2) > 0);
                    bool key = ((b & 4) > 0);

                    if (iv)
                    {
                        packetIV = br.ReadBytes(16);
                        if (debug)
                        {
                            Program.DebugLog("PacketIV     : " + Hexlify(packetIV));
                        }
                    }

                    if (key)
                    {
                        sessionKeyUrl = br.ReadString();
                        if (debug)
                        {
                            Program.DebugLog("SessionKeyUrl: " + sessionKeyUrl);
                        }
                        string keyPath = sessionKeyUrl.Substring(sessionKeyUrl.LastIndexOf('/'));
                        string keyUrl  = HTTP.JoinUrl(baseUrl, keyPath) + auth;

                        // Download key file if required
                        if (sessionKeyUrl != lastKeyUrl)
                        {
                            if ((baseUrl.Length == 0) && (sessionKey.Length == 0))
                            {
                                if (debug)
                                {
                                    Program.DebugLog("Unable to download session key without manifest url. you must specify it manually using 'adkey' switch.");
                                }
                            }
                            else
                            {
                                if (baseUrl.Length > 0)
                                {
                                    if (debug)
                                    {
                                        Program.DebugLog("Downloading new session key from " + keyUrl);
                                    }
                                    byte[] downloadedData = HTTP.TryGETData(keyUrl, out int retCode, out string status);
                                    if (retCode == 200)
                                    {
                                        sessionID  = "_" + keyPath.Substring("/key_".Length);
                                        sessionKey = downloadedData;
                                    }
                                    else
                                    {
                                        if (debug)
                                        {
                                            Program.DebugLog("Failed to download new session key, Status: " + status + " (" + retCode + ")");
                                        }
                                        sessionID = "";
                                    }
                                }
                            }
                            lastKeyUrl = sessionKeyUrl;
                            if (sessionKey == null || sessionKey.Length == 0)
                            {
                                Program.Quit("Failed to download akamai session decryption key");
                            }
                        }
                    }

                    if (debug)
                    {
                        Program.DebugLog("SessionKey   : " + Hexlify(sessionKey));
                    }

                    if (sessionKey == null || sessionKey.Length < 1)
                    {
                        Program.Quit("ERROR: Fragments can't be decrypted properly without corresponding session key.");
                    }

                    byte reserved; byte[] reservedBlock1, reservedBlock2, encryptedData, lastBlockData;

                    reserved       = br.ReadByte();
                    packetSalt     = br.ReadBytes(32);
                    reservedBlock1 = br.ReadBytes(20);
                    reservedBlock2 = br.ReadBytes(20);
                    if (debug)
                    {
                        Program.DebugLog("ReservedByte : " + reserved + ", ReservedBlock1: " + Hexlify(reservedBlock1) + ", ReservedBlock2: " + Hexlify(reservedBlock2));
                    }

                    // Generate packet decryption key
                    KDF();

                    // Decrypt packet data
                    encryptedData = br.ReadBytes((int)decryptBytes);
                    lastBlockData = br.ReadToEnd();
                    if (decryptBytes > 0)
                    {
                        decryptedData = AesDecrypt(encryptedData, packetKey, packetIV);
                    }
                    decryptedData = F4FOldMethod.AppendBuf(decryptedData, lastBlockData);
                    if (debug)
                    {
                        Program.DebugLog("EncryptedData: " + Hexlify(encryptedData, 64));
                        Program.DebugLog("DecryptedData: " + Hexlify(decryptedData, 64));
                        Program.DebugLog("----- Akamai Decryption End -----\n");
                    }
                } // using (HDSBinaryReader br = new HDSBinaryReader(ms))
            }     // using (MemoryStream ms = new MemoryStream(data))

            return(decryptedData);
        }
예제 #6
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;
            }
        }
예제 #7
0
        private Media QualitySelectionForMedia(List <Media> mediaList, ref string avaliable, bool collectBitrates, bool isAlt = false)
        {
            if (collectBitrates)
            {
                avaliable = " ";
            }
            Media selected = null;

            string[] langs = lang.ToLower().Split(','); int indexLang = 99;
            // sorting media by quality
            mediaList.Sort((a, b) => b.bitrate.CompareTo(a.bitrate));
            if (mediaList.Count > 0)
            {
                foreach (Media media in mediaList)
                {
                    if (isAlt)
                    {
                        if (collectBitrates)
                        {
                            avaliable += media.label + " ";
                        }
                        Program.DebugLog(String.Format(" {0,-8}{1}", media.label, media.url));
                        //selected by language, codec, bitrate or label
                        if (!string.IsNullOrEmpty(alt))
                        {
                            string altLow = alt.ToLower();
                            if (altLow == media.label.ToLower() || altLow == media.lang.ToLower() || altLow == media.bitrate.ToString() || altLow == media.streamId.ToLower())
                            {
                                selected = media;
                            }
                            else if (media.audioCodec.ToLower().IndexOf(altLow) >= 0)
                            {
                                selected = media;
                            }
                            else if (media.videoCodec.ToLower().IndexOf(altLow) >= 0)
                            {
                                selected = media;
                            }
                        }
                        if (!string.IsNullOrEmpty(lang))
                        {
                            int idx = Array.IndexOf(langs, media.lang.ToLower());
                            if (idx >= 0 && idx < indexLang)
                            {
                                indexLang = idx;
                                selected  = media;
                            }
                        }
                    }
                    else
                    {
                        if (collectBitrates)
                        {
                            avaliable += media.bitrate + " ";
                        }
                        Program.DebugLog(String.Format(" {0,-8}{1}", media.bitrate, media.url));
                        if (media.bitrate.ToString() == quality)
                        {
                            selected = media;
                        }
                    }
                }
                if (selected == null && !isAlt)
                {
                    if (int.TryParse(quality, out int iQuality))
                    {
                        // search nearest bitrate
                        int minDiff = int.MaxValue;
                        foreach (var m in mediaList)
                        {
                            int diff = Math.Abs(m.bitrate - iQuality);
                            if (diff < minDiff)
                            {
                                minDiff  = diff;
                                selected = m;
                            }
                        }
                    }
                    else
                    {
                        switch (quality.ToLower())
                        {
                        case "low": selected = mediaList[mediaList.Count - 1]; break;

                        case "medium": selected = mediaList[mediaList.Count / 2]; break;

                        default: selected = mediaList[0]; break;           // first
                        }
                    }
                }
            }
            return(selected);
        }
예제 #8
0
        private void GetManifestAndSelectMedia(string manifestUrl, int nestedBitrate = 0, int level = 0)
        {
            if (level > MAX_LEVEL_NESTED_MANIFESTS)
            {
                throw new InvalidOperationException("Maximum nesting level reached of multi-level manifests.");
            }

            XmlNodeEx xmlManifest = LoadXml(manifestUrl);

            if (string.IsNullOrEmpty(baseUrl))
            {
                baseUrl = URL.ExtractBaseUrl(manifestUrl);
            }

            // parse the manifest
            manifest = new Manifest(xmlManifest, baseUrl, "", nestedBitrate);

            if (string.IsNullOrEmpty(manifest.baseURL))
            {
                throw new InvalidOperationException("Not found <c:Magenta>baseURL</c> value in manifest or in parameter <c:White>--urlbase</c>.");
            }

            if (manifest.media.Count < 1)
            {
                throw new InvalidOperationException("No media entry found in the manifest");
            }

            Program.DebugLog("Manifest entries:\n");
            Program.DebugLog(String.Format(" {0,-8}{1}", "Bitrate", "URL"));

            // TEST for alternate selection
            if (testalt)
            {
                manifest.alternativeMedia.AddRange(manifest.media);
            }

            // Quality selection
            selectedMedia = QualitySelectionForMedia(manifest.media, ref avaliableBitrates, level < 1);

            // Quality selection for alternative media
            selectedMediaAlt = QualitySelectionForMedia(manifest.alternativeMedia, ref avaliableAlt, level < 1, true);

            if (selectedMedia == null)
            {
                selectedMedia = manifest.media[0];
            }

            // check for multi-level manifest
            if (!string.IsNullOrEmpty(selectedMedia.href))
            {
                string nestedManifestUrl = URL.getAbsoluteUrl(manifest.baseURL, selectedMedia.href);
                baseUrl       = URL.ExtractBaseUrl(nestedManifestUrl);
                nestedBitrate = selectedMedia.bitrate;
                selectedMedia = null;
                GetManifestAndSelectMedia(nestedManifestUrl, nestedBitrate, level + 1);
                return;
            }

            string sQuality = selectedMedia.bitrate.ToString();
            int    n        = Math.Max(0, avaliableBitrates.IndexOf(sQuality));

            avaliableBitrates = avaliableBitrates.Replace(" " + sQuality + " ", " <c:Cyan>" + sQuality + "</c> ");
            Program.Message("Quality Selection:");
            Program.Message("Available:" + avaliableBitrates);
            Program.Message("Selected : <c:Cyan>" + sQuality.PadLeft(n + sQuality.Length - 1));
            if (manifest.alternativeMedia.Count > 0)
            {
                Program.Message("Alternatives:" + avaliableAlt);
                if (selectedMediaAlt != null)
                {
                    string label = selectedMediaAlt.label;
                    n            = avaliableAlt.IndexOf(label);
                    avaliableAlt = avaliableAlt.Replace(" " + label + " ", " <c:Cyan>" + label + "</c> ");
                    Program.Message("Selected    : <c:Cyan>" + label.PadLeft(n + label.Length - 1));
                    // get bootstrap for media from manifest by id
                    if (!string.IsNullOrEmpty(selectedMediaAlt.bootstrapInfo?.id) && (selectedMediaAlt.bootstrapInfo.data == null))
                    {
                        selectedMediaAlt.bootstrapInfo = manifest.bootstrapInfos.Find(i => i.id == selectedMediaAlt.bootstrapInfo.id);
                    }
                }
            }

            // get bootstrap for media from manifest by id
            if (!string.IsNullOrEmpty(selectedMedia.bootstrapInfo?.id) && (selectedMedia.bootstrapInfo.data == null))
            {
                selectedMedia.bootstrapInfo = manifest.bootstrapInfos.Find(i => i.id == selectedMedia.bootstrapInfo.id);
            }

            if (selectedMedia.bootstrapInfo == null)
            {
                throw new InvalidOperationException("No bootstrapInfo for selected media entry");
            }

            if (!Program.fproxy)
            {
                HTTP.notUseProxy = true;
            }

            // Use embedded auth information when available
            int idx = selectedMedia.url.IndexOf('?');

            if (idx > 0)
            {
                auth = selectedMedia.url.Substring(idx);
                selectedMedia.url = selectedMedia.url.Substring(0, idx);
            }

            if (selectedMedia.metadata != null)
            {
                FLVFile.onMetaData = new FLVTagScriptBody(selectedMedia.metadata);
            }

            selectedMedia.AfterUpdateBootstrap += Media_AfterUpdateBootstrap;

            selectedMedia.UpdateBootstrapInfo();

            if (selectedMedia.Bootstrap.live)
            {
                Program.Message("<c:Magenta>[Live stream]");
            }

            if (selectedMediaAlt == selectedMedia)
            {
                selectedMediaAlt = null;
            }

            if (selectedMediaAlt != null)
            {
                selectedMediaAlt.alternate = true;
                // Use embedded auth information when available
                idx = selectedMediaAlt.url.IndexOf('?');
                if (idx > 0)
                {
                    auth = selectedMediaAlt.url.Substring(idx);
                    selectedMediaAlt.url = selectedMediaAlt.url.Substring(0, idx);
                }
                selectedMediaAlt.AfterUpdateBootstrap += Media_AfterUpdateBootstrap;

                selectedMediaAlt.UpdateBootstrapInfo();
            }
        }