Beispiel #1
0
 public List <DvbSubPes> GetSubtitlePesPackets(int packetId)
 {
     if (SubtitlesLookup.ContainsKey(packetId))
     {
         return(SubtitlesLookup[packetId]);
     }
     return(null);
 }
Beispiel #2
0
        private ulong?ProcessPackages(int packetId, Dictionary <int, List <int> > teletextPages, Dictionary <int, List <DvbSubPes> > teletextPesList, ulong?firstVideoMs)
        {
            var list = MakeSubtitlePesPackets(packetId, SubtitlePackets);

            if (list.Count == 0)
            {
                return(firstVideoMs);
            }

            if (!firstVideoMs.HasValue)
            {
                foreach (var pes in list)
                {
                    if (pes.PresentationTimestamp.HasValue)
                    {
                        firstVideoMs = pes.PresentationTimestampToMilliseconds();
                        break;
                    }
                }
            }

            if (list.Any(p => p.IsDvbSubPicture) || IsM2TransportStream)
            {
                if (SubtitlesLookup.ContainsKey(packetId))
                {
                    SubtitlesLookup[packetId].AddRange(list);
                }
                else
                {
                    SubtitlesLookup.Add(packetId, list);
                }
            }

            foreach (var item in list.Where(p => p.IsTeletext))
            {
                foreach (var pageNumber in item.PrepareTeletext().Where(p => p > 0))
                {
                    if (!teletextPages.ContainsKey(packetId))
                    {
                        teletextPages.Add(packetId, new List <int> {
                            pageNumber
                        });
                    }
                    else
                    {
                        if (!teletextPages[packetId].Contains(pageNumber))
                        {
                            teletextPages[packetId].Add(pageNumber);
                        }
                    }
                }

                if (teletextPesList.ContainsKey(packetId))
                {
                    teletextPesList[packetId].Add(item);
                }
                else
                {
                    teletextPesList.Add(packetId, new List <DvbSubPes> {
                        item
                    });
                }
            }

            return(firstVideoMs);
        }
