예제 #1
0
파일: Mkv.cs 프로젝트: 2php/TsRemux_HK
        private Int64 GetClusterClock(EbmlElement cluster)
        {
            Int64 clock = -1;

            if (cluster.Id != Constants.MKVCLUSTER_START)
            {
                throw new FormatException("Bad cluster ID - Invalid/Corrupted MKV file");
            }
            EbmlElement[] children = cluster.Children;
            foreach (EbmlElement time in children)
            {
                if (time.Id == Constants.MKVTIMECODE_START)
                {
                    clock = 0;
                    Stream s = time.DataStream;
                    for (Int64 i = 0; i < time.Size; i++)
                    {
                        clock <<= 8;
                        clock  |= (byte)fs.ReadByte();
                    }
                    break;
                }
            }
            if (-1 == clock)
            {
                throw new FormatException("Could not find timecode in cluster.");
            }
            return(clock);
        }
예제 #2
0
파일: Mkv.cs 프로젝트: 2php/TsRemux_HK
 public TrackInfo(ushort pid, string codec, byte[] data, EbmlElement info)
 {
     this.pid   = pid;
     this.codec = codec;
     this.data  = data;
     this.info  = info;
 }
예제 #3
0
파일: Mkv.cs 프로젝트: hermanho/TsRemux_HK
 public TrackInfo(ushort pid, string codec, byte[] data, EbmlElement info)
 {
     this.pid = pid;
     this.codec = codec;
     this.data = data;
     this.info = info;
 }
예제 #4
0
파일: Mkv.cs 프로젝트: 2php/TsRemux_HK
        public static EbmlElement ParseEbml(Stream fs)
        {
            Int64       pos  = fs.Position;
            EbmlElement ebml = null;

            if (null == fs || fs.Length == 0)
            {
                return(null);
            }
            int b = fs.ReadByte();

            if (b == -1)
            {
                goto cleanup;
            }
            int len = VintLength((byte)b);

            if ((fs.Length - fs.Position) < (Int64)len)
            {
                goto cleanup;
            }
            fs.Position -= 1;
            Int64 id = 0;

            for (int i = 0; i < len; i++)
            {
                id <<= 8;
                id  |= (byte)fs.ReadByte();
            }
            b = fs.ReadByte();
            if (b == -1)
            {
                goto cleanup;
            }
            len = VintLength((byte)b);
            if ((fs.Length - fs.Position) < (Int64)len)
            {
                goto cleanup;
            }
            fs.Position -= 1;
            Int64 size = VintToInt64(fs);

            if ((fs.Length - fs.Position) < size)
            {
                goto cleanup;
            }
            ebml = new EbmlElement(id, size, fs.Position, fs);

cleanup:
            fs.Position = pos;
            return(ebml);
        }
예제 #5
0
파일: Mkv.cs 프로젝트: 2php/TsRemux_HK
        public override PesPacket[] GetNextPesPackets()
        {
            if (CurrentIndex >= Clusters.Keys.Count)
            {
                return(null);
            }
            EbmlElement cluster = Clusters[Clusters.Keys[CurrentIndex]];

            EbmlElement[]    blocks   = cluster.Children;
            List <PesPacket> packList = new List <PesPacket>();
            Int64            clock    = GetClusterClock(cluster);

            if (pcrDelegate != null)
            {
                pcrDelegate(clock * (Constants.MPEG2TS_CLOCK_RATE / 1000));
            }
            foreach (EbmlElement bl in blocks)
            {
                EbmlElement block = null;
                switch (bl.Id)
                {
                case 0xa0:     // block group
                    EbmlElement[] cbls = bl.Children;
                    foreach (EbmlElement bl2 in cbls)
                    {
                        if (bl2.Id == 0xa1)
                        {
                            block = bl2;
                            break;
                        }
                    }
                    break;

                case 0xa3:
                    block = bl;
                    break;
                }
                if (null != block)
                {
                    Stream stm    = block.DataStream;
                    Int64  endPos = stm.Position + block.Size;
                    Int64  track  = EbmlElement.VintToInt64(stm);
                    Int16  time   = (short)stm.ReadByte();
                    time <<= 8;
                    time  += (short)stm.ReadByte();
                    Int64 pts = clock + time;
                    pts *= 90;
                    byte       flags  = (byte)stm.ReadByte();
                    LacingType lacing = (LacingType)((flags >> 1) & 0x03);
                    if (lacing != LacingType.NoLacing && lacing != LacingType.FixedSizeLacing)
                    {
                        throw new FormatException("Variable lacing is not yet supported");
                    }
                    if (lacing == LacingType.FixedSizeLacing)
                    {
                        stm.Position += 1;
                    }
                    byte[] data = new byte[endPos - stm.Position];
                    stm.Read(data, 0, (int)(endPos - stm.Position));
                    if (data.Length > 0 && TrackList.ContainsKey((ushort)track))
                    {
                        TrackInfo ti = TrackList[(ushort)track];
                        if (ptsDelegate != null)
                        {
                            ptsDelegate(pts, ti.pid);
                        }
                        switch (sis[(ushort)track - 1].StreamType)
                        {
                        case ElementaryStreamTypes.AUDIO_STREAM_AC3:
                            packList.Add(BuildAc3Pes(pts, data, ti.pid));
                            break;

                        case ElementaryStreamTypes.AUDIO_STREAM_DTS:
                            packList.Add(BuildDtsPes(pts, data, ti.pid));
                            break;

                        case ElementaryStreamTypes.VIDEO_STREAM_MPEG2:
                            packList.Add(BuildMpeg2Pes(pts, data, ti.pid));
                            break;

                        case ElementaryStreamTypes.VIDEO_STREAM_H264:
                            packList.Add(BuildAvcPes(pts, data, ti.pid));
                            break;

                        case ElementaryStreamTypes.VIDEO_STREAM_VC1:
                            packList.Add(BuildVc1Pes(pts, data, ti.pid));
                            break;
                        }
                    }
                }
            }
            CurrentIndex++;
            if (packList.Count == 0)
            {
                return(null);
            }
            return(packList.ToArray());
        }
