Example #1
0
        private void CycleCompositionStateButton_Click(object sender, RoutedEventArgs e)
        {
            if (CompositionState == WindowCompositionState.Alpha)
            {
                CompositionState = WindowCompositionState.Glass;
            }
            else if (CompositionState == WindowCompositionState.Glass)
            {
                CompositionState = WindowCompositionState.Accent;
            }
            else if (CompositionState == WindowCompositionState.Accent)
            {
                CompositionState = WindowCompositionState.Acrylic;
            }
            else
            {
                CompositionState = WindowCompositionState.Alpha;
            }

            CurrentCompositionStateTextBlock.Text = CompositionState.ToString();
        }
Example #2
0
        /// <summary>
        /// Can be used with e.g. MemoryStream or FileStream
        /// </summary>
        /// <param name="ms">memory stream containing sup data</param>
        /// <param name="log">Text parser log</param>
        public static List <BluRaySupPicture> ParseBluRaySup(Stream ms, StringBuilder log, bool fromMatroskaFile)
        {
            SupSegment              segment;
            BluRaySupPicture        pic         = null;
            BluRaySupPicture        picLast     = null;
            BluRaySupPicture        picTmp      = null;
            List <BluRaySupPicture> subPictures = new List <BluRaySupPicture>();
            int              odsCtr             = 0;
            int              pdsCtr             = 0;
            int              odsCtrOld          = 0;
            int              pdsCtrOld          = 0;
            int              compNum            = -1;
            int              compNumOld         = -1;
            int              compCount          = 0;
            long             ptsPcs             = 0;
            bool             paletteUpdate      = false;
            CompositionState cs = CompositionState.Invalid;

            ms.Position = 0;
            long      position   = 0;
            int       i          = 0;
            const int headerSize = 13;

            byte[] buffer;
            while (position < ms.Length)
            {
                string[] so = new string[1]; // hack to return string

                ms.Seek(position, SeekOrigin.Begin);

                if (fromMatroskaFile)
                {
                    buffer = new byte[3];
                    ms.Read(buffer, 0, buffer.Length);
                    segment   = ReadSegmentFromMatroska(buffer, log);
                    position += 3;
                }
                else
                {
                    buffer = new byte[headerSize];
                    ms.Read(buffer, 0, buffer.Length);
                    segment   = ReadSegment(buffer, log);
                    position += headerSize;
                }

                buffer = new byte[segment.Size];
                ms.Read(buffer, 0, buffer.Length);
                log.Append(i + ": ");
                switch (segment.Type)
                {
                case 0x14:     // Palette
                    log.Append(string.Format("0x14 - Palette - PDS offset={0} size={1}", position, segment.Size));

                    if (compNum != compNumOld)
                    {
                        if (pic != null)
                        {
                            so[0] = null;
                            int ps = ParsePds(buffer, segment, pic, so);
                            if (ps >= 0)
                            {
                                log.AppendLine(", " + so[0]);
                                if (ps > 0)     // don't count empty palettes
                                {
                                    pdsCtr++;
                                }
                            }
                            else
                            {
                                log.AppendLine();
                                log.AppendLine(so[0]);
                            }
                        }
                        else
                        {
                            log.AppendLine();
                            log.AppendLine("missing PTS start -> ignored");
                        }
                    }
                    else
                    {
                        log.AppendLine(", comp # unchanged -> ignored");
                    }
                    break;

                case 0x15:     // Image bitmap data
                    log.Append(string.Format("0x15 - bitmap data - ODS offset={0} size={1}", position, segment.Size));

                    if (compNum != compNumOld)
                    {
                        if (!paletteUpdate)
                        {
                            if (pic != null)
                            {
                                so[0] = null;
                                if (ParseOds(buffer, segment, pic, so))
                                {
                                    odsCtr++;
                                }
                                if (so[0] != null)
                                {
                                    log.Append(", " + so[0]);
                                }
                                log.AppendLine(", img size: " + pic.Width + "*" + pic.Height);
                            }
                            else
                            {
                                log.AppendLine();
                                log.AppendLine("missing PTS start -> ignored");
                            }
                        }
                        else
                        {
                            log.AppendLine();
                            log.AppendLine("palette update only -> ignored");
                        }
                    }
                    else
                    {
                        log.AppendLine(", comp # unchanged -> ignored");
                    }
                    break;

                case 0x16:
                    log.Append(string.Format("0x16 - Time codes, offset={0} size={1}", position, segment.Size));

                    compNum       = BigEndianInt16(buffer, 5);
                    cs            = GetCompositionState(buffer[7]);
                    paletteUpdate = buffer[8] == 0x80;
                    ptsPcs        = segment.PtsTimestamp;
                    if (segment.Size >= 0x13)
                    {
                        compCount = 1;     // could be also 2, but we'll ignore this for the moment
                    }
                    else
                    {
                        compCount = 0;
                    }
                    if (cs == CompositionState.Invalid)
                    {
                        log.AppendLine("Illegal composition state at offset " + position);
                    }
                    else if (cs == CompositionState.EpochStart)
                    {
                        //new frame
                        if (subPictures.Count > 0 && (odsCtr == 0 || pdsCtr == 0))
                        {
                            log.AppendLine("missing PDS/ODS: last epoch is discarded");
                            subPictures.RemoveAt(subPictures.Count - 1);
                            compNumOld = compNum - 1;
                            if (subPictures.Count > 0)
                            {
                                picLast = subPictures[subPictures.Count - 1];
                            }
                            else
                            {
                                picLast = null;
                            }
                        }
                        else
                        {
                            picLast = pic;
                        }

                        pic = new BluRaySupPicture();
                        subPictures.Add(pic);     // add to list
                        pic.StartTime = segment.PtsTimestamp;
                        log.Append("#> " + (subPictures.Count) + " (" + ToolBox.PtsToTimeString(pic.StartTime) + ")");

                        so[0] = null;
                        ParsePcs(segment, pic, so, buffer);
                        // fix end time stamp of previous pic if still missing
                        if (picLast != null && picLast.EndTime == 0)
                        {
                            picLast.EndTime = pic.StartTime;
                        }

                        if (so[0] != null)
                        {
                            log.Append(", " + so[0]);
                        }
                        log.Append(", PTS start: " + ToolBox.PtsToTimeString(pic.StartTime));
                        log.AppendLine(", screen size: " + pic.Width + "*" + pic.Height);
                        odsCtr    = 0;
                        pdsCtr    = 0;
                        odsCtrOld = 0;
                        pdsCtrOld = 0;
                        picTmp    = null;
                    }
                    else
                    {
                        if (pic == null)
                        {
                            log.AppendLine(" Missing start of epoch at offset " + position);
                            break;
                        }
                        log.Append("PCS ofs:" + ToolBox.ToHex(buffer, 0, 8) + ", ");
                        switch (cs)
                        {
                        case CompositionState.EpochContinue:
                            log.AppendLine(" CONT, ");
                            break;

                        case CompositionState.AcquPoint:
                            log.AppendLine(" ACQU, ");
                            break;

                        case CompositionState.Normal:
                            log.AppendLine(" NORM, ");
                            break;
                        }
                        log.Append("size: " + segment.Size + ", comp#: " + compNum + ", forced: " + pic.IsForced);
                        if (compNum != compNumOld)
                        {
                            so[0] = null;
                            // store state to be able to revert to it
                            picTmp         = new BluRaySupPicture(pic); // deep copy
                            picTmp.EndTime = ptsPcs;
                            // create new pic
                            ParsePcs(segment, pic, so, buffer);
                        }
                        if (so[0] != null)
                        {
                            log.Append(", " + so[0]);
                        }
                        log.AppendLine(", pal update: " + paletteUpdate);
                        log.AppendLine("PTS: " + ToolBox.PtsToTimeString(segment.PtsTimestamp));
                    }
                    break;

                case 0x17:
                    log.Append(string.Format("0x17 - WDS offset={0} size={1}", position, segment.Size));

                    int x      = BigEndianInt16(buffer, 2);
                    int y      = BigEndianInt16(buffer, 4);
                    int width  = BigEndianInt16(buffer, 6);
                    int height = BigEndianInt16(buffer, 8);

                    log.AppendLine(string.Format(", width:{0}, height:{1}   x,y={2},{3}", width, height, x, y));
                    break;

                case 0x80:
                    log.Append(string.Format("0x80 - END offset={0} size={1}", position, segment.Size));

                    // decide whether to store this last composition section as caption or merge it
                    if (cs == CompositionState.EpochStart)
                    {
                        if (compCount > 0 && odsCtr > odsCtrOld && compNum != compNumOld && IsPictureMergable(picLast, pic))
                        {
                            // the last start epoch did not contain any (new) content
                            // and should be merged to the previous frame
                            subPictures.RemoveAt(subPictures.Count - 1);
                            pic = picLast;
                            if (subPictures.Count > 0)
                            {
                                picLast = subPictures[subPictures.Count - 1];
                            }
                            else
                            {
                                picLast = null;
                            }
                            log.AppendLine("#< caption merged");
                        }
                    }
                    else
                    {
                        long startTime = 0;
                        if (pic != null)
                        {
                            startTime     = pic.StartTime; // store
                            pic.StartTime = ptsPcs;        // set for testing merge
                        }

                        if (compCount > 0 && odsCtr > odsCtrOld && compNum != compNumOld && !IsPictureMergable(picTmp, pic))
                        {
                            // last PCS should be stored as separate caption
                            if (odsCtr - odsCtrOld > 1 || pdsCtr - pdsCtrOld > 1)
                            {
                                log.AppendLine("multiple PDS/ODS definitions: result may be erratic");
                            }
                            // replace pic with picTmp (deepCopy created before new PCS)
                            subPictures[subPictures.Count - 1] = picTmp; // replace in list
                            picLast = picTmp;
                            subPictures.Add(pic);                        // add to list
                            log.AppendLine("#< " + (subPictures.Count) + " (" + ToolBox.PtsToTimeString(pic.StartTime) + ")");
                            odsCtrOld = odsCtr;
                        }
                        else
                        {
                            if (pic != null)
                            {
                                // merge with previous pic
                                pic.StartTime = startTime;     // restore
                                pic.EndTime   = ptsPcs;
                                // for the unlikely case that forced flag changed during one captions
                                if (picTmp != null && picTmp.IsForced)
                                {
                                    pic.IsForced = true;
                                }

                                if (pdsCtr > pdsCtrOld || paletteUpdate)
                                {
                                    log.AppendLine("palette animation: result may be erratic\n");
                                }
                            }
                            else
                            {
                                log.AppendLine("end without at least one epoch start");
                            }
                        }
                    }

                    pdsCtrOld  = pdsCtr;
                    compNumOld = compNum;
                    break;

                default:
                    log.AppendLine(string.Format("0x?? - END offset={0} UNKOWN SEGMENT TYPE={1}", position, segment.Type));
                    break;
                }
                log.AppendLine();
                position += segment.Size;
                i++;
            }
            //    File.WriteAllText(@"C:\Users\Nikse\Desktop\Blu-Ray Sup\log.txt", log.ToString());
            return(subPictures);
        }