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(); }
/// <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); }