예제 #6
0
파일: Mkv.cs 프로젝트: 2php/TsRemux_HK
        protected override void GetInitialValues()
        {
            fs.Seek(0, SeekOrigin.Begin);
            UInt32      header = 0xffffffff;
            EbmlElement mkv    = null;
            byte        b      = 0;

            for (int i = 0; i < Constants.DISK_BUFFER; i++)
            {
                int ib = fs.ReadByte();
                if (ib == -1)
                {
                    throw new FormatException("The specified file is too short");
                }
                b        = (byte)(ib & 0xff);
                header <<= 8;
                header  |= b;
                if (header == Constants.MKVSEGMENT_START)
                {
                    fs.Seek(-4, SeekOrigin.Current);
                    mkv = EbmlElement.ParseEbml(fs);
                    if (null == mkv)
                    {
                        throw new FormatException("Invalid/Corrupted MKV file");
                    }
                    break;
                }
            }
            EbmlElement[] clusts = mkv.Children;
            foreach (EbmlElement clust in clusts)
            {
                ReportProgress((int)(50 * clust.DataStream.Position / clust.DataStream.Length));
                if (clust.Id == Constants.MKVCLUSTER_START)
                {
                    Clusters.Add(GetClusterClock(clust), clust);
                }
                else if (clust.Id == Constants.MKVTRACKINFO_START)
                {
                    EbmlElement[]     tracks     = clust.Children;
                    ushort            id         = 0;
                    List <StreamInfo> mkvStreams = new List <StreamInfo>();
                    foreach (EbmlElement track in tracks)
                    {
                        if (track.Id == 0xae)
                        {
                            EbmlElement[] trackAttributes = track.Children;
                            string        codec           = null;
                            ushort        pid             = 0;
                            UInt64        uid             = 0;
                            byte[]        data            = null;
                            EbmlElement   elementaryInfo  = null;
                            foreach (EbmlElement trackAtt in trackAttributes)
                            {
                                switch (trackAtt.Id)
                                {
                                case 0xd7:     // Track number
                                    for (Int64 i = 0; i < trackAtt.Size; i++)
                                    {
                                        pid <<= 8;
                                        pid  |= (byte)fs.ReadByte();
                                    }
                                    break;

                                case 0x86:     // Codec ID
                                    byte[] cid = new byte[(int)trackAtt.Size];
                                    trackAtt.DataStream.Read(cid, 0, (int)trackAtt.Size);
                                    codec = Encoding.ASCII.GetString(cid);
                                    break;

                                case 0x63a2:     // Coded Private
                                    data = new byte[(int)trackAtt.Size];
                                    trackAtt.DataStream.Read(data, 0, (int)trackAtt.Size);
                                    break;

                                case 0x73c5:     // Track UID
                                    for (Int64 i = 0; i < trackAtt.Size; i++)
                                    {
                                        uid <<= 8;
                                        uid  |= (byte)fs.ReadByte();
                                    }
                                    break;

                                case 0xe0:     // Video elementary stream info
                                    elementaryInfo = trackAtt;
                                    break;

                                case 0xe1:     // Audio elementary stream info
                                    elementaryInfo = trackAtt;
                                    break;
                                }
                            }
                            if (codec == null || pid == 0)
                            {
                                throw new FormatException("Track info is invalid");
                            }
                            if (0 == string.Compare(codec, "V_MPEG2", true, CultureInfo.InvariantCulture) ||
                                0 == string.Compare(codec, "V_MPEG4/ISO/AVC", true, CultureInfo.InvariantCulture) ||
                                0 == string.Compare(codec, "V_MS/VFW/FOURCC", true, CultureInfo.InvariantCulture) ||
                                0 == string.Compare(codec, "A_AC3", true, CultureInfo.InvariantCulture) ||
                                0 == string.Compare(codec, "A_DTS", true, CultureInfo.InvariantCulture))
                            {
                                id++;
                                TrackInfo ti = new TrackInfo(id, codec, data, elementaryInfo);
                                TrackList.Add(id, ti);
                                StreamInfo si = null;
                                if (0 == string.Compare(codec, "V_MPEG2", true, CultureInfo.InvariantCulture))
                                {
                                    si = new StreamInfo(ElementaryStreamTypes.VIDEO_STREAM_MPEG2, id);
                                }
                                else if (0 == string.Compare(codec, "V_MPEG4/ISO/AVC", true, CultureInfo.InvariantCulture))
                                {
                                    si = new StreamInfo(ElementaryStreamTypes.VIDEO_STREAM_H264, id);
                                }
                                else if (0 == string.Compare(codec, "V_MS/VFW/FOURCC", true, CultureInfo.InvariantCulture))
                                {
                                    si = new StreamInfo(ElementaryStreamTypes.VIDEO_STREAM_VC1, id);
                                }
                                else if (0 == string.Compare(codec, "A_AC3", true, CultureInfo.InvariantCulture))
                                {
                                    si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_AC3, id);
                                }
                                else if (0 == string.Compare(codec, "A_DTS", true, CultureInfo.InvariantCulture))
                                {
                                    si = new StreamInfo(ElementaryStreamTypes.AUDIO_STREAM_DTS, id);
                                }
                                mkvStreams.Add(si);
                            }
                        }
                    }
                    if (mkvStreams.Count > 0)
                    {
                        sis = mkvStreams.ToArray();
                    }
                }
            }
            GetTimeStamps();
            CurrentIndex = 0;
        }
