Exemplo n.º 1
0
        /// <summary>Load a cluster by 0-based index</summary>
        public ReusableCluster load(int idx)
        {
            Entry entry;

            if (dict.TryGetValue(idx, out entry))
            {
                list.Remove(entry.node);
                list.AddLast(entry.node);
                return(entry.value);
            }
            ReusableCluster cluster = null;

            LinkedListNode <int> node;

            if (dict.Count >= capacity)
            {
                // Evicting a cluster from the cache
                node = list.First;
                if (dict.TryGetValue(node.Value, out entry))
                {
                    cluster = entry.value;
                    dict.Remove(node.Value);
                }
                list.RemoveFirst();
            }

            cluster = file.segment.cluster[idx].load(file.stream, file.segment.position, cluster);
            node    = list.AddLast(idx);
            dict.Add(idx, new Entry(node, cluster));
            return(cluster);
        }
Exemplo n.º 2
0
 public void loadCluster(int idx, ReusableCluster dest)
 {
     if (idx < 0 || idx >= segment.cluster.Length)
     {
         throw new IndexOutOfRangeException();
     }
     segment.cluster[idx].load(stream, segment.position, dest);
 }
Exemplo n.º 3
0
        bool loadCluster(int i, bool unpackFrames = true)
        {
            // Stopwatch sw = Stopwatch.StartNew();
            ReusableCluster cluster = clusters.load(i);

            clusterTimestamp = (long)cluster.timestamp;
            clusterIndex     = i;
            blobs.Clear();
            if (null != cluster.simpleBlock)
            {
                foreach (var b in cluster.simpleBlock)
                {
                    if (b.trackNumber != trackNumber)
                    {
                        continue;
                    }
                    blobs.Add(b);
                }
            }
            if (null != cluster.blockGroup)
            {
                foreach (var b in cluster.blockGroup)
                {
                    if (b.block.trackNumber != trackNumber)
                    {
                        continue;
                    }
                    blobs.Add(b.block);
                }
            }

            if (blobs.Count > 0)
            {
                if (!unpackFrames)
                {
                    return(true);
                }

                // Initialize the first block of the now current cluster
                var firstBlock = blobs[0];
                lock (clusters.syncRoot)
                    stream.unpackFrames(ref firstBlock, ref laced);
                updateTimestamp(firstBlock.timestamp);

                // Logger.logVerbose( "{0}.loadCluster #{1}, {2}", this.GetType().Name, i, timestamp );
                // Logger.logVerbose( "{0}.loadCluster #{1}, {2}; took {3} ms", this.GetType().Name, i, timestamp, sw.Elapsed.TotalMilliseconds );
                return(true);
            }

            // Sometimes a cluster has a single blob of only 1 stream.
            // Probably caused by the fact that unlike Mpeg4, for some reason MKV developers decided to use the same time scale for all tracks.
            // Despite they're completely unrelated, audio comes at 48 KHz, video at 24 or 29.97 or 59.94 FPS.
            return(false);
        }
Exemplo n.º 4
0
        internal ReusableCluster load(Stream stream, long segmentOffset, ReusableCluster cluster)
        {
            if (null == cluster)
            {
                cluster = new ReusableCluster();
            }
            stream.Seek(segmentOffset + segmentPosition, SeekOrigin.Begin);
            var id = stream.readElementId();

            if (id != eElement.Cluster)
            {
                throw new ApplicationException($"Expected a cluster, found { id }");
            }

            cluster.read(stream);
            return(cluster);
        }
Exemplo n.º 5
0
        public static MkvSeekPosition find(ClustersCache cache, TimeSpan where, ulong trackNumber)
        {
            ulong searchingTime = cache.timeScaler.convertBack(where);

            int idx = Array.BinarySearch(cache.file.segment.cluster, new ClusterPlaceholder(searchingTime), clusterCompare);

            if (idx < 0)
            {
                idx = (~idx) - 1;
            }

            if (idx < 0)
            {
                return(new MkvSeekPosition(TimeSpan.Zero, 0, 0));
            }

            if (null == tempCluster)
            {
                tempCluster = new ReusableCluster();
            }

            Logger.logDebug("FindSeekPosition.find, looking for {0}, scaled {1}, starting from {2}", where, searchingTime, idx);

            // Create a new reusable one
            ReusableCluster rc   = new ReusableCluster();
            sSeekPos?       blob = listBlobsInClusters(cache, trackNumber, idx)
                                   .Where(sp => sp.time <= searchingTime)
                                   .Select(nullable)
                                   .LastOrDefault();

            if (!blob.HasValue)
            {
                throw new ApplicationException("Seek failed, might be trying to seek past the end");
            }

            TimeSpan time = cache.timeScaler.convert((long)blob.Value.time);

            return(new MkvSeekPosition(time, blob.Value.cluster, blob.Value.blob));
        }
Exemplo n.º 6
0
        /// <summary>Sequence of blobs in the cluster, with sequence numbers</summary>
        static IEnumerable <sSeekPos> listBlobsInCluster(ReusableCluster cluster, ulong trackNumber, int clusterIdx)
        {
            sSeekPos result = default;

            result.cluster = clusterIdx;
            result.blob    = 0;
            long time = (long)cluster.timestamp;

            // The filtering code needs to match what's in ReaderBase.loadCluster or this gonna fail, miserably.
            if (null != cluster.simpleBlock)
            {
                foreach (var b in cluster.simpleBlock)
                {
                    if (b.trackNumber != trackNumber)
                    {
                        continue;
                    }
                    result.time = checked ((ulong)(time + b.timestamp));
                    yield return(result);

                    result.blob++;
                }
            }
            if (null != cluster.blockGroup)
            {
                foreach (var b in cluster.blockGroup)
                {
                    if (b.block.trackNumber != trackNumber)
                    {
                        continue;
                    }
                    result.time = checked ((ulong)(time + b.block.timestamp));
                    result.blob++;
                }
            }
        }
Exemplo n.º 7
0
 public Entry(LinkedListNode <int> node, ReusableCluster value)
 {
     this.node  = node;
     this.value = value;
 }