private void RipSubtitles(string vobFileName, MemoryStream stream, int vobNumber) { long firstNavStartPts = 0; using (var fs = RetryOpenRead(vobFileName)) { var buffer = new byte[0x800]; long position = 0; progressBarRip.Maximum = 100; progressBarRip.Value = 0; int lba = 0; long length = fs.Length; while (position < length && !_abort) { int bytesRead = 0; // Reading and test for IO errors... and allow abort/retry/ignore var tryAgain = true; while (tryAgain && position < length) { tryAgain = false; try { fs.Seek(position, SeekOrigin.Begin); bytesRead = fs.Read(buffer, 0, 0x800); } catch (IOException exception) { var result = MessageBox.Show(string.Format("An error occured while reading file: {0}", exception.Message), "", MessageBoxButtons.AbortRetryIgnore); if (result == DialogResult.Abort) { return; } if (result == DialogResult.Retry) { tryAgain = true; } if (result == DialogResult.Ignore) { position += 0x800; tryAgain = true; } } } if (VobSubParser.IsMpeg2PackHeader(buffer)) { var vsp = new VobSubPack(buffer, null); if (IsSubtitlePack(buffer)) { if (vsp.PacketizedElementaryStream.PresentationTimestamp.HasValue && _accumulatedPresentationTimestamp != 0) { UpdatePresentationTimestamp(buffer, _accumulatedPresentationTimestamp, vsp); } stream.Write(buffer, 0, 0x800); if (bytesRead < 0x800) { stream.Write(Encoding.ASCII.GetBytes(new string(' ', 0x800 - bytesRead)), 0, 0x800 - bytesRead); } } else if (IsPrivateStream2(buffer, 0x26)) { if (Helper.GetEndian(buffer, 0x0026, 4) == 0x1bf && Helper.GetEndian(buffer, 0x0400, 4) == 0x1bf) { uint vobuSPtm = Helper.GetEndian(buffer, 0x0039, 4); uint vobuEPtm = Helper.GetEndian(buffer, 0x003d, 4); _lastPresentationTimestamp = vobuEPtm; if (firstNavStartPts == 0) { firstNavStartPts = vobuSPtm; if (vobNumber == 0) { _accumulatedPresentationTimestamp = -vobuSPtm; } } if (vobuSPtm + firstNavStartPts + _accumulatedPresentationTimestamp < _lastVobPresentationTimestamp) { _accumulatedPresentationTimestamp += _lastNavEndPts - vobuSPtm; } else if (_lastNavEndPts > vobuEPtm) { _accumulatedPresentationTimestamp += _lastNavEndPts - vobuSPtm; } _lastNavEndPts = vobuEPtm; } } } position += 0x800; var progress = (int)((position * 100) / length); if (progress != progressBarRip.Value) { progressBarRip.Value = progress; TaskbarList.SetProgressValue(_taskbarFormHandle, (vobNumber * 100) + progressBarRip.Value, progressBarRip.Maximum * listBoxVobFiles.Items.Count); Application.DoEvents(); } lba++; } } _lastVobPresentationTimestamp = _lastPresentationTimestamp; }
/// <summary> /// Write the 5 PTS bytes to buffer /// </summary> private static void UpdatePresentationTimestamp(byte[] buffer, long addPresentationTimestamp, VobSubPack vsp) { const int presentationTimestampIndex = 23; long newPts = addPresentationTimestamp + ((long)vsp.PacketizedElementaryStream.PresentationTimestamp.Value); var buffer5B = BitConverter.GetBytes((UInt64)newPts); if (BitConverter.IsLittleEndian) { buffer[presentationTimestampIndex + 4] = (byte)(buffer5B[0] << 1 | 0b00000001); // last 7 bits + '1' buffer[presentationTimestampIndex + 3] = (byte)((buffer5B[0] >> 7) + (buffer5B[1] << 1)); // the next 8 bits (1 from last byte, 7 from next) buffer[presentationTimestampIndex + 2] = (byte)((buffer5B[1] >> 6 | 0b00000001) + (buffer5B[2] << 2)); // the next 7 bits (1 from 2nd last byte, 6 from 3rd last byte) buffer[presentationTimestampIndex + 1] = (byte)((buffer5B[2] >> 6) + (buffer5B[3] << 2)); // the next 8 bits (2 from 3rd last byte, 6 from 2rd last byte) buffer[presentationTimestampIndex] = (byte)((buffer5B[3] >> 6 | 0b00000001) + (buffer5B[4] << 2)); } else { buffer[presentationTimestampIndex + 4] = (byte)(buffer5B[7] << 1 | 0b00000001); // last 7 bits + '1' buffer[presentationTimestampIndex + 3] = (byte)((buffer5B[7] >> 7) + (buffer5B[6] << 1)); // the next 8 bits (1 from last byte, 7 from next) buffer[presentationTimestampIndex + 2] = (byte)((buffer5B[6] >> 6 | 0b00000001) + (buffer5B[5] << 2)); // the next 7 bits (1 from 2nd last byte, 6 from 3rd last byte) buffer[presentationTimestampIndex + 1] = (byte)((buffer5B[5] >> 6) + (buffer5B[4] << 2)); // the next 8 bits (2 from 3rd last byte, 6 from 2rd last byte) buffer[presentationTimestampIndex] = (byte)((buffer5B[4] >> 6 | 0b00000001) + (buffer5B[3] << 2)); } if (vsp.PacketizedElementaryStream.PresentationTimestampDecodeTimestampFlags == 0b00000010) { buffer[presentationTimestampIndex] += 0b00100000; } else { buffer[presentationTimestampIndex] += 0b00110000; } }
private void RipSubtitles(string vobFileName, MemoryStream stream, int vobNumber) { long firstNavStartPTS = 0; FileStream fs = null; bool tryAgain = true; while (tryAgain) { try { fs = new FileStream(vobFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); tryAgain = false; } catch (IOException exception) { var result = MessageBox.Show(string.Format("An error occured while opening file: {0}", exception.Message), "", MessageBoxButtons.RetryCancel); if (result == DialogResult.Cancel) { return; } if (result == DialogResult.Retry) { tryAgain = true; } } } byte[] buffer = new byte[0x800]; long position = 0; progressBarRip.Maximum = 100; progressBarRip.Value = 0; int lba = 0; long length = fs.Length; while (position < length && !_abort) { int bytesRead = 0; // Reading and test for IO errors... and allow abort/retry/ignore tryAgain = true; while (tryAgain && position < length) { tryAgain = false; try { fs.Seek(position, SeekOrigin.Begin); bytesRead = fs.Read(buffer, 0, 0x0800); } catch (IOException exception) { var result = MessageBox.Show(string.Format("An error occured while reading file: {0}", exception.Message), "", MessageBoxButtons.AbortRetryIgnore); if (result == DialogResult.Abort) { return; } if (result == DialogResult.Retry) { tryAgain = true; } if (result == DialogResult.Ignore) { position += 0x800; tryAgain = true; } } } if (VobSubParser.IsMpeg2PackHeader(buffer)) { VobSubPack vsp = new VobSubPack(buffer, null); if (IsSubtitlePack(buffer)) { if (vsp.PacketizedElementaryStream.PresentationTimeStamp.HasValue && _accumulatedPresentationTimeStamp != 0) { UpdatePresentationTimeStamp(buffer, _accumulatedPresentationTimeStamp, vsp); } stream.Write(buffer, 0, 0x800); if (bytesRead < 0x800) { stream.Write(Encoding.ASCII.GetBytes(new string(' ', 0x800 - bytesRead)), 0, 0x800 - bytesRead); } } else if (IsPrivateStream2(buffer, 0x26)) { if (Helper.GetEndian(buffer, 0x0026, 4) == 0x1bf && Helper.GetEndian(buffer, 0x400, 4) == 0x1bf) { uint vobu_s_ptm = Helper.GetEndian(buffer, 0x0039, 4); uint vobu_e_ptm = Helper.GetEndian(buffer, 0x003d, 4); _lastPresentationTimeStamp = vobu_e_ptm; if (firstNavStartPTS == 0) { firstNavStartPTS = vobu_s_ptm; if (vobNumber == 0) { _accumulatedPresentationTimeStamp = -vobu_s_ptm; } } if (vobu_s_ptm + firstNavStartPTS + _accumulatedPresentationTimeStamp < _lastVobPresentationTimeStamp) { _accumulatedPresentationTimeStamp += _lastNavEndPts - vobu_s_ptm; } else if (_lastNavEndPts > vobu_e_ptm) { _accumulatedPresentationTimeStamp += _lastNavEndPts - vobu_s_ptm; } _lastNavEndPts = vobu_e_ptm; } } } position += 0x800; progressBarRip.Value = (int)((position * 100) / length); Application.DoEvents(); lba++; } fs.Close(); _lastVobPresentationTimeStamp = _lastPresentationTimeStamp; }