예제 #7
0
파일: Mkv.cs 프로젝트: hermanho/TsRemux_HK
 private Int64 GetClusterClock(EbmlElement cluster)
 {
     Int64 clock = -1;
     if(cluster.Id != Constants.MKVCLUSTER_START)
         throw new FormatException("Bad cluster ID - Invalid/Corrupted MKV file");
     EbmlElement[] children = cluster.Children;
     foreach (EbmlElement time in children)
     {
         if (time.Id == Constants.MKVTIMECODE_START)
         {
             clock = 0;
             Stream s = time.DataStream;
             for (Int64 i = 0; i < time.Size; i++)
             {
                 clock <<= 8;
                 clock |= (byte)fs.ReadByte();
             }
             break;
         }
     }
     if (-1 == clock)
         throw new FormatException("Could not find timecode in cluster.");
     return clock;
 }
예제 #8
0
파일: Mkv.cs 프로젝트: hermanho/TsRemux_HK
        public static EbmlElement ParseEbml(Stream fs)
        {
            Int64 pos = fs.Position;
            EbmlElement ebml = null;
            if (null == fs || fs.Length == 0)
                return null;
            int b = fs.ReadByte();
            if (b == -1)
                goto cleanup;
            int len = VintLength((byte)b);
            if ((fs.Length - fs.Position) < (Int64)len)
                goto cleanup;
            fs.Position -= 1;
            Int64 id = 0;
            for (int i = 0; i < len; i++)
            {
                id <<= 8;
                id |= (byte)fs.ReadByte();
            }
            b = fs.ReadByte();
            if (b == -1)
                goto cleanup;
            len = VintLength((byte)b);
            if ((fs.Length - fs.Position) < (Int64)len)
                goto cleanup;
            fs.Position -= 1;
            Int64 size = VintToInt64(fs);
            if ((fs.Length - fs.Position) < size)
                goto cleanup;
            ebml = new EbmlElement(id, size, fs.Position, fs);

            cleanup:
            fs.Position = pos;
            return ebml;
        }