Beispiel #3
0
        /// <summary>
        /// Can be used with e.g. MemoryStream or FileStream
        /// </summary>
        /// <param name="ms">Input stream</param>
        /// <param name="callback">Optional callback event to follow progress</param>
        public void Parse(Stream ms, LoadTransportStreamCallback callback)
        {
            bool firstVideoPtsFound = false;

            IsM2TransportStream         = false;
            NumberOfNullPackets         = 0;
            TotalNumberOfPackets        = 0;
            TotalNumberOfPrivateStream1 = 0;
            TotalNumberOfPrivateStream1Continuation0 = 0;
            SubtitlePacketIds = new List <int>();
            SubtitlePackets   = new List <Packet>();
            ms.Position       = 0;
            const int packetLength = 188;

            IsM2TransportStream = IsM3TransportStream(ms);
            var  packetBuffer       = new byte[packetLength];
            var  m2TsTimeCodeBuffer = new byte[4];
            long position           = 0;

            SubtitlesLookup = new Dictionary <int, List <DvbSubPes> >();

            // check for Topfield .rec file
            ms.Seek(position, SeekOrigin.Begin);
            ms.Read(m2TsTimeCodeBuffer, 0, 3);
            if (m2TsTimeCodeBuffer[0] == 0x54 && m2TsTimeCodeBuffer[1] == 0x46 && m2TsTimeCodeBuffer[2] == 0x72)
            {
                position = 3760;
            }

            long transportStreamLength = ms.Length;

            while (position < transportStreamLength)
            {
                ms.Seek(position, SeekOrigin.Begin);

                if (IsM2TransportStream)
                {
                    ms.Read(m2TsTimeCodeBuffer, 0, m2TsTimeCodeBuffer.Length);
                    position += m2TsTimeCodeBuffer.Length;
                }

                ms.Read(packetBuffer, 0, packetLength);
                byte syncByte = packetBuffer[0];
                if (syncByte == Packet.SynchronizationByte)
                {
                    var packet = new Packet(packetBuffer);

                    if (packet.IsNullPacket)
                    {
                        NumberOfNullPackets++;
                    }
                    else if (!firstVideoPtsFound && packet.IsVideoStream)
                    {
                        if (packet.Payload != null && packet.Payload.Length > 10)
                        {
                            int presentationTimestampDecodeTimestampFlags = packet.Payload[7] >> 6;
                            if (presentationTimestampDecodeTimestampFlags == Helper.B00000010 ||
                                presentationTimestampDecodeTimestampFlags == Helper.B00000011)
                            {
                                FirstVideoPts      = (ulong)packet.Payload[9 + 4] >> 1;
                                FirstVideoPts     += (ulong)packet.Payload[9 + 3] << 7;
                                FirstVideoPts     += (ulong)(packet.Payload[9 + 2] & Helper.B11111110) << 14;
                                FirstVideoPts     += (ulong)packet.Payload[9 + 1] << 22;
                                FirstVideoPts     += (ulong)(packet.Payload[9 + 0] & Helper.B00001110) << 29;
                                firstVideoPtsFound = true;
                            }
                        }
                    }
                    else if (packet.IsProgramAssociationTable)
                    {
                    }
                    else if (packet.IsPrivateStream1 || SubtitlePacketIds.Contains(packet.PacketId))
                    {
                        TotalNumberOfPrivateStream1++;

                        if (!SubtitlePacketIds.Contains(packet.PacketId))
                        {
                            SubtitlePacketIds.Add(packet.PacketId);
                        }

                        if (!IsM2TransportStream && packet.PayloadUnitStartIndicator)
                        {
                            var  list = MakeSubtitlePesPackets(packet.PacketId, SubtitlePackets);
                            bool hasImageSubtitles = false;
                            foreach (var item in list)
                            {
                                if (item.IsDvbSubpicture)
                                {
                                    hasImageSubtitles = true;
                                    break;
                                }
                            }
                            if (hasImageSubtitles)
                            {
                                if (SubtitlesLookup.ContainsKey(packet.PacketId))
                                {
                                    SubtitlesLookup[packet.PacketId].AddRange(list);
                                }
                                else
                                {
                                    SubtitlesLookup.Add(packet.PacketId, list);
                                }
                            }

                            SubtitlePackets.RemoveAll(p => p.PacketId == packet.PacketId);
                        }
                        SubtitlePackets.Add(packet);


                        if (packet.ContinuityCounter == 0)
                        {
                            TotalNumberOfPrivateStream1Continuation0++;

                            //int pesExtensionlength = 0;
                            //if (12 + packet.AdaptionFieldLength < packetBuffer.Length)
                            //    pesExtensionlength = 0xFF & packetBuffer[12 + packet.AdaptionFieldLength];
                            //int pesOffset = 13 + packet.AdaptionFieldLength + pesExtensionlength;
                            //bool isTeletext = (pesExtensionlength == 0x24 && (0xFF & packetBuffer[pesOffset]) >> 4 == 1);

                            //// workaround uk freesat teletext
                            //if (!isTeletext)
                            //    isTeletext = (pesExtensionlength == 0x24 && (0xFF & packetBuffer[pesOffset]) == 0x99);

                            //if (!isTeletext)
                            //{

                            //}
                        }
                    }
                    TotalNumberOfPackets++;
                    position += packetLength;

                    if (TotalNumberOfPackets % 100000 == 0)
                    {
                        callback.Invoke(ms.Position, transportStreamLength);
                    }
                }
                else
                {
                    position++;
                }
            }

            if (IsM2TransportStream)
            {
                DvbSubtitlesLookup = new Dictionary <int, List <TransportStreamSubtitle> >();
                SubtitlesLookup    = new Dictionary <int, List <DvbSubPes> >();
                foreach (int pid in SubtitlePacketIds)
                {
                    var bdMs        = new MemoryStream();
                    var list        = MakeSubtitlePesPackets(pid, SubtitlePackets);
                    var currentList = new List <DvbSubPes>();
                    var sb          = new StringBuilder();
                    var subList     = new List <TransportStreamSubtitle>();
                    for (var index = 0; index < list.Count; index++)
                    {
                        var item = list[index];
                        item.WriteToStream(bdMs);
                        currentList.Add(item);
                        if (item.DataIdentifier == 0x80)
                        {
                            bdMs.Position = 0;
                            var bdList = BluRaySupParser.ParseBluRaySup(bdMs, sb, true);
                            if (bdList.Count > 0)
                            {
                                var startMs = currentList.First().PresentationTimestampToMilliseconds();
                                var endMs   = index + 1 < list.Count ? list[index + 1].PresentationTimestampToMilliseconds() : startMs + (ulong)Configuration.Settings.General.NewEmptyDefaultMs;
                                subList.Add(new TransportStreamSubtitle(bdList[0], startMs, endMs, (ulong)(FirstVideoPts / 90.0)));
                            }
                            bdMs = new MemoryStream();
                            currentList.Clear();
                        }
                    }
                    SubtitlesLookup.Add(pid, list);
                    DvbSubtitlesLookup.Add(pid, subList);
                }
                SubtitlePacketIds.Clear();
                foreach (int key in DvbSubtitlesLookup.Keys)
                {
                    SubtitlePacketIds.Add(key);
                }

                SubtitlePacketIds.Sort();
                return;
            }

            // check for SubPictureStreamId = 32
            foreach (int pid in SubtitlePacketIds)
            {
                var  list = MakeSubtitlePesPackets(pid, SubtitlePackets);
                bool hasImageSubtitles = false;
                foreach (var item in list)
                {
                    if (item.IsDvbSubpicture)
                    {
                        hasImageSubtitles = true;
                        break;
                    }
                }
                if (hasImageSubtitles)
                {
                    if (SubtitlesLookup.ContainsKey(pid))
                    {
                        SubtitlesLookup[pid].AddRange(list);
                    }
                    else
                    {
                        SubtitlesLookup.Add(pid, list);
                    }
                }
                SubtitlePackets.RemoveAll(p => p.PacketId == pid);
            }

            SubtitlePacketIds.Clear();
            foreach (int key in SubtitlesLookup.Keys)
            {
                SubtitlePacketIds.Add(key);
            }

            SubtitlePacketIds.Sort();

            // Merge packets and set start/end time
            DvbSubtitlesLookup = new Dictionary <int, List <TransportStreamSubtitle> >();
            var firstVideoMs = (ulong)(FirstVideoPts / 90.0);

            foreach (int pid in SubtitlePacketIds)
            {
                var subtitles = new List <TransportStreamSubtitle>();
                var list      = ParseAndRemoveEmpty(GetSubtitlePesPackets(pid));
                for (int i = 0; i < list.Count; i++)
                {
                    var pes = list[i];
                    pes.ParseSegments();
                    if (pes.ObjectDataList.Count > 0)
                    {
                        var sub = new TransportStreamSubtitle {
                            StartMilliseconds = pes.PresentationTimestampToMilliseconds(), Pes = pes
                        };
                        if (i + 1 < list.Count && list[i + 1].PresentationTimestampToMilliseconds() > 25)
                        {
                            sub.EndMilliseconds = list[i + 1].PresentationTimestampToMilliseconds() - 25;
                        }
                        if (sub.EndMilliseconds < sub.StartMilliseconds || sub.EndMilliseconds - sub.StartMilliseconds > (ulong)Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds)
                        {
                            sub.EndMilliseconds = sub.StartMilliseconds + (ulong)Configuration.Settings.General.SubtitleMaximumDisplayMilliseconds;
                        }
                        subtitles.Add(sub);
                        if (sub.StartMilliseconds < firstVideoMs)
                        {
                            firstVideoMs = sub.StartMilliseconds;
                        }
                    }
                }
                foreach (var s in subtitles)
                {
                    s.OffsetMilliseconds = firstVideoMs;
                }
                DvbSubtitlesLookup.Add(pid, subtitles);
            }
            SubtitlePacketIds.Clear();
            foreach (int key in DvbSubtitlesLookup.Keys)
            {
                if (DvbSubtitlesLookup[key].Count > 0)
                {
                    SubtitlePacketIds.Add(key);
                }
            }
            SubtitlePacketIds.Sort();
        }