public void BluRaySupWriteAndReadTwoBitmaps()
        {
            var fileName = Guid.NewGuid() + ".sup";

            using (var binarySubtitleFile = new FileStream(fileName, FileMode.Create))
            {
                var brSub = new BluRaySupPicture
                {
                    StartTime = 0,
                    EndTime   = 1000,
                    Width     = 1080,
                    Height    = 720
                };
                var buffer = BluRaySupPicture.CreateSupFrame(brSub, new Bitmap(100, 20), 10, 25, 10, ContentAlignment.BottomCenter);
                binarySubtitleFile.Write(buffer, 0, buffer.Length);
                brSub.StartTime = 2000;
                brSub.EndTime   = 3000;
                buffer          = BluRaySupPicture.CreateSupFrame(brSub, new Bitmap(100, 20), 10, 25, 10, ContentAlignment.BottomCenter);
                binarySubtitleFile.Write(buffer, 0, buffer.Length);
            }

            var log       = new StringBuilder();
            var subtitles = BluRaySupParser.ParseBluRaySup(fileName, log);

            Assert.AreEqual(2, subtitles.Count);
        }
示例#2
0
        private static void ConvertBluRaySubtitle(string fileName, string toFormat, string offset, Encoding targetEncoding, string outputFolder, int count, ref int converted, ref int errors, IList <SubtitleFormat> formats, bool overwrite, string pacCodePage, double?targetFrameRate, bool removeTextForHi, bool fixCommonErrors, bool redoCasing)
        {
            SubtitleFormat format = Utilities.GetSubtitleFormatByFriendlyName(toFormat) ?? new SubRip();

            var log = new StringBuilder();

            Console.WriteLine("Loading subtitles from file \"{0}\"", fileName);
            var      bluRaySubtitles = BluRaySupParser.ParseBluRaySup(fileName, log);
            Subtitle sub;

            using (var vobSubOcr = new VobSubOcr())
            {
                Console.WriteLine("Using OCR to extract subtitles");
                vobSubOcr.FileName = Path.GetFileName(fileName);
                vobSubOcr.InitializeBatch(bluRaySubtitles, Configuration.Settings.VobSubOcr, fileName);
                sub = vobSubOcr.SubtitleFromOcr;
                Console.WriteLine("Extracted subtitles from file \"{0}\"", fileName);
            }

            if (sub != null)
            {
                Console.WriteLine("Converted subtitle");
                BatchConvertSave(toFormat, offset, targetEncoding, outputFolder, count, ref converted, ref errors, formats, fileName, sub, format, overwrite, pacCodePage, targetFrameRate, removeTextForHi, fixCommonErrors, redoCasing);
            }
        }
示例#3
0
        private void OpenBinSubtitle(string fileName)
        {
            numericUpDownScreenWidth.Value  = 1920;
            numericUpDownScreenHeight.Value = 1080;

            comboBoxFrameRate.Items.Clear();
            comboBoxFrameRate.Items.Add("23.976");
            comboBoxFrameRate.Items.Add("24");
            comboBoxFrameRate.Items.Add("25");
            comboBoxFrameRate.Items.Add("29.97");
            comboBoxFrameRate.Items.Add("30");
            comboBoxFrameRate.Items.Add("50");
            comboBoxFrameRate.Items.Add("59.94");
            comboBoxFrameRate.Items.Add("60");
            comboBoxFrameRate.SelectedIndex = 2;

            if (FileUtil.IsBluRaySup(fileName))
            {
                var log = new StringBuilder();
                _bluRaySubtitles = BluRaySupParser.ParseBluRaySup(fileName, log);
                _subtitle        = new Subtitle();
                _extra           = new List <Extra>();
                bool first = true;
                foreach (var s in _bluRaySubtitles)
                {
                    if (first)
                    {
                        var bmp = s.GetBitmap();
                        if (bmp != null && bmp.Width > 1 && bmp.Height > 1)
                        {
                            SetFrameRate(s.FramesPerSecondType);
                            SetResolution(s.Size);
                            first = false;
                        }
                    }

                    _subtitle.Paragraphs.Add(new Paragraph
                    {
                        StartTime = new TimeCode(s.StartTime / 90.0),
                        EndTime   = new TimeCode(s.EndTime / 90.0)
                    });

                    var pos = s.GetPosition();
                    _extra.Add(new Extra {
                        Forced = s.IsForced, X = pos.Left, Y = pos.Top
                    });
                }

                _subtitle.Renumber();
                subtitleListView1.Fill(_subtitle);
            }

            if (_subtitle != null)
            {
                subtitleListView1.SelectIndexAndEnsureVisible(_subtitle.GetParagraphOrDefault(0));
            }
        }
示例#4
0
        private static List <PcsData> LoadBluRaySubFromMatroska(MatroskaTrackInfo matroskaSubtitleInfo, MatroskaFile matroska)
        {
            var sub           = matroska.GetSubtitle(matroskaSubtitleInfo.TrackNumber, null);
            var subtitles     = new List <BluRaySupParser.PcsData>();
            var log           = new StringBuilder();
            var clusterStream = new MemoryStream();
            var lastPalettes  = new Dictionary <int, List <PaletteInfo> >();
            var bitmapObjects = new Dictionary <int, List <OdsData> >();

            foreach (var p in sub)
            {
                var buffer = p.GetData(matroskaSubtitleInfo);
                if (buffer != null && buffer.Length > 2)
                {
                    clusterStream.Write(buffer, 0, buffer.Length);
                    if (ContainsBluRayStartSegment(buffer))
                    {
                        if (subtitles.Count > 0 && subtitles[subtitles.Count - 1].StartTime == subtitles[subtitles.Count - 1].EndTime)
                        {
                            subtitles[subtitles.Count - 1].EndTime = (long)((p.Start - 1) * 90.0);
                        }
                        clusterStream.Position = 0;
                        var list = BluRaySupParser.ParseBluRaySup(clusterStream, log, true, lastPalettes, bitmapObjects);
                        foreach (var sup in list)
                        {
                            sup.StartTime = (long)((p.Start - 1) * 90.0);
                            sup.EndTime   = (long)((p.End - 1) * 90.0);
                            subtitles.Add(sup);

                            // fix overlapping
                            if (subtitles.Count > 1 && sub[subtitles.Count - 2].End > sub[subtitles.Count - 1].Start)
                            {
                                subtitles[subtitles.Count - 2].EndTime = subtitles[subtitles.Count - 1].StartTime - 1;
                            }
                        }
                        clusterStream = new MemoryStream();
                    }
                }
                else if (subtitles.Count > 0)
                {
                    var lastSub = subtitles[subtitles.Count - 1];
                    if (lastSub.StartTime == lastSub.EndTime)
                    {
                        lastSub.EndTime = (long)((p.Start - 1) * 90.0);
                        if (lastSub.EndTime - lastSub.StartTime > 1000000)
                        {
                            lastSub.EndTime = lastSub.StartTime;
                        }
                    }
                }
            }

            return(subtitles);
        }
        public void BluRaySupReadMultiImagePic()
        {
            string fileName  = Path.Combine(Directory.GetCurrentDirectory(), "sample_BDSUP_multi_image.sup");
            var    log       = new StringBuilder();
            var    subtitles = BluRaySupParser.ParseBluRaySup(fileName, log);

            Assert.AreEqual(2, subtitles.Count);
            Assert.AreEqual(2, subtitles[0].PcsObjects.Count);
            using (var bmp = subtitles[0].GetBitmap())
            {
                Assert.AreEqual(784, bmp.Width);
                Assert.AreEqual(911, bmp.Height);
            }
        }
示例#6
0
        private static bool ContainsBluRayStartSegment(byte[] buffer)
        {
            const int epochStart = 0x80;
            var       position   = 0;

            while (position + 3 <= buffer.Length)
            {
                var segmentType = buffer[position];
                if (segmentType == epochStart)
                {
                    return(true);
                }
                var length = BluRaySupParser.BigEndianInt16(buffer, position + 1) + 3;
                position += length;
            }
            return(false);
        }
        public static List <SubtitleEvent> ReadSup(string inputFile)
        {
            List <SubtitleEvent> events = new List <SubtitleEvent>();
            StringBuilder        logger = new StringBuilder();
            var result = BluRaySupParser.ParseBluRaySup(inputFile, logger);
            int i      = 0;

            foreach (var line in result)
            {
                var bitmap = BluRaySupParser.SupDecoder.DecodeImage(line.PcsObjects[0], line.BitmapObjects[0], line.PaletteInfos);

                var image_data = ImageUtil.ConvertToPngBytes(bitmap);
                events.Add(new SubtitleEvent()
                {
                    StartTime = TimeSpan.FromMilliseconds(line.StartTime / 90.0), EndTime = TimeSpan.FromMilliseconds(line.EndTime / 90.0), MimeType = "image/png", Image = image_data, Origin = line.PcsObjects[0].Origin
                });
                i++;
            }
            return(events);
        }
示例#8
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)
        {
            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 SortedDictionary <int, List <DvbSubPes> >();
            TeletextSubtitlesLookup = new SortedDictionary <int, SortedDictionary <int, List <Paragraph> > >();
            var   teletextPesList = new Dictionary <int, List <DvbSubPes> >();
            var   teletextPages   = new Dictionary <int, List <int> >();
            ulong?firstMs         = null;
            ulong?firstVideoMs    = null;

            // 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;

            ms.Seek(position, SeekOrigin.Begin);
            while (position < transportStreamLength)
            {
                if (IsM2TransportStream)
                {
                    ms.Read(m2TsTimeCodeBuffer, 0, m2TsTimeCodeBuffer.Length);
                    position += m2TsTimeCodeBuffer.Length;
                }

                var bytesRead = ms.Read(packetBuffer, 0, packetLength);
                if (bytesRead < packetLength)
                {
                    break; // incomplete packet at end-of-file
                }

                if (packetBuffer[0] == Packet.SynchronizationByte)
                {
                    var packet = new Packet(packetBuffer);
                    if (packet.IsNullPacket)
                    {
                        NumberOfNullPackets++;
                    }

                    else if (!firstVideoMs.HasValue && packet.IsVideoStream)
                    {
                        if (packet.Payload != null && packet.Payload.Length > 10)
                        {
                            int presentationTimestampDecodeTimestampFlags = packet.Payload[7] >> 6;
                            if (presentationTimestampDecodeTimestampFlags == Helper.B00000010 ||
                                presentationTimestampDecodeTimestampFlags == Helper.B00000011)
                            {
                                firstVideoMs  = (ulong)packet.Payload[9 + 4] >> 1;
                                firstVideoMs += (ulong)packet.Payload[9 + 3] << 7;
                                firstVideoMs += (ulong)(packet.Payload[9 + 2] & Helper.B11111110) << 14;
                                firstVideoMs += (ulong)packet.Payload[9 + 1] << 22;
                                firstVideoMs += (ulong)(packet.Payload[9 + 0] & Helper.B00001110) << 29;
                                firstVideoMs  = firstVideoMs / 90;
                            }
                        }
                    }

                    else if (packet.IsPrivateStream1 || SubtitlePacketIds.Contains(packet.PacketId))
                    {
                        TotalNumberOfPrivateStream1++;

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

                        if (packet.PayloadUnitStartIndicator)
                        {
                            firstMs = ProcessPackages(packet.PacketId, teletextPages, teletextPesList, firstMs);
                            SubtitlePackets.RemoveAll(p => p.PacketId == packet.PacketId);
                        }
                        SubtitlePackets.Add(packet);

                        if (packet.ContinuityCounter == 0)
                        {
                            TotalNumberOfPrivateStream1Continuation0++;
                        }
                    }
                    TotalNumberOfPackets++;
                    position += packetLength;

                    if (TotalNumberOfPackets % 100000 == 0)
                    {
                        callback?.Invoke(position, transportStreamLength);
                    }
                }
                else
                {
                    // sync byte not found - search for it (will be very slow!)
                    if (IsM2TransportStream)
                    {
                        position -= m2TsTimeCodeBuffer.Length;
                    }
                    position++;
                    ms.Seek(position, SeekOrigin.Begin);
                }
            }
            foreach (var pid in SubtitlePackets.GroupBy(p => p.PacketId))
            {
                firstMs = ProcessPackages(pid.Key, teletextPages, teletextPesList, firstMs);
            }
            SubtitlePackets.Clear();
            callback?.Invoke(transportStreamLength, transportStreamLength);

            foreach (var packetId in teletextPesList.Keys) // teletext from PES packets
            {
                if (!teletextPages.ContainsKey(packetId))
                {
                    continue;
                }

                foreach (var page in teletextPages[packetId].OrderBy(p => p))
                {
                    var pageBcd = Teletext.DecToBec(page);
                    Teletext.InitializeStaticFields(packetId, pageBcd);
                    var teletextRunSettings = new TeletextRunSettings(firstMs);
                    foreach (var pes in teletextPesList[packetId])
                    {
                        var textDictionary = pes.GetTeletext(teletextRunSettings, page, pageBcd);
                        AddToTeletextDictionary(textDictionary, packetId);
                    }

                    var lastTextDictionary = Teletext.ProcessTelxPacketPendingLeftovers(teletextRunSettings, page);
                    AddToTeletextDictionary(lastTextDictionary, packetId);
                }
            }
            if (Configuration.Settings.SubtitleSettings.TeletextItalicFix)
            {
                FixTeletextItalics(TeletextSubtitlesLookup);
            }

            foreach (var id in TeletextSubtitlesLookup.Keys)
            {
                SubtitlePacketIds = SubtitlePacketIds.Where(p => p != id).ToList();
                SubtitlesLookup.Remove(id);
            }

            DvbSubtitlesLookup = new SortedDictionary <int, List <TransportStreamSubtitle> >();
            if (IsM2TransportStream) // m2ts blu-ray images from PES packets
            {
                foreach (int pid in SubtitlesLookup.Keys)
                {
                    var bdMs        = new MemoryStream();
                    var list        = SubtitlesLookup[pid];
                    var currentList = new List <DvbSubPes>();
                    var sb          = new StringBuilder();
                    var subList     = new List <TransportStreamSubtitle>();
                    var offset      = (long)(firstVideoMs ?? 0); // when to use firstMs ?
                    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;
                                startMs = (ulong)((long)startMs - offset);
                                endMs   = (ulong)((long)endMs - offset);
                                subList.Add(new TransportStreamSubtitle(bdList[0], startMs, endMs));
                            }
                            bdMs.Dispose();
                            bdMs = new MemoryStream();
                            currentList.Clear();
                        }
                    }

                    if (subList.Count > 0)
                    {
                        DvbSubtitlesLookup.Add(pid, subList);
                        SubtitlePacketIds = SubtitlePacketIds.Where(p => p != pid).ToList();
                    }
                }
            }

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

            // Merge packets and set start/end time
            foreach (int pid in SubtitlePacketIds.Where(p => !DvbSubtitlesLookup.ContainsKey(p)))
            {
                var subtitles = new List <TransportStreamSubtitle>();
                var list      = ParseAndRemoveEmpty(GetSubtitlePesPackets(pid));
                var offset    = (long)(firstVideoMs ?? 0); // when to use firstMs ?
                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;
                        }

                        if (offset <= (long)sub.StartMilliseconds || offset < 0)
                        {
                            sub.StartMilliseconds = (ulong)((long)sub.StartMilliseconds - offset);
                            sub.EndMilliseconds   = (ulong)((long)sub.EndMilliseconds - offset);
                        }
                        else
                        {
                            if (subtitles.Count > 0)
                            {
                                offset = (long)sub.StartMilliseconds - (long)subtitles[subtitles.Count - 1].EndMilliseconds + 1000;
                                sub.StartMilliseconds = (ulong)((long)sub.StartMilliseconds - offset);
                                sub.EndMilliseconds   = (ulong)((long)sub.EndMilliseconds - offset);
                            }
                        }
                        subtitles.Add(sub);
                    }
                }
                if (subtitles.Count > 0)
                {
                    DvbSubtitlesLookup.Add(pid, subtitles);
                }
            }

            SubtitlePacketIds.Clear();
            foreach (int key in DvbSubtitlesLookup.Keys)
            {
                if (DvbSubtitlesLookup[key].Count > 0 && !SubtitlePacketIds.Contains(key))
                {
                    SubtitlePacketIds.Add(key);
                }
            }
            SubtitlePacketIds.Sort();
        }
示例#9
0
        /// <summary>
        /// Can be used with e.g. MemoryStream or FileStream
        /// </summary>
        /// <param name="ms">Input stream</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>();
            //            ProgramAssociationTables = new List<Packet>();
            ms.Position = 0;
            const int packetLength = 188;

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

            // 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);
                    //var tc = (m2tsTimeCodeBuffer[0]<< 24) | (m2tsTimeCodeBuffer[1] << 16) | (m2tsTimeCodeBuffer[2] << 8) | (m2tsTimeCodeBuffer[3]);
                    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)
                    {
                        //var sb = new StringBuilder();
                        //sb.AppendLine("PacketNo: " + TotalNumberOfPackets + 1);
                        //sb.AppendLine("PacketId: " + packet.PacketId);
                        //sb.AppendLine();
                        //sb.AppendLine("TransportErrorIndicator: " + packet.TransportErrorIndicator);
                        //sb.AppendLine("PayloadUnitStartIndicator: " + packet.PayloadUnitStartIndicator);
                        //sb.AppendLine("TransportPriority: " + packet.TransportPriority);
                        //sb.AppendLine("ScramblingControl: " + packet.ScramblingControl);
                        //sb.AppendLine("AdaptationFieldExist: " + packet.AdaptationFieldControl);
                        //sb.AppendLine("ContinuityCounter: " + packet.ContinuityCounter);
                        //sb.AppendLine();
                        //if (packet.AdaptationField != null)
                        //{
                        //sb.AppendLine("AdaptationFieldLength: " + packet.AdaptationField.Length);
                        //sb.AppendLine("DiscontinuityIndicator: " + packet.AdaptationField.DiscontinuityIndicator);
                        //sb.AppendLine("RandomAccessIndicator: " + packet.AdaptationField.RandomAccessIndicator);
                        //sb.AppendLine("ElementaryStreamPriorityIndicator: " + packet.AdaptationField.ElementaryStreamPriorityIndicator);
                        //sb.AppendLine("PcrFlag: " + packet.AdaptationField.PcrFlag);
                        //sb.AppendLine("OpcrFlag: " + packet.AdaptationField.OpcrFlag);
                        //sb.AppendLine("SplicingPointFlag: " + packet.AdaptationField.SplicingPointFlag);
                        //sb.AppendLine("TransportPrivateDataFlag: " + packet.AdaptationField.TransportPrivateDataFlag);
                        //sb.AppendLine("AdaptationFieldExtensionFlag: " + packet.AdaptationField.AdaptationFieldExtensionFlag);
                        //sb.AppendLine();
                        //}
                        //sb.AppendLine("TableId: " + packet.ProgramAssociationTable.TableId);
                        //sb.AppendLine("SectionLength: " + packet.ProgramAssociationTable.SectionLength);
                        //sb.AppendLine("TransportStreamId: " + packet.ProgramAssociationTable.TransportStreamId);
                        //sb.AppendLine("VersionNumber: " + packet.ProgramAssociationTable.VersionNumber);
                        //sb.AppendLine("CurrentNextIndicator: " + packet.ProgramAssociationTable.CurrentNextIndicator);
                        //sb.AppendLine("SectionNumber: " + packet.ProgramAssociationTable.SectionNumber);
                        //sb.AppendLine("LastSectionNumber: " + packet.ProgramAssociationTable.LastSectionNumber);
                        //ProgramAssociationTables.Add(packet);
                    }
                    else if (packet.IsPrivateStream1 || SubtitlePacketIds.Contains(packet.PacketId))
                    {
                        TotalNumberOfPrivateStream1++;

                        SubtitlePackets.Add(packet);

                        if (!SubtitlePacketIds.Contains(packet.PacketId))
                        {
                            SubtitlePacketIds.Add(packet.PacketId);
                        }
                        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)
                            //{

                            //}
                        }
                        if (callback != null)
                        {
                            callback.Invoke(ms.Position, transportStreamLength);
                        }
                    }
                    TotalNumberOfPackets++;
                    position += packetLength;
                }
                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);
                    var startMsList = new List <ulong>();
                    var endMsList   = new List <ulong>();
                    foreach (var item in list)
                    {
                        item.WriteToStream(bdMs);
                        if (item.DataIdentifier == 0x16)
                        {
                            if (startMsList.Count <= endMsList.Count)
                            {
                                startMsList.Add(item.PresentationTimestampToMilliseconds());
                            }
                            else
                            {
                                endMsList.Add(item.PresentationTimestampToMilliseconds());
                            }
                        }
                        //else if (item.DataBuffer[0] == 0x80)
                        //{ // TODO: Load bd sub after 0x80, so we can be sure to get correct time code???
                        //    endMsList.Add(item.PresentationTimestampToMilliseconds() / 90);
                        //}
                    }
                    SubtitlesLookup.Add(pid, list);

                    bdMs.Position = 0;
                    var sb     = new StringBuilder();
                    var bdList = BluRaySupParser.ParseBluRaySup(bdMs, sb, true);
                    if (bdList.Count > 0)
                    {
                        var subList = new List <TransportStreamSubtitle>();
                        for (int k = 0; k < bdList.Count; k++)
                        {
                            var   bdSup   = bdList[k];
                            ulong startMs = 0;
                            if (k < startMsList.Count)
                            {
                                startMs = startMsList[k];
                            }
                            ulong endMs = 0;
                            if (k < endMsList.Count)
                            {
                                endMs = endMsList[k];
                            }
                            subList.Add(new TransportStreamSubtitle(bdSup, startMs, endMs, (ulong)((FirstVideoPts + 45) / 90.0)));
                        }
                        DvbSubtitlesLookup.Add(pid, subList);
                    }
                }
                SubtitlePacketIds.Clear();
                foreach (int key in DvbSubtitlesLookup.Keys)
                {
                    SubtitlePacketIds.Add(key);
                }
                SubtitlePacketIds.Sort();
                return;
            }

            // check for SubPictureStreamId = 32
            SubtitlesLookup = new Dictionary <int, List <DvbSubPes> >();
            foreach (int pid in SubtitlePacketIds)
            {
                var  list = MakeSubtitlePesPackets(pid);
                bool hasImageSubtitles = false;
                foreach (var item in list)
                {
                    if (item.IsDvbSubpicture)
                    {
                        hasImageSubtitles = true;
                        break;
                    }
                }
                if (hasImageSubtitles)
                {
                    SubtitlesLookup.Add(pid, list);
                }
            }
            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 + 45) / 90.0);

            foreach (int pid in SubtitlePacketIds)
            {
                var subtitles = new List <TransportStreamSubtitle>();
                var list      = GetSubtitlePesPackets(pid);
                if (list != null)
                {
                    for (int i = 0; i < list.Count; i++)
                    {
                        var pes = list[i];
                        pes.ParseSegments();
                        if (pes.ObjectDataList.Count > 0)
                        {
                            var sub = new TransportStreamSubtitle();
                            sub.StartMilliseconds = pes.PresentationTimestampToMilliseconds();
                            sub.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 + 3500;
                            }
                            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();
        }
示例#10
0
        public List <BluRaySupParser.PcsData> LoadSubtitles(string supFileName)
        {
            var log = new StringBuilder();

            return(BluRaySupParser.ParseBluRaySup(supFileName, log));
        }
        public static List <SubtitleEvent> ReadMatroskaBluraySup(string inputFile, int tracknumber)
        {
            List <SubtitleEvent> events = new List <SubtitleEvent>();
            var matroska             = new MatroskaFile(inputFile);
            var matroskaSubtitleInfo = matroska.GetTracks()[tracknumber];

            var sub = matroska.GetSubtitle(matroskaSubtitleInfo.TrackNumber, (p, t) => Console.WriteLine("Progress: {0} out of {1}", p, t));

            var subtitles         = new List <BluRaySupParser.PcsData>();
            var log               = new StringBuilder();
            var clusterStream     = new MemoryStream();
            var lastPalettes      = new Dictionary <int, List <PaletteInfo> >();
            var lastBitmapObjects = new Dictionary <int, List <BluRaySupParser.OdsData> >();

            foreach (var p in sub)
            {
                byte[] buffer = p.GetData(matroskaSubtitleInfo);
                if (buffer != null && buffer.Length > 2)
                {
                    clusterStream.Write(buffer, 0, buffer.Length);
                    if (ContainsBluRayStartSegment(buffer))
                    {
                        if (subtitles.Count > 0 && subtitles[subtitles.Count - 1].StartTime == subtitles[subtitles.Count - 1].EndTime)
                        {
                            subtitles[subtitles.Count - 1].EndTime = (long)((p.Start - 1) * 90.0);
                        }
                        clusterStream.Position = 0;
                        var list = BluRaySupParser.ParseBluRaySup(clusterStream, log, true, lastPalettes, lastBitmapObjects);
                        foreach (var sup in list)
                        {
                            sup.StartTime = (long)((p.Start - 1) * 90.0);
                            sup.EndTime   = (long)((p.End - 1) * 90.0);
                            subtitles.Add(sup);

                            // fix overlapping
                            if (subtitles.Count > 1 && sub[subtitles.Count - 2].End > sub[subtitles.Count - 1].Start)
                            {
                                subtitles[subtitles.Count - 2].EndTime = subtitles[subtitles.Count - 1].StartTime - 1;
                            }
                        }
                        clusterStream = new MemoryStream();
                    }
                }
                else if (subtitles.Count > 0)
                {
                    var lastSub = subtitles[subtitles.Count - 1];
                    if (lastSub.StartTime == lastSub.EndTime)
                    {
                        lastSub.EndTime = (long)((p.Start - 1) * 90.0);
                        if (lastSub.EndTime - lastSub.StartTime > 1000000)
                        {
                            lastSub.EndTime = lastSub.StartTime;
                        }
                    }
                }
            }

            clusterStream.Dispose();

            int i = 0;

            foreach (var line in subtitles)
            {
                var bitmap = BluRaySupParser.SupDecoder.DecodeImage(line.PcsObjects[0], line.BitmapObjects[0], line.PaletteInfos);

                var image_data = ImageUtil.ConvertToPngBytes(bitmap);
                events.Add(new SubtitleEvent()
                {
                    StartTime = TimeSpan.FromMilliseconds(line.StartTime / 90.0), EndTime = TimeSpan.FromMilliseconds(line.EndTime / 90.0), MimeType = "image/png", Image = image_data, Origin = line.PcsObjects[0].Origin
                });
                i++;
            }
            return(events);
        }
示例#12
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();
        }
示例#13
0
        private void importTimeCodesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (_subtitle.Paragraphs.Count < 1)
            {
                return;
            }

            openFileDialog1.Title    = Configuration.Settings.Language.General.OpenSubtitle;
            openFileDialog1.FileName = string.Empty;
            openFileDialog1.Filter   = UiUtil.SubtitleExtensionFilter.Value;
            if (openFileDialog1.ShowDialog(this) == DialogResult.OK)
            {
                var            timeCodeSubtitle = new Subtitle();
                SubtitleFormat format           = null;

                if (openFileDialog1.FileName.EndsWith(".sup", StringComparison.OrdinalIgnoreCase) &&
                    FileUtil.IsBluRaySup(openFileDialog1.FileName))
                {
                    var log       = new StringBuilder();
                    var subtitles = BluRaySupParser.ParseBluRaySup(openFileDialog1.FileName, log);
                    if (subtitles.Count > 0)
                    {
                        foreach (var sup in subtitles)
                        {
                            timeCodeSubtitle.Paragraphs.Add(new Paragraph(sup.StartTimeCode, sup.EndTimeCode, string.Empty));
                        }

                        format = new SubRip(); // just to set format to something
                    }
                }

                if (format == null)
                {
                    format = timeCodeSubtitle.LoadSubtitle(openFileDialog1.FileName, out var encoding, null);
                }

                if (format == null)
                {
                    var formats = SubtitleFormat.GetBinaryFormats(true).Union(SubtitleFormat.GetTextOtherFormats()).Union(new SubtitleFormat[]
                    {
                        new TimeCodesOnly1(),
                        new TimeCodesOnly2()
                    }).ToArray();
                    format = SubtitleFormat.LoadSubtitleFromFile(formats, openFileDialog1.FileName, timeCodeSubtitle);
                }

                if (format == null)
                {
                    return;
                }

                if (timeCodeSubtitle.Paragraphs.Count != _subtitle.Paragraphs.Count)
                {
                    var text = string.Format(Configuration.Settings.Language.Main.ImportTimeCodesDifferentNumberOfLinesWarning, timeCodeSubtitle.Paragraphs.Count, _subtitle.Paragraphs.Count);
                    if (MessageBox.Show(this, text, Text, MessageBoxButtons.YesNoCancel) != DialogResult.Yes)
                    {
                        return;
                    }
                }

                int count = 0;
                for (int i = 0; i < timeCodeSubtitle.Paragraphs.Count; i++)
                {
                    var existing = _subtitle.GetParagraphOrDefault(i);

                    var newTimeCode = timeCodeSubtitle.GetParagraphOrDefault(i);
                    if (existing == null || newTimeCode == null)
                    {
                        break;
                    }

                    existing.StartTime.TotalMilliseconds = newTimeCode.StartTime.TotalMilliseconds;
                    existing.EndTime.TotalMilliseconds   = newTimeCode.EndTime.TotalMilliseconds;
                    count++;
                }

                MessageBox.Show(string.Format(Configuration.Settings.Language.Main.TimeCodeImportedFromXY, Path.GetFileName(openFileDialog1.FileName), count));
                var idx = subtitleListView1.SelectedItems[0].Index;
                subtitleListView1.Fill(_subtitle);
                subtitleListView1.SelectIndexAndEnsureVisible(_subtitle.GetParagraphOrDefault(idx));
            }
        }