public VobSubMergedPack(byte[] subPictureData, TimeSpan presentationTimestamp, int streamId, IdxParagraph idxLine)
 {
     SubPicture = new SubPicture(subPictureData);
     StartTime = presentationTimestamp;
     StreamId = streamId;
     IdxLine = idxLine;
 }
 public VobSubMergedPack(byte[] subPictureData, TimeSpan presentationTimestamp, int streamId, IdxParagraph idxLine)
 {
     SubPicture = new SubPicture(subPictureData);
     StartTime  = presentationTimestamp;
     StreamId   = streamId;
     IdxLine    = idxLine;
 }
        /// <summary>
        /// Demultiplex multiplexed packs together each streamId at a time + removing bad packs + fixing displaytimes
        /// </summary>
        /// <returns>List of complete packs each with a complete sub image</returns>
        public List <VobSubMergedPack> MergeVobSubPacks()
        {
            var list     = new List <VobSubMergedPack>();
            var pts      = new TimeSpan();
            var ms       = new MemoryStream();
            int streamId = 0;

            float ticksPerMillisecond = 90.000F;

            if (!IsPal)
            {
                ticksPerMillisecond = 90.090F; // TODO: What should this be for NTSC?
            }
            // get unique streamIds
            var uniqueStreamIds = new List <int>();

            foreach (var p in VobSubPacks)
            {
                if (p.PacketizedElementaryStream != null &&
                    p.PacketizedElementaryStream.SubPictureStreamId.HasValue &&
                    !uniqueStreamIds.Contains(p.PacketizedElementaryStream.SubPictureStreamId.Value))
                {
                    uniqueStreamIds.Add(p.PacketizedElementaryStream.SubPictureStreamId.Value);
                }
            }

            IdxParagraph lastIdxParagraph = null;

            foreach (int uniqueStreamId in uniqueStreamIds) // packets must be merged in streamId order (so they don't get mixed)
            {
                foreach (var p in VobSubPacks)
                {
                    if (p.PacketizedElementaryStream != null && p.PacketizedElementaryStream.SubPictureStreamId.HasValue &&
                        p.PacketizedElementaryStream.SubPictureStreamId.Value == uniqueStreamId)
                    {
                        if (p.PacketizedElementaryStream.PresentationTimestampDecodeTimestampFlags > 0)
                        {
                            if (lastIdxParagraph == null || p.IdxLine.FilePosition != lastIdxParagraph.FilePosition)
                            {
                                if (ms.Length > 0)
                                {
                                    list.Add(new VobSubMergedPack(ms.ToArray(), pts, streamId, lastIdxParagraph));
                                }
                                ms.Close();
                                ms       = new MemoryStream();
                                pts      = TimeSpan.FromMilliseconds(Convert.ToDouble(p.PacketizedElementaryStream.PresentationTimestamp / ticksPerMillisecond)); //90000F * 1000)); (PAL)
                                streamId = p.PacketizedElementaryStream.SubPictureStreamId.Value;
                            }
                        }
                        lastIdxParagraph = p.IdxLine;
                        p.PacketizedElementaryStream.WriteToStream(ms);
                    }
                }
                if (ms.Length > 0)
                {
                    list.Add(new VobSubMergedPack(ms.ToArray(), pts, streamId, lastIdxParagraph));
                    ms.Close();
                    ms = new MemoryStream();
                }
            }
            ms.Close();

            // Remove any bad packs
            for (int i = list.Count - 1; i >= 0; i--)
            {
                VobSubMergedPack pack = list[i];
                if (pack.SubPicture == null || pack.SubPicture.ImageDisplayArea.Width <= 3 || pack.SubPicture.ImageDisplayArea.Height <= 2)
                {
                    list.RemoveAt(i);
                }
                else if (pack.EndTime.TotalSeconds - pack.StartTime.TotalSeconds < 0.1 && pack.SubPicture.ImageDisplayArea.Width <= 10 && pack.SubPicture.ImageDisplayArea.Height <= 10)
                {
                    list.RemoveAt(i);
                }
            }

            // Fix subs with no duration (completely normal) or negative duration or duration > 10 seconds
            for (int i = 0; i < list.Count; i++)
            {
                VobSubMergedPack pack = list[i];
                if (pack.SubPicture.Delay.TotalMilliseconds > 0)
                {
                    pack.EndTime = pack.StartTime.Add(pack.SubPicture.Delay);
                }

                if (pack.EndTime < pack.StartTime || pack.EndTime.TotalSeconds - pack.StartTime.TotalSeconds > 10.0)
                {
                    if (i + 1 < list.Count)
                    {
                        pack.EndTime = TimeSpan.FromMilliseconds(list[i].StartTime.TotalMilliseconds - 100);
                    }
                    else
                    {
                        pack.EndTime = TimeSpan.FromMilliseconds(pack.StartTime.TotalMilliseconds + 3000);
                    }
                }
            }

            return(list);
        }
Exemple #4
0
        public Idx(string[] lines)
        {
            int languageIndex = 0;

            foreach (string line in lines)
            {
                if (_timeCodeLinePattern.IsMatch(line))
                {
                    IdxParagraph p = GetTimeCodeAndFilePosition(line);
                    if (p != null)
                    {
                        IdxParagraphs.Add(p);
                    }
                }
                else if (line.StartsWith("palette:", StringComparison.OrdinalIgnoreCase) && line.Length > 10)
                {
                    string   s      = line.Substring("palette:".Length + 1);
                    string[] colors = s.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string hex in colors)
                    {
                        Palette.Add(HexToColor(hex));
                    }
                }
                else if (line.StartsWith("id:", StringComparison.OrdinalIgnoreCase) && line.Length > 4)
                {
                    //id: en, index: 1
                    //id: es, index: 2
                    var parts = line.Split(new[] { ':', ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    if (parts.Length > 1)
                    {
                        string twoLetterLanguageId = parts[1];
                        string nativeName;
                        if (IfoParser.LanguageCodes.Contains(twoLetterLanguageId))
                        {
                            nativeName = IfoParser.LanguageNames[IfoParser.LanguageCodes.IndexOf(twoLetterLanguageId)];
                        }
                        else
                        {
                            try
                            {
                                nativeName = CultureInfo.GetCultureInfoByIetfLanguageTag(twoLetterLanguageId).NativeName;
                            }
                            catch
                            {
                                nativeName = "Unknown (" + twoLetterLanguageId + ")";
                            }
                        }
                        if (parts.Length > 3 && parts[2].Equals("index", StringComparison.OrdinalIgnoreCase))
                        {
                            int index;
                            if (int.TryParse(parts[3], out index))
                            {
                                languageIndex = index;
                            }
                        }
                        // Use U+200E (LEFT-TO-RIGHT MARK) to support right-to-left scripts
                        Languages.Add(string.Format("{0} \x200E(0x{1:x})", nativeName, languageIndex + 32));
                        languageIndex++;
                    }
                }
            }
        }