Пример #1
0
		private void button3_Click(object sender, System.EventArgs e)
		{
            try
            {
                lock (this)
                {
                    List<IFOParse.VOB> vobs = null;
                    IFOParse.ProgramChain pgc = null;
                    List<IFOParse.Cell> cells = null;
                    if (treeView1.SelectedNode == null)
                        return;
                    if (treeView1.SelectedNode.Tag.GetType() == typeof(FileInfo))
                    {
                        // got single vob file
                        FileInfo fi = (FileInfo)treeView1.SelectedNode.Tag;
                        IFOParse.VOB v = new IFOParse.VOB(fi.FullName);
                        vobs = new List<IFOParse.VOB>();
                        vobs.Add(v);

                        // create dummy cell list
                        cells = new List<IFOParse.Cell>();
                        IFOParse.Cell c = new IFOParse.Cell();
                        c.FirstSector = 0;
                        c.LastSector = (int)v.LastSector;
                        cells.Add(c);
                    }
                    else if (treeView1.SelectedNode.Tag.GetType() == typeof(IFOParse.ProgramChain))
                    {
                        pgc = (IFOParse.ProgramChain)treeView1.SelectedNode.Tag;
                        vobs = pgc.Title.VOBs;
                        cells = pgc.Cells;
                    }


                    m_ds = new DSUtils();
                    ArrayList ranges = new ArrayList();
                    ArrayList vobNames = new ArrayList();
                    for (int c = 0; c < cells.Count; c++)
                    {
                        ranges.Add(cells[c].FirstSector);
                        ranges.Add(cells[c].LastSector);
                    }
                    for (int v = 0; v < vobs.Count; v++)
                    {
                        vobNames.Add(vobs[v].FileInfo.FullName);
                        vobNames.Add(vobs[v].Sectors);
                    }
                    m_ds.Preview(ranges, vobNames, panel1.Handle, trackBar1.Value);
                    button3.Enabled = false;
                    button4.Enabled = true;
                    button5.Enabled = true;
                    if (Settings.Default.AudioMode)
                    {
                        label9.Visible = true;
                        label10.Visible = true;
                    }

                    m_videoThread = new Thread(new ThreadStart(PlaybackProgress));
                    m_videoThread.Start();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(String.Format("Error starting preview: {0}", ex.Message));
            }
		}
Пример #2
0
		private void ProcessVOB()
		{
			try
			{
				DisableForm();
				List<IFOParse.VOB> vobs = null;
				IFOParse.ProgramChain pgc = null;
				List<IFOParse.Cell> cells = null;
				int selectedAudioTrack = 0;
				if (treeView1.SelectedNode.Tag.GetType() == typeof(FileInfo))
				{
					// treat a single vob file with no ifo file as all data
					// got single vob file
					FileInfo fi = (FileInfo)treeView1.SelectedNode.Tag;
					IFOParse.VOB v = new IFOParse.VOB(fi.FullName);
					vobs = new List<IFOParse.VOB>();
					vobs.Add(v);

					// create dummy cell list
					cells = new List<IFOParse.Cell>();
					IFOParse.Cell c = new IFOParse.Cell();
					c.FirstSector = 0;
					c.LastSector = (int)v.LastSector;
					cells.Add(c);
				}
				else if (treeView1.SelectedNode.Tag.GetType() == typeof(IFOParse.ProgramChain))
				{
					pgc = (IFOParse.ProgramChain)treeView1.SelectedNode.Tag;
					vobs = pgc.Title.VOBs;
					cells = pgc.Cells;
					// if we have multiple audio streams, allow the user to select which one to use
					if (pgc.Title.AudioFormat.Count > 1)
					{
						SelectAudio audioSelector = new SelectAudio(pgc.Title.AudioFormat);
						if (audioSelector.ShowDialog() == DialogResult.Cancel)
							return;
						selectedAudioTrack = audioSelector.SelectedSubstreamID;
					}
				}

				//string outputDir = "";
				#region Choose a file, default to last directory used
				string saveFile = "";
				saveFileDialog1.FileName = textBox2.Text + "-" + textBox4.Text + "-" + textBox3.Text + ".mpg";
				saveFileDialog1.FileName = new Utilities().MakeSafeFilename(saveFileDialog1.FileName);

				RegistryKey rk = Registry.LocalMachine.OpenSubKey(REGISTRY_KEY);
				if (rk != null)
				{
					string initialDir = rk.GetValue("DefaultDirectory").ToString();
					if (initialDir != null && Directory.Exists(initialDir))
						saveFileDialog1.InitialDirectory = initialDir;
				}
				DialogResult dr = saveFileDialog1.ShowDialog();
				if (dr == DialogResult.OK && File.Exists(saveFileDialog1.FileName))
				{
					dr = DialogResult.Cancel;
					// ask about overwriting
					if (MessageBox.Show(saveFileDialog1.FileName + " already exists.\nDo you want to replace it?", "Save As", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
					{
						dr = DialogResult.OK;
						File.Delete(saveFileDialog1.FileName);
					}
				}
				if (dr == DialogResult.OK)
				{
					saveFile = saveFileDialog1.FileName;
					FileInfo fi = new FileInfo(saveFile);
					try
					{
						RegistryKey saveKey = Registry.LocalMachine.CreateSubKey(REGISTRY_KEY);
						saveKey.SetValue("DefaultDirectory", fi.Directory.FullName);
						//outputDir = fi.Directory.FullName;
					}
					catch { }
				}
				else
				{
					SetProgress(0);
					SetStatusText("");
					EnableForm();
					thread = null;
					return;
				}
				#endregion

				int audioOffset = 0;
				int videoOffset = 0;
				string audio = null;
				string video = null;

				m_startTime = DateTime.Now;
				m_lastSecond = 0;

				try
				{
					SetProgress(0);
					byte[] buf = new byte[2048];
					long totalSectors = 0;
					long currentSector = 0;
					// find total number of sectors for all cells
					for (int cellNum = 0; cellNum < cells.Count; cellNum++)
					{
						IFOParse.Cell cell = cells[cellNum];
						totalSectors += cell.LastSector - cell.FirstSector;
					}

					SetStatusText("Reading from DVD...");
					for (int cellNum = 0; cellNum < cells.Count; cellNum++)
					{
						IFOParse.Cell cell = cells[cellNum];
						ulong updateInterval = 0;
						for (int sector = cell.FirstSector; sector <= cell.LastSector; sector++)
						{
							ReadSector(vobs, buf, sector);
							if (updateInterval++ % 10 == 0)
							{
								SetStatusText("Reading from DVD..." + Convert.ToInt32(100.0 * (Convert.ToDouble(currentSector) / Convert.ToDouble(totalSectors))) + "%");
								SetProgress(Convert.ToInt32(m_demuxCount * (Convert.ToDouble(currentSector) / Convert.ToDouble(totalSectors))));
							}
							currentSector++;
							uint code = ReadCode(buf, 0);
							if (code != BLOCK_START_CODE)
								continue;

							int i = 0x0e;
							ulong systemCode = ReadCode(buf, i);
							i += 4;
							UInt16 headerLength = ReadWord(buf, i);
							i += 2;

							switch (systemCode)
							{
								case AC3_DETECT_BYTES:
									//if (!inCell)
									//	break;
									//audPacks++;
									#region write non-mpeg audio data to temp file
									UInt16 flags = ReadWord(buf, i);
									i += 2;
									byte b = buf[i++];
									#region find ms offset
									if ((flags & 0xc000) == 0x8000 && (flags & 0xff) >= 0x80 && audioOffset == 0)
									{
										byte c = buf[i++];
										int offset = (c & 0x0e) << 29;
										offset += (ReadWord(buf, i) & 0xfffe) << 14;
										i += 2;
										offset += (ReadWord(buf, i) >> 1) & 0x7fff;
										i += 2;
										offset /= 90;
										i += b - 5;
										audioOffset = offset;
									}
									else
										i += b;
									#endregion
									byte substream = buf[i++];
									i++; // # frame headers
									UInt16 pointer = ReadWord(buf, i);
									i += 2;
									int t = substream;
									string name = t.ToString("000");
									if (t >= 0xA8) // nothing
										continue;
									else if (t >= 0xA0) // PCM
									{
										// http://dvd.sourceforge.net/dvdinfo/index.html
										name += ".wav";
										i++; // emph, mute, reserved, frame #
										byte details = buf[i++];
										i++; // dynamic range;

										// these seem to be zeroed out in my tests, ignore them
										int bitsPerSample = (details & 0xC0) >> 6;
										int sampleRate = (details & 0x30) >> 4;
										int numChannels = details & 0x07;
										b += 3;
									}
									else if (t >= 0x88) // DTS
										name += ".dts"; // dts audio will be ignored (most dvds are ac3, or at least have an ac3 track)
									else if (t >= 0x80) // AC3
										name += ".ac3";
									else
										continue;
									FileStream w = null;
									if (writers.ContainsKey(name))
										w = (FileStream)writers[name];
									else
									{
										w = File.Create(TempPath + name);
										writers[name] = w;
										if (name.EndsWith(".wav")) // leave room for wav header
											w.Seek(44, SeekOrigin.Begin);
									}
									//SaveData(w, buf, i, 2048 - i, t);
									SaveData(w, buf, i, (headerLength - 7 - b), t);
									#endregion
									break;
								case VID_DETECT_BYTES:
									//if (!inCell)
									//	break;
									//vidPacks++;
									#region write mpeg video to temp file
									flags = ReadWord(buf, i);
									i += 2;
									b = buf[i++];
									#region find ms offset
									if ((flags & 0xc000) == 0x8000 && (flags & 0xff) >= 0x80 && videoOffset == 0)
									{
										byte c = buf[i++];
										int offset = (c & 0x0e) << 29;
										offset += (ReadWord(buf, i) & 0xfffe) << 14;
										i += 2;
										offset += (ReadWord(buf, i) >> 1) & 0x7fff;
										i += 2;
										offset /= 90;
										i += b - 5;
										videoOffset = offset;
									}
									else
										i += b;
									#endregion
									string vname = "video.m2v";
									video = vname;
									FileStream vw = null;
									if (writers.ContainsKey(vname))
										vw = (FileStream)writers[vname];
									else
									{
										vw = File.Create(TempPath + vname);
										writers[vname] = vw;
									}
									//SaveData(vw, buf, i, 2048 - i, 1);
									SaveData(vw, buf, i, (headerLength - 3 - b), 1);
									#endregion
									break;
								case AUD_DETECT_BYTES:
									//if (!inCell)
									//	break;
									//audPacks++;
									#region write mpeg audio to temp file
									flags = ReadWord(buf, i);
									i += 2;
									b = buf[i++];
									#region find ms offset
									if ((flags & 0xc000) == 0x8000 && (flags & 0xff) >= 0x80 && audioOffset == 0)
									{
										byte c = buf[i++];
										int offset = (c & 0x0e) << 29;
										offset += (ReadWord(buf, i) & 0xfffe) << 14;
										i += 2;
										offset += (ReadWord(buf, i) >> 1) & 0x7fff;
										i += 2;
										offset /= 90;
										i += b - 5;
										audioOffset = offset;
									}
									else
										i += b;
									#endregion
									string aname = "vob.mp2";
									if (audio == null)
										audio = aname;
									FileStream aw = null;
									if (writers.ContainsKey(aname))
										aw = (FileStream)writers[aname];
									else
									{
										aw = File.Create(TempPath + aname);
										writers[aname] = aw;
									}
									//SaveData(aw, buf, i, 2048 - i, 0);
									SaveData(aw, buf, i, (headerLength - 3 - b), 1);
									#endregion
									break;
								case NAV_DETECT_BYTES:
									//navPacks++;
									#region find vobID and cellID
									int cellID = buf[0x422];
									int vobID = (buf[0x41f] << 8) + buf[0x420];
									//if (cellID == cell.CellID && vobID == cell.VobID)
									//	inCell = true;
									//else
									//	inCell = false;
									#endregion
									break;
								default:
									break;
							}

							if (m_run == false)
								return;
						}
					}
					SetProgress(m_demuxCount);
				}
				finally
				{
					if (bs != null)
						bs.TRMSFinalize();
					bs = null;
					foreach (string name in writers.Keys)
					{
						FileStream fs = (FileStream)writers[name];
						fs.Close();

						// determine the audio track to use by selecting the first one we encounter,
						// or the one the user selected if there is more than one
						// (if the audio is .mp2, it will already be set and we don't have to worry about the non-digit
						// name at this point)
						if (name.EndsWith(".m2v"))
							video = name;
						else if (audio == null && selectedAudioTrack == 0 && (name.EndsWith(".ac3") || name.EndsWith(".dts") || name.EndsWith(".wav") || name.EndsWith(".mp2"))) // select first audio track we encounter, unless otherwise directed
							audio = name;
						else if (audio == null && selectedAudioTrack == Convert.ToInt32(Path.GetFileNameWithoutExtension(name)))
							audio = name;

						// delete anything after the first audio and video streams in the file
						if (audio != null && name != video && name != audio)
							File.Delete(name);
					}
					writers.Clear();
					foreach (FileStream fs in readers.Values)
					{
						fs.Close();
					}
					readers.Clear();
				}

				int duration = 0;
				if (pgc != null)
					duration = pgc.Duration;
				if (audio == null) // don't process empty audio (will screw things up)
					return;
				audio = ConvertAudio(TempPath + audio, duration);
				if (audio == null)
					return;
				SetProgress(m_audioCount);

				DisableCancel();
				SetStatusText("Remuxing elementary mpeg streams...");
				FileInfo appPath = new FileInfo(Application.ExecutablePath);
				string mplexCommand = appPath.Directory + "\\mplex.exe";
				if (File.Exists(mplexCommand) == false)
					return;

				process = new Process();
				process.StartInfo.UseShellExecute = false;
				process.StartInfo.WorkingDirectory = Environment.CurrentDirectory;
				//process.StartInfo.RedirectStandardOutput = true;
				process.StartInfo.RedirectStandardError = true;
				process.StartInfo.FileName = mplexCommand;
				int AVOffset = Offset(cells, vobs);
				// format = MPEG2 (-f 3)
				// -V = VBR
				// -v 2 = verbose output
				// -O x = A/V offset
				// -S 0 = disable segment splitting
				// -o <file> = output to final output
				process.StartInfo.Arguments = String.Format("-f 3 -V -v 2 -O {0} -S 0 -o \"{1}\" \"{2}\" \"{3}\"",
					AVOffset,
					saveFile,
					TempPath + video,
					audio);
				process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
				process.StartInfo.CreateNoWindow = true;
				process.Start();
				string line;
				string muxBitrate = String.Empty;
				string muxStatus = String.Empty;
				int streams = 0;
				int overflowCount = 0;
				long lastSCR = 0;
				StreamReader sr = process.StandardError;
				DateTime lastMessage = DateTime.MinValue;
				while ((line = sr.ReadLine()) != null)
				{
					line = Regex.Replace(line, @"^[^\[]*\[[^\]]*\]\s+", ""); // get rid of process name at start of string
					if (m_run == false)
						return;
					else if(line.Contains("SCR="))
					{
						if (DateTime.Now < lastMessage.AddMilliseconds(50))
							continue;
						try
						{
							Match m = Regex.Match(line, @"\w\d:\s+SCR=(-?\d+)");
							if (m.Success)
							{
								// workaround for printf in windows truncating 64-bit SCR data
								long scr = Convert.ToInt64(m.Groups[1].Value);
								if(scr < lastSCR)
									overflowCount++;
								lastSCR = scr;
								scr += overflowCount * UInt32.MaxValue;

								// divide it by the CLOCK value to get number of seconds
								scr /= m_mplexMpegClock;

								if (pgc == null)
								{
									SetStatusText("Remuxing elementary mpeg streams...");
								}
								else
								{
									SetStatusText("Remuxing elementary mpeg streams..." + Convert.ToInt32(100.0 * (Convert.ToDouble(scr) / Convert.ToDouble(pgc.Duration))) + "%");
									SetProgress(m_audioCount + Convert.ToInt32((m_remuxCount - m_audioCount) * (Convert.ToDouble(scr) / Convert.ToDouble(pgc.Duration))));
								}
								lastMessage = DateTime.Now;
							}
						}
						catch { }
					}
					else if (line == "New sequence commences...")
						streams++;
					else if (line.StartsWith("MUX STATUS: "))
					{
						line = line.Replace("MUX STATUS: ", "");
						muxStatus = line;
					}
					else if (line.StartsWith("Average bit-rate"))
					{
						muxBitrate = line;
					}
				}
				process.WaitForExit();
				process = null;

				SetProgress(m_remuxCount);
				if (String.IsNullOrEmpty(muxBitrate) == false)
				{
					SetStatusText(muxBitrate);
					Thread.Sleep(500);
				}
				if(AVOffset != 0)
				{
					if(String.IsNullOrEmpty(muxStatus))
						muxStatus = "";
					else 
						muxStatus += " ";
					muxStatus += "used " + AVOffset + "ms AV offset";
				}
				if (String.IsNullOrEmpty(muxStatus) == false)
				{
					SetStatusText(muxStatus);
					Thread.Sleep(500);
				}
			}
			catch (ThreadAbortException)
			{
				try
				{
					if (process != null && process.HasExited == false)
						process.Kill();
				}
				catch { }
			}
			catch (Exception ex)
			{
				MessageBox.Show("Error: " + ex.Message);
			}
			finally
			{
				if (process != null && process.HasExited == false)
					process.Kill();
				EnableForm();
				thread = null;
				SetProgress(0);
				//SetStatusText("");
				SetETAText("");
				SetStatusText("");

				try
				{
					Directory.Delete(TempPath, true);
				}
				catch { }
			}
		}
Пример #3
0
		private void LoadTitles()
		{
			try
			{
				treeView1.Nodes.Clear();
				button3.Enabled = false;
				button4.Enabled = false;
				button5.Enabled = false;
				string path = "";
				if (tabControl1.SelectedIndex == 0)
				{
					string drive = comboBox1.Items[comboBox1.SelectedIndex].ToString();
					path = drive + "VIDEO_TS";
				}
				else
					path = textBox1.Text;
				if (!Directory.Exists(path))
					return;

				//int index = 0;
				int maxLength = 0;
				TreeNode longestNode = null;
				int ifoIdx = 1;
				while (true)
				{
					FileInfo fi = new FileInfo(path + Path.DirectorySeparatorChar + "VTS_" + ifoIdx.ToString("00") + "_0.IFO");
					if (fi.Exists == false)
						break;
					ifoIdx++;
					string name = fi.Name.ToUpper();
					//if (name == "VIDEO_TS.IFO")
					//	continue;
					try
					{
						int title = Convert.ToInt32(name.Replace("VTS_", "").Replace("_0.IFO", ""));
						IFOParse ifo = new IFOParse(fi.FullName);

						// add to tree view
						TreeNode titleNode = new TreeNode();
						string audioTracks = "No audio";
						if (ifo.AudioFormat.Count == 1)
							audioTracks = ifo.AudioFormat[0].ToString();
						else if(ifo.AudioFormat.Count > 1)
							audioTracks = "Multiple audio streams";
						titleNode.Text = "Title " + title + ": " + ifo.VideoMode + " video, " + audioTracks;
						titleNode.Tag = ifo;
						titleNode.Nodes.Clear();
						titleNode.ToolTipText = ifo.ProgramChainCount + " programs";
						for (int pgcNum = 0; pgcNum < ifo.ProgramChainCount; pgcNum++)
						{
							IFOParse.ProgramChain pgc = ifo.ProgramChains[pgcNum];
							TreeNode n = new TreeNode();
							n.Text = "PGC " + (pgcNum + 1) + ": " + Utilities.SecondsToLength(pgc.Duration);
							n.ToolTipText = pgc.Cells.Count + " cells";
							n.Tag = pgc;
							titleNode.Nodes.Add(n);
							if (pgc.Duration > maxLength)
							{
								longestNode = n;
								maxLength = pgc.Duration;
							}
						}
						treeView1.Nodes.Add(titleNode);
					}
					catch (Exception ex)
					{
						MessageBox.Show(ex.Message);
					}
				}
				if (treeView1.Nodes.Count == 0)
				{
					// found no IFO files, load raw VOB list
					foreach (string file in Directory.GetFiles(path, "*.VOB"))
					{
						FileInfo fi = new FileInfo(file);
						string name = fi.Name.ToUpper();

						TreeNode titleNode = new TreeNode();

						List<IFOParse.VOB> vobs = new List<IFOParse.VOB>();
						IFOParse.VOB v = new IFOParse.VOB(file);
						vobs = new List<IFOParse.VOB>();
						vobs.Add(v);

						// create dummy cell list
						List<IFOParse.Cell> cells = new List<IFOParse.Cell>();
						IFOParse.Cell c = new IFOParse.Cell();
						c.FirstSector = 0;
						c.LastSector = (int)v.LastSector;
						cells.Add(c);

						titleNode.Text = name + ": " + Utilities.BytesToSize(fi.Length);
						titleNode.Tag = fi;
						treeView1.Nodes.Add(titleNode);
					}
				}
				if (longestNode != null)
					treeView1.SelectedNode = longestNode;
				treeView1.ExpandAll();
			}
			catch (Exception ex)
			{
				MessageBox.Show("An error occurred reading DVD, it may be corrupt or a failed burn.\n\n" + ex.Message);
			}
		}