}
printf("");
printf("");
- if(argc_ < 3){
+ if(argc_ < 2){
printf("usage: tsremux input-file output-path [-a] [+b] [+m] [+c]\n");
printf(" -a: do not use async io (default on)\n");
printf(" +b: bypass audio alignment (default off)\n");
return 0;
}
- exec_condition_.input_file_text_ = argv_[1];
+ exec_condition_.input_file_text_ = pByte(&argv_[0]);
exec_condition_.use_async_io_ = false;
exec_condition_.bypass_audio_processing_ = false;
exec_condition_.mip_to_ac3_ = false;
}
}
- exec_condition_.output_file_text_ = argv_[2];
+ exec_condition_.output_file_text_ = pByte(&argv_[1]);
char* output_extension;
- for(int i = strlen(exec_condition_.output_file_text_)-1; i >= 0; i--) {
+ for(int i = strlen(exec_condition_.output_file_text_.get())-1; i >= 0; i--) {
if(!strncmp(&exec_condition_.output_file_text_[i], ".", 1)) {
strncpy(output_extension,
&exec_condition_.output_file_text_[i],
printf("unrecognized output type\n");
}
- say(argv_[2]);
+ say(&argv_[2]);
return 0;
}
return;
}
+
+
+
+
+ /*
+ * Copyright (c) 2007, 2008 dmz
+ *
+ * This file is part of TsRemux.
+ *
+ * TsRemux is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * TsRemux is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with TsRemux. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * MODIFIED 04/14/2008 by spacecat56:
+ * Use a folder browser dialog for blu-ray output; interlock with user changes to selected output type.
+ * Not allow repeated remux without re-opening the file (some side effect causes 10x slowing on repeated remux).
+ * Show 4 places of version.
+ * Minor refactoring and added methods to support command-line execution.
+ */
+
+ using System;
+ using System.Collections.Generic;
+ using System.ComponentModel;
+ using System.Data;
+ using System.Drawing;
+ using System.Text;
+ using System.Windows.Forms;
+ using System.IO;
+ using System.Reflection;
+
+ namespace TsRemux
+ {
+ public enum SaveState
+ {
+ Remux,
+ DemuxSup,
+ DemuxStream,
+ DemuxPes
+ }
+
+ public partial class TsRemux : Form
+ {
+ private PesFile inFile;
+ TimeSpan length;
+ List<ushort> pidList;
+ List<ushort> pidsToKeep;
+ SaveState state;
+ string elmName;
+ ushort elmPid;
+ bool supPresent;
+ PesFile supFile;
+ DateTime whenStarted = new DateTime();
+
+ [System.Runtime.InteropServices.DllImport("kernel32.dll")]
+ static extern bool AttachConsole(int dwProcessId);
+ private const int ATTACH_PARENT_PROCESS = -1;
+ string[] args;
+ frmConsole con = null;
+ bool keepConOpen = false;
+
+ public TsRemux()
+ {
+ init();
+ }
+
+ public TsRemux(string[] args)
+ {
+ this.args = args;
+ this.Visible = false;
+ init();
+
+ try
+ {
+ // only works with XP
+ AttachConsole(ATTACH_PARENT_PROCESS);
+ }
+ catch (Exception)
+ {
+ // use our own form
+ con = new frmConsole();
+ Console.SetOut(con.ConWriter);
+ con.Show();
+ }
+ }
+
+ public Form exec()
+ {
+ }
+
+ private void say(string txt)
+ {
+ System.Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd.HH:mm:ss.fff ") + txt);
+ }
+
+ private void init()
+ {
+ InitializeComponent();
+ inFile = null;
+ length = new TimeSpan();
+ pidList = new List<ushort>();
+ pidsToKeep = new List<ushort>();
+ OutputFileBrowseButton.Enabled = false;
+ RemuxButton.Enabled = false;
+ OpenOutputFileDialog.OverwritePrompt = false;
+ DisableNumerics();
+ RemuxButton.Text = "Remux";
+ AssemblyName an = Assembly.GetExecutingAssembly().GetName();
+ this.Text = an.Name + " v." + an.Version.ToString(4);
+ state = SaveState.Remux;
+ elmName = string.Empty;
+ elmPid = 0;
+ supPresent = false;
+ supFile = null;
+ }
+
+ private void DisableNumerics()
+ {
+ TrimEndNumericHours.Enabled = false;
+ TrimEndNumericMinutes.Enabled = false;
+ TrimEndNumericSeconds.Enabled = false;
+ TrimStartNumericHours.Enabled = false;
+ TrimStartNumericMinutes.Enabled = false;
+ TrimStartNumericSeconds.Enabled = false;
+ ChapterLengthUpDown.Enabled = false;
+ DisableSup();
+ }
+
+ private void DisableSup()
+ {
+ SupOffsetNumericHours.Enabled = false;
+ SupOffsetNumericMinutes.Enabled = false;
+ SupOffsetNumericSeconds.Enabled = false;
+ }
+
+ private void EnableSup()
+ {
+ SupOffsetNumericHours.Enabled = true;
+ SupOffsetNumericMinutes.Enabled = true;
+ SupOffsetNumericSeconds.Enabled = true;
+ }
+
+ private void EnableNumerics()
+ {
+ TrimEndNumericHours.Enabled = true;
+ TrimEndNumericMinutes.Enabled = true;
+ TrimEndNumericSeconds.Enabled = true;
+ TrimStartNumericHours.Enabled = true;
+ TrimStartNumericMinutes.Enabled = true;
+ TrimStartNumericSeconds.Enabled = true;
+ if (supPresent)
+ EnableSup();
+ if (BluRayFormatRadioButton.Checked)
+ ChapterLengthUpDown.Enabled = true;
+ }
+
+ private void OpenFile(string filename)
+ {
+ if (null != inFile)
+ {
+ inFile.CloseFile();
+ inFile = null;
+ }
+ if (null != supFile)
+ {
+ supFile.CloseFile();
+ supFile = null;
+ }
+ inFile = PesFile.OpenFile(filename, cbxUseAsyncIO.Checked, backgroundWorker2);
+ }
+
+ private void OpenInputFileDialog_FileOk(object sender, CancelEventArgs e)
+ {
+ AsyncOpenFile(OpenInputFileDialog.FileName);
+ }
+
+ private void AsyncOpenFile(string filename)
+ {
+ RemuxProgressBar.Maximum = 100;
+ RemoveSup();
+ OutputFileBrowseButton.Enabled = false;
+ RemuxButton.Text = "Cancel";
+ RemuxButton.Enabled = true;
+ Quit.Enabled = false;
+ cbxUseAsyncIO.Enabled = false;
+ cbxBypassAudioProcessing.Enabled = false;
+ cbxMlpToAc3.Enabled = false;
+ DisableNumerics();
+ TrimEnd = new TimeSpan(0);
+ TrimStart = new TimeSpan(0);
+ ElementaryStreamsListBox.Items.Clear();
+ ElementaryStreamsListBox.Enabled = false;
+ InputFileTextBox.Text = String.Empty;
+ DtcpInfo.Nodes.Clear();
+ DtcpInfo.Nodes.Add("DTCP Info");
+ DtcpInfo.Nodes[0].Nodes.Add("DTCP Descriptor not present");
+ TsFormatRadioButton.Enabled = false;
+ TsFormatRadioButton.Checked = false;
+ M2tsFormatRadioButton.Enabled = false;
+ M2tsFormatRadioButton.Checked = false;
+ BluRayFormatRadioButton.Enabled = false;
+ BluRayFormatRadioButton.Checked = false;
+ length = new TimeSpan();
+ pidList = new List<ushort>();
+ pidsToKeep = new List<ushort>();
+ this.Cursor = Cursors.WaitCursor;
+ backgroundWorker2.RunWorkerAsync(filename);
+ }
+
+ private void InputFileBrowseButton_Click(object sender, EventArgs e)
+ {
+ OpenInputFileDialog.FileName = InputFileTextBox.Text;
+ OpenInputFileDialog.ShowDialog();
+ }
+
+ private void OpenOutputFileDialog_FileOk(object sender, CancelEventArgs e)
+ {
+ if (string.CompareOrdinal(InputFileTextBox.Text, OpenOutputFileDialog.FileName) == 0)
+ {
+ OutputFileTextBox.Text = String.Empty;
+ MessageBox.Show("Cannot open the same file as a source and an output file");
+ }
+ else
+ {
+ OutputFileTextBox.Text = OpenOutputFileDialog.FileName;
+ RemuxButton.Enabled = true;
+ }
+ }
+
+ private void OutputFileBrowseButton_Click(object sender, EventArgs e)
+ {
+ if (BluRayFormatRadioButton.Checked)
+ {
+ if (OutputFileTextBox.Text.LastIndexOf("\\") > 0)
+ {
+ SelectOutputFolderDialog.SelectedPath = OutputFileTextBox.Text.Substring(0, OutputFileTextBox.Text.LastIndexOf("\\"));
+ }
+ DialogResult dr = SelectOutputFolderDialog.ShowDialog();
+ if (dr == DialogResult.OK)
+ {
+ OutputFileTextBox.Text = SelectOutputFolderDialog.SelectedPath;
+ RemuxButton.Enabled = true;
+ }
+ }
+ else
+ {
+ OpenOutputFileDialog.FileName = OutputFileTextBox.Text;
+ OpenOutputFileDialog.ShowDialog();
+ }
+
+ }
+
+ private void EnableCbxMlp()
+ {
+ cbxMlpToAc3.Enabled = false;
+ if(inFile.FileType == TsFileType.M2TS || inFile.FileType == TsFileType.TS)
+ {
+ foreach (StreamInfo si in inFile.StreamInfos)
+ if ((pidsToKeep.Contains(si.ElementaryPID) && si.StreamType == ElementaryStreamTypes.AUDIO_STREAM_AC3_TRUE_HD)
+ || (pidsToKeep.Contains(si.ElementaryPID) && si.StreamType == ElementaryStreamTypes.AUDIO_STREAM_DTS_HD)
+ ||(pidsToKeep.Contains(si.ElementaryPID) && si.StreamType == ElementaryStreamTypes.AUDIO_STREAM_DTS_HD_MASTER_AUDIO))
+ cbxMlpToAc3.Enabled = true;
+ }
+ }
+
+ private void ElementaryStreamsListBox_ItemCheck(object sender, ItemCheckEventArgs e)
+ {
+ pidsToKeep.Clear();
+ for (int i = 0; i < ElementaryStreamsListBox.Items.Count; i++)
+ {
+ if (i != e.Index)
+ {
+ if (ElementaryStreamsListBox.CheckedItems.Contains(ElementaryStreamsListBox.Items[i]))
+ {
+ pidsToKeep.Add(pidList[i]);
+ }
+ }
+ else if (e.NewValue == CheckState.Checked)
+ pidsToKeep.Add(pidList[i]);
+ }
+ EnableCbxMlp();
+ }
+
+ private void Quit_Click(object sender, EventArgs e)
+ {
+ Close();
+ }
+
+ private void RemuxButton_Click(object sender, EventArgs e)
+ {
+ if (backgroundWorker1.IsBusy == false && backgroundWorker2.IsBusy == false)
+ {
+ RemuxButton.Text = "Cancel";
+ InputFileBrowseButton.Enabled = false;
+ OutputFileBrowseButton.Enabled = false;
+ InputFileTextBox.Enabled = false;
+ OutputFileTextBox.Enabled = false;
+ this.Cursor = Cursors.WaitCursor;
+ RemuxProgressTimeTextBox.Text = length.Subtract(TrimEnd).ToString();
+ RemuxProgressBar.Value = RemuxProgressBar.Minimum;
+ RemuxProgressBar.Maximum = (int)length.Subtract(TrimEnd).TotalMinutes;
+ FormatBox.Enabled = false;
+ TsFormatRadioButton.Enabled = false;
+ M2tsFormatRadioButton.Enabled = false;
+ BluRayFormatRadioButton.Enabled = false;
+ Quit.Enabled = false;
+ cbxUseAsyncIO.Enabled = false;
+ cbxBypassAudioProcessing.Enabled = false;
+ cbxMlpToAc3.Enabled = false;
+ ElementaryStreamsListBox.Enabled = false;
+ DisableNumerics();
+ whenStarted = DateTime.Now;
+ backgroundWorker1.RunWorkerAsync();
+ }
+ else if (backgroundWorker1.IsBusy)
+ {
+ RemuxButton.Enabled = false;
+ backgroundWorker1.CancelAsync();
+ }
+ else if (backgroundWorker2.IsBusy)
+ {
+ RemuxButton.Enabled = false;
+ backgroundWorker2.CancelAsync();
+ }
+ }
+
+ private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
+ {
+ Coordinator cor = new Coordinator();
+ switch (state)
+ {
+ case SaveState.Remux:
+ if (TsFormatRadioButton.Checked)
+ {
+ cor.StartMuxing(OutputFileTextBox.Text, backgroundWorker1, TsFileType.TS, pidsToKeep, TrimStart, TrimEnd, cbxUseAsyncIO.Checked, cbxBypassAudioProcessing.Checked, cbxMlpToAc3.Checked, inFile, supFile, SupStart, ChapterLen);
+ }
+ else if (M2tsFormatRadioButton.Checked)
+ {
+ cor.StartMuxing(OutputFileTextBox.Text, backgroundWorker1, TsFileType.M2TS, pidsToKeep, TrimStart, TrimEnd, cbxUseAsyncIO.Checked, cbxBypassAudioProcessing.Checked, cbxMlpToAc3.Checked, inFile, supFile, SupStart, ChapterLen);
+ }
+ else if (BluRayFormatRadioButton.Checked)
+ {
+ cor.StartMuxing(OutputFileTextBox.Text, backgroundWorker1, TsFileType.BLU_RAY, pidsToKeep, TrimStart, TrimEnd, cbxUseAsyncIO.Checked, cbxBypassAudioProcessing.Checked, cbxMlpToAc3.Checked, inFile, supFile, SupStart, ChapterLen);
+ }
+ break;
+ case SaveState.DemuxSup:
+ if (elmPid != 0)
+ {
+ List<ushort> elmPids = new List<ushort>();
+ elmPids.Add(elmPid);
+ cor.StartMuxing(elmName, backgroundWorker1, TsFileType.SUP_ELEMENTARY, elmPids, TrimStart, TrimEnd, cbxUseAsyncIO.Checked, inFile);
+ }
+ break;
+ case SaveState.DemuxStream:
+ if (elmPid != 0)
+ {
+ List<ushort> elmPids = new List<ushort>();
+ elmPids.Add(elmPid);
+ cor.StartMuxing(elmName, backgroundWorker1, TsFileType.ELEMENTARY, elmPids, TrimStart, TrimEnd, cbxUseAsyncIO.Checked, inFile);
+ }
+ break;
+ case SaveState.DemuxPes:
+ if (elmPid != 0)
+ {
+ List<ushort> elmPids = new List<ushort>();
+ elmPids.Add(elmPid);
+ cor.StartMuxing(elmName, backgroundWorker1, TsFileType.PES_ELEMENTARY, elmPids, TrimStart, TrimEnd, cbxUseAsyncIO.Checked, inFile);
+ }
+ break;
+ }
+ }
+
+ private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
+ {
+ TimeSpan ts = (TimeSpan)e.UserState;
+ TimeSpan nts = length - TrimEnd - ts;
+ RemuxProgressTimeTextBox.Text = String.Format("{0:00}:{1:00}:{2:00}", ts.Hours, ts.Minutes, ts.Seconds);
+ int newValue = (int)nts.TotalMinutes;
+ if (newValue != RemuxProgressBar.Value && newValue > 0)
+ RemuxProgressBar.Value = newValue;
+ }
+
+ private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+ {
+ if (whenStarted.Ticks > 0)
+ {
+ TimeSpan ts = DateTime.Now.Subtract(whenStarted);
+ this.RemuxProgressTimeTextBox.Text = "elapsed: " + ts.TotalSeconds.ToString("#.00") + " sec.";
+ }
+ RemuxButton.Text = "Remux";
+ InputFileBrowseButton.Enabled = true;
+ OutputFileBrowseButton.Enabled = true;
+ InputFileTextBox.Enabled = true;
+ OutputFileTextBox.Enabled = true;
+ FormatBox.Enabled = true;
+ TsFormatRadioButton.Enabled = true;
+ cbxUseAsyncIO.Enabled = true;
+ cbxBypassAudioProcessing.Enabled = true;
+ EnableCbxMlp();
+ if (length > TimeSpan.Zero)
+ {
+ M2tsFormatRadioButton.Enabled = true;
+ BluRayFormatRadioButton.Enabled = true;
+ }
+ Quit.Enabled = true;
+ ElementaryStreamsListBox.Enabled = true;
+ if (length > TimeSpan.Zero)
+ EnableNumerics();
+ this.Cursor = Cursors.Default;
+ state = SaveState.Remux;
+ elmName = String.Empty;
+ elmPid = 0;
+ /***********
+ * some artifact of the remux process causes extreme performance degradation, IF
+ * you just re-remux the same file over again. re-opening the input seems to
+ * clear this condition. So here we force user to do that in order to re-remux
+ */
+ if (InputFileTextBox.Text.Length > 0 && OutputFileTextBox.Text.Length > 0)
+ RemuxButton.Enabled = true;
+ else
+ RemuxButton.Enabled = false;
+ // * *********/
+ //RemuxButton.Enabled = false;
+ if (e.Error != null)
+ MessageBox.Show(e.Error.Message + "\n" + e.Error.StackTrace);
+ }
+
+ private void RemuxButton_MouseEnter(object sender, EventArgs e)
+ {
+ if ((backgroundWorker1.IsBusy && backgroundWorker1.CancellationPending == false) ||
+ (backgroundWorker2.IsBusy && backgroundWorker1.CancellationPending == false))
+ this.Cursor = Cursors.Default;
+ }
+
+ private void RemuxButton_MouseLeave(object sender, EventArgs e)
+ {
+ if (backgroundWorker1.IsBusy || backgroundWorker2.IsBusy)
+ this.Cursor = Cursors.WaitCursor;
+ }
+
+ private void TsRemux_DragDrop(object sender, DragEventArgs e)
+ {
+ string[] formats = e.Data.GetFormats(false);
+ if (e.Data.GetDataPresent(DataFormats.FileDrop))
+ {
+ string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
+ AsyncOpenFile(files[0]);
+ }
+ }
+
+ private void TsRemux_DragEnter(object sender, DragEventArgs e)
+ {
+ if (e.Data.GetDataPresent(DataFormats.FileDrop))
+ e.Effect = DragDropEffects.Copy;
+ }
+
+ private void TrimStartNumericHours_ValueChanged(object sender, EventArgs e)
+ {
+ CheckTrimStart();
+ }
+
+ private void TrimStartNumericMinutes_ValueChanged(object sender, EventArgs e)
+ {
+ if (TrimStartNumericMinutes.Value == 60)
+ {
+ if (TrimStartNumericHours.Value < TrimStartNumericHours.Maximum)
+ {
+ TrimStartNumericMinutes.Value = 0;
+ TrimStartNumericHours.Value += 1;
+ }
+ else
+ TrimStartNumericMinutes.Value = 59;
+ }
+ else if (TrimStartNumericMinutes.Value == -1)
+ {
+ if (TrimStartNumericHours.Value > 0)
+ {
+ TrimStartNumericMinutes.Value = 59;
+ TrimStartNumericHours.Value -= 1;
+ }
+ else
+ TrimStartNumericMinutes.Value = 0;
+ }
+ CheckTrimStart();
+ }
+
+ private void TrimStartNumericSeconds_ValueChanged(object sender, EventArgs e)
+ {
+ if (TrimStartNumericSeconds.Value == 60)
+ {
+ if (TrimStartNumericHours.Value == TrimStartNumericHours.Maximum && TrimStartNumericMinutes.Value == 59)
+ {
+ TrimStartNumericSeconds.Value = 59;
+ }
+ else
+ {
+ TrimStartNumericSeconds.Value = 0;
+ TrimStartNumericMinutes.Value += 1;
+ }
+ }
+ else if (TrimStartNumericSeconds.Value == -1)
+ {
+ if (TrimStartNumericMinutes.Value > 0 || TrimStartNumericHours.Value > 0)
+ {
+ TrimStartNumericSeconds.Value = 59;
+ TrimStartNumericMinutes.Value -= 1;
+ }
+ else
+ TrimStartNumericSeconds.Value = 0;
+ }
+ CheckTrimStart();
+ }
+
+ private void TrimEndNumericHours_ValueChanged(object sender, EventArgs e)
+ {
+ CheckTrimEnd();
+ }
+
+ private void TrimEndNumericMinutes_ValueChanged(object sender, EventArgs e)
+ {
+ if (TrimEndNumericMinutes.Value == 60)
+ {
+ if (TrimEndNumericHours.Value < TrimEndNumericHours.Maximum)
+ {
+ TrimEndNumericMinutes.Value = 0;
+ TrimEndNumericHours.Value += 1;
+ }
+ else
+ TrimEndNumericMinutes.Value = 59;
+ }
+ else if (TrimEndNumericMinutes.Value == -1)
+ {
+ if (TrimEndNumericHours.Value > 0)
+ {
+ TrimEndNumericMinutes.Value = 59;
+ TrimEndNumericHours.Value -= 1;
+ }
+ else
+ TrimEndNumericMinutes.Value = 0;
+ }
+ CheckTrimEnd();
+ }
+
+ private void TrimEndNumericSeconds_ValueChanged(object sender, EventArgs e)
+ {
+ if (TrimEndNumericSeconds.Value == 60)
+ {
+ if (TrimEndNumericHours.Value == TrimEndNumericHours.Maximum && TrimEndNumericMinutes.Value == 59)
+ {
+ TrimEndNumericSeconds.Value = 59;
+ }
+ else
+ {
+ TrimEndNumericSeconds.Value = 0;
+ TrimEndNumericMinutes.Value += 1;
+ }
+ }
+ else if (TrimEndNumericSeconds.Value == -1)
+ {
+ if (TrimEndNumericMinutes.Value > 0 || TrimEndNumericHours.Value > 0)
+ {
+ TrimEndNumericSeconds.Value = 59;
+ TrimEndNumericMinutes.Value -= 1;
+ }
+ else
+ TrimEndNumericSeconds.Value = 0;
+ }
+ CheckTrimEnd();
+ }
+
+ private void CheckTrimStart()
+ {
+ TimeSpan total = TrimStart.Add(TrimEnd);
+ if (total.CompareTo(length) >= 0)
+ {
+ TimeSpan newEnd = length.Subtract(TrimStart);
+ if (newEnd.TotalSeconds <= 0)
+ {
+ TrimStart = new TimeSpan(length.Hours, length.Minutes, length.Seconds);
+ TrimEnd = new TimeSpan(0, 0, 0);
+ }
+ else
+ TrimEnd = new TimeSpan(newEnd.Hours, newEnd.Minutes, newEnd.Seconds);
+ }
+ CheckSupStart();
+ CheckChapterLen();
+ }
+
+ private void CheckSupStart()
+ {
+ TimeSpan total = TrimStart.Add(TrimEnd);
+ total = length.Subtract(total);
+ if (SupStart.CompareTo(total) >= 0)
+ {
+ SupStart = total;
+ }
+ }
+
+ private void CheckChapterLen()
+ {
+ TimeSpan total = TrimStart.Add(TrimEnd);
+ total = length.Subtract(total);
+ if (ChapterLen.CompareTo(total) >= 0)
+ {
+ ChapterLen = total;
+ }
+ }
+
+ private void CheckTrimEnd()
+ {
+ TimeSpan total = TrimEnd.Add(TrimStart);
+ if (total.CompareTo(length) >= 0)
+ {
+ TimeSpan newStart = length.Subtract(TrimEnd);
+ if (newStart.TotalSeconds <= 0)
+ {
+ TrimEnd = new TimeSpan(length.Hours, length.Minutes, length.Seconds);
+ TrimStart = new TimeSpan(0, 0, 0);
+ }
+ else
+ TrimStart = new TimeSpan(newStart.Hours, newStart.Minutes, newStart.Seconds);
+ }
+ CheckSupStart();
+ CheckChapterLen();
+ }
+
+ private TimeSpan TrimStart
+ {
+ get
+ {
+ return new TimeSpan((int)TrimStartNumericHours.Value, (int)TrimStartNumericMinutes.Value, (int)TrimStartNumericSeconds.Value);
+ }
+ set
+ {
+ TrimStartNumericHours.Value = value.Hours;
+ TrimStartNumericMinutes.Value = value.Minutes;
+ TrimStartNumericSeconds.Value = value.Seconds;
+ }
+ }
+
+ private TimeSpan SupStart
+ {
+ get
+ {
+ return new TimeSpan((int)SupOffsetNumericHours.Value, (int)SupOffsetNumericMinutes.Value, (int)SupOffsetNumericSeconds.Value);
+ }
+ set
+ {
+ SupOffsetNumericHours.Value = value.Hours;
+ SupOffsetNumericMinutes.Value = value.Minutes;
+ SupOffsetNumericSeconds.Value = value.Seconds;
+ }
+ }
+
+ private TimeSpan ChapterLen
+ {
+ get
+ {
+ return new TimeSpan((int)ChapterLengthUpDown.Value / 60, (int)ChapterLengthUpDown.Value % 60, 0);
+ }
+ set
+ {
+ int len = (int)value.TotalMinutes;
+ if (len >= ChapterLengthUpDown.Minimum)
+ ChapterLengthUpDown.Value = len;
+ else
+ ChapterLengthUpDown.Value = ChapterLengthUpDown.Minimum;
+ }
+ }
+
+ private TimeSpan TrimEnd
+ {
+ get
+ {
+ return new TimeSpan((int)TrimEndNumericHours.Value, (int)TrimEndNumericMinutes.Value, (int)TrimEndNumericSeconds.Value);
+ }
+ set
+ {
+ TrimEndNumericHours.Value = value.Hours;
+ TrimEndNumericMinutes.Value = value.Minutes;
+ TrimEndNumericSeconds.Value = value.Seconds;
+ }
+ }
+
+ private bool SupSelected
+ {
+ get
+ {
+ return (ElementaryStreamsListBox.SelectedIndex == ElementaryStreamsListBox.Items.Count - 1) && supPresent;
+ }
+ }
+
+ private void ElementaryContextMenu_Opening(object sender, CancelEventArgs e)
+ {
+ ElementaryContextMenu.Items.Clear();
+ e.Cancel = false;
+ ToolStripLabel tl = null;
+ if (supPresent)
+ tl = new ToolStripLabel("Remove SUPread stream", null, false, RemoveStream_Click);
+ else
+ tl = new ToolStripLabel("Add a new SUPread stream", null, false, AddStream_Click);
+ tl.MouseEnter += new EventHandler(tl_MouseEnter);
+ tl.MouseLeave += new EventHandler(tl_MouseLeave);
+ ElementaryContextMenu.Items.Add(tl);
+ ElementaryContextMenu.Items.Add(new ToolStripSeparator());
+ if (null != ElementaryStreamsListBox.SelectedItem && SupSelected == false)
+ {
+ tl = new ToolStripLabel(String.Format("Demux {0} to elementary stream", ElementaryStreamsListBox.SelectedItem.ToString()), null, false, DemuxElementary_Click);
+ tl.MouseEnter += new EventHandler(tl_MouseEnter);
+ tl.MouseLeave += new EventHandler(tl_MouseLeave);
+ ElementaryContextMenu.Items.Add(tl);
+ tl = new ToolStripLabel(String.Format("Demux {0} to PES stream", ElementaryStreamsListBox.SelectedItem.ToString()), null, false, DemuxPes_Click);
+ tl.MouseEnter += new EventHandler(tl_MouseEnter);
+ tl.MouseLeave += new EventHandler(tl_MouseLeave);
+ ElementaryContextMenu.Items.Add(tl);
+ ushort pid = pidList[ElementaryStreamsListBox.Items.IndexOf(ElementaryStreamsListBox.SelectedItem)];
+ foreach (StreamInfo si in inFile.StreamInfos)
+ {
+ if (si.ElementaryPID == pid)
+ {
+ if (si.StreamType == ElementaryStreamTypes.PRESENTATION_GRAPHICS_STREAM)
+ {
+ tl = new ToolStripLabel(String.Format("Demux {0} to SUPread stream", ElementaryStreamsListBox.SelectedItem.ToString()), null, false, DemuxSup_Click);
+ ElementaryContextMenu.Items.Add(tl);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ void tl_MouseLeave(object sender, EventArgs e)
+ {
+ ((ToolStripLabel)sender).ForeColor = Color.Black;
+ }
+
+ void tl_MouseEnter(object sender, EventArgs e)
+ {
+ ((ToolStripLabel)sender).ForeColor = Color.Aqua;
+ }
+
+ private void AddStream_Click(object sender, EventArgs e)
+ {
+ OpenSupFileDialog.ShowDialog();
+ }
+
+ private void RemoveStream_Click(object sender, EventArgs e)
+ {
+ RemoveSup();
+ }
+
+ private void DemuxElementary_Click(object sender, EventArgs e)
+ {
+ state = SaveState.DemuxStream;
+ SaveElementaryStream.ShowDialog();
+ }
+
+ private void DemuxPes_Click(object sender, EventArgs e)
+ {
+ state = SaveState.DemuxPes;
+ SaveElementaryStream.ShowDialog();
+ }
+
+ private void DemuxSup_Click(object sender, EventArgs e)
+ {
+ state = SaveState.DemuxSup;
+ SaveElementaryStream.ShowDialog();
+ }
+
+ private void SaveElementaryStream_FileOk(object sender, CancelEventArgs e)
+ {
+ if (backgroundWorker1.IsBusy == false)
+ {
+ elmName = SaveElementaryStream.FileName;
+ elmPid = pidList[ElementaryStreamsListBox.Items.IndexOf(ElementaryStreamsListBox.SelectedItem)];
+ RemuxButton.Text = "Cancel";
+ RemuxButton.Enabled = true;
+ InputFileBrowseButton.Enabled = false;
+ OutputFileBrowseButton.Enabled = false;
+ InputFileTextBox.Enabled = false;
+ OutputFileTextBox.Enabled = false;
+ this.Cursor = Cursors.WaitCursor;
+ RemuxProgressTimeTextBox.Text = length.Subtract(TrimEnd).ToString();
+ RemuxProgressBar.Value = RemuxProgressBar.Minimum;
+ RemuxProgressBar.Maximum = (int)length.Subtract(TrimEnd).TotalMinutes;
+ FormatBox.Enabled = false;
+ TsFormatRadioButton.Enabled = false;
+ M2tsFormatRadioButton.Enabled = false;
+ BluRayFormatRadioButton.Enabled = false;
+ Quit.Enabled = false;
+ ElementaryStreamsListBox.Enabled = false;
+ DisableNumerics();
+ backgroundWorker1.RunWorkerAsync();
+ }
+ }
+
+ private void RemoveSup()
+ {
+ if (supPresent)
+ {
+ pidList.RemoveAt(pidList.Count - 1);
+ ElementaryStreamsListBox.Items.RemoveAt(ElementaryStreamsListBox.Items.Count - 1);
+ pidsToKeep.Remove(supFile.StreamInfos[0].ElementaryPID);
+ supPresent = false;
+ supFile.CloseFile();
+ supFile = null;
+ }
+ SupStart = TimeSpan.Zero;
+ DisableSup();
+ }
+
+ private void OpenSupFileDialog_FileOk(object sender, CancelEventArgs e)
+ {
+ RemoveSup();
+
+ supFile = PesFile.OpenFile(OpenSupFileDialog.FileName, cbxUseAsyncIO.Checked, backgroundWorker2);
+ if (supFile.FileType != TsFileType.SUP_ELEMENTARY)
+ {
+ MessageBox.Show(String.Format("File \"{0}\" is not a valid SUP file.", OpenSupFileDialog.FileName));
+ return;
+ }
+
+ ushort pid = Constants.DEFAULT_PRESENTATION_GRAPHICS_PID;
+ while (PidExists(pid))
+ pid++;
+ supFile.StreamInfos[0].ElementaryPID = pid;
+ pidList.Add(pid);
+ ElementaryStreamsListBox.Items.Add(String.Format("Presentation Graphics Stream # {0}", supFile.StreamInfos[0].ElementaryPID & 0xf));
+ ElementaryStreamsListBox.SetItemChecked(ElementaryStreamsListBox.Items.Count - 1, true);
+ EnableSup();
+ supPresent = true;
+ }
+
+ private bool PidExists(ushort pid)
+ {
+ foreach (StreamInfo si in inFile.StreamInfos)
+ if (si.ElementaryPID == pid)
+ return true;
+ return false;
+ }
+
+ private void SupOffsetNumericSeconds_ValueChanged(object sender, EventArgs e)
+ {
+ if (SupOffsetNumericSeconds.Value == 60)
+ {
+ if (SupOffsetNumericHours.Value == SupOffsetNumericHours.Maximum && SupOffsetNumericMinutes.Value == 59)
+ {
+ SupOffsetNumericSeconds.Value = 59;
+ }
+ else
+ {
+ SupOffsetNumericSeconds.Value = 0;
+ SupOffsetNumericMinutes.Value += 1;
+ }
+ }
+ else if (SupOffsetNumericSeconds.Value == -1)
+ {
+ if (SupOffsetNumericMinutes.Value > 0 || SupOffsetNumericHours.Value > 0)
+ {
+ SupOffsetNumericSeconds.Value = 59;
+ SupOffsetNumericMinutes.Value -= 1;
+ }
+ else
+ SupOffsetNumericSeconds.Value = 0;
+ }
+ CheckSupStart();
+ CheckChapterLen();
+ }
+
+ private void SupOffsetNumericMinutes_ValueChanged(object sender, EventArgs e)
+ {
+ if (SupOffsetNumericMinutes.Value == 60)
+ {
+ if (SupOffsetNumericHours.Value < SupOffsetNumericHours.Maximum)
+ {
+ SupOffsetNumericMinutes.Value = 0;
+ SupOffsetNumericHours.Value += 1;
+ }
+ else
+ SupOffsetNumericMinutes.Value = 59;
+ }
+ else if (SupOffsetNumericMinutes.Value == -1)
+ {
+ if (SupOffsetNumericHours.Value > 0)
+ {
+ SupOffsetNumericMinutes.Value = 59;
+ SupOffsetNumericHours.Value -= 1;
+ }
+ else
+ SupOffsetNumericMinutes.Value = 0;
+ }
+ CheckSupStart();
+ CheckChapterLen();
+ }
+
+ private void SupOffsetNumericHours_ValueChanged(object sender, EventArgs e)
+ {
+ CheckSupStart();
+ }
+
+ private void ChapterLengthUpDown_ValueChanged(object sender, EventArgs e)
+ {
+ CheckChapterLen();
+ }
+
+ private void BluRayFormatRadioButton_CheckedChanged(object sender, EventArgs e)
+ {
+ if (BluRayFormatRadioButton.Checked)
+ {
+ ChapterLengthUpDown.Enabled = true;
+ if (inFile.FileType == TsFileType.M2TS)
+ cbxBypassAudioProcessing.Checked = true;
+ else
+ cbxBypassAudioProcessing.Checked = false;
+ if (!this.RemuxButton.Enabled)
+ {
+ if (this.OutputFileTextBox.Text.LastIndexOf(".") < this.OutputFileTextBox.Text.LastIndexOf("\\"))
+ this.RemuxButton.Enabled = true;
+ }
+ else
+ {
+ if (this.OutputFileTextBox.Text.LastIndexOf(".") >= this.OutputFileTextBox.Text.LastIndexOf("\\"))
+ this.RemuxButton.Enabled = false;
+ }
+ }
+ else
+ {
+ ChapterLengthUpDown.Enabled = false;
+ // don't allow folder for other options
+ if (this.RemuxButton.Enabled)
+ {
+ if (this.OutputFileTextBox.Text.LastIndexOf(".") < this.OutputFileTextBox.Text.LastIndexOf("\\"))
+ this.RemuxButton.Enabled = false;
+ }
+ else
+ {
+ if (this.OutputFileTextBox.Text.LastIndexOf(".") >= this.OutputFileTextBox.Text.LastIndexOf("\\"))
+ this.RemuxButton.Enabled = true;
+ }
+ }
+ }
+
+ private void TsFormatRadioButton_CheckedChanged(object sender, EventArgs e)
+ {
+ if (TsFormatRadioButton.Checked)
+ cbxBypassAudioProcessing.Checked = true;
+ }
+
+ private void M2tsFormatRadioButton_CheckedChanged(object sender, EventArgs e)
+ {
+ if (M2tsFormatRadioButton.Checked)
+ cbxBypassAudioProcessing.Checked = true;
+ }
+
+ private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e)
+ {
+ try
+ {
+ OpenFile((string)e.Argument);
+ }
+ catch (Exception ex)
+ {
+ e.Result = ex;
+ }
+ e.Result = e.Argument;
+ }
+
+ private void backgroundWorker2_ProgressChanged(object sender, ProgressChangedEventArgs e)
+ {
+ RemuxProgressBar.Value = e.ProgressPercentage;
+ }
+
+ private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+ {
+ this.Cursor = Cursors.Default;
+ RemuxButton.Text = "Remux";
+ RemuxButton.Enabled = false;
+ Quit.Enabled = true;
+ cbxUseAsyncIO.Enabled = true;
+ cbxBypassAudioProcessing.Enabled = true;
+ if (e.Error != null)
+ {
+ if (e.Error is ApplicationException)
+ return;
+ else
+ MessageBox.Show(e.Error.Message + "\n" + e.Error.StackTrace);
+ return;
+ }
+ if (e.Result != null && e.Result is Exception)
+ {
+ Exception ex = (Exception)e.Result;
+ MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
+ return;
+ }
+ EnableCbxMlp();
+ StreamInfo[] streams = null;
+ streams = inFile.StreamInfos;
+ if (null == streams)
+ {
+ MessageBox.Show("The specified file does not contain a valid PAT/PMT combo.");
+ return;
+ }
+
+ InputFileTextBox.Text = (string)e.Result;
+ foreach (StreamInfo si in streams)
+ {
+ pidList.Add(si.ElementaryPID);
+ switch (si.StreamType)
+ {
+ case ElementaryStreamTypes.VIDEO_STREAM_H264:
+ ElementaryStreamsListBox.Items.Add(String.Format("AVC Video Stream # {0}", si.ElementaryPID & 0xff));
+ break;
+ case ElementaryStreamTypes.VIDEO_STREAM_MPEG2:
+ ElementaryStreamsListBox.Items.Add(String.Format("MPEG2 Video Stream # {0}", si.ElementaryPID & 0xff));
+ break;
+ case ElementaryStreamTypes.VIDEO_STREAM_VC1:
+ ElementaryStreamsListBox.Items.Add(String.Format("VC-1 Video Stream # {0}", si.ElementaryPID & 0xff));
+ break;
+ case ElementaryStreamTypes.AUDIO_STREAM_AC3:
+ ElementaryStreamsListBox.Items.Add(String.Format("Dolby Digital Audio Stream # {0}", si.ElementaryPID & 0xff));
+ break;
+ case ElementaryStreamTypes.AUDIO_STREAM_AC3_PLUS:
+ ElementaryStreamsListBox.Items.Add(String.Format("Dolby Digital Plus Audio Stream # {0}", si.ElementaryPID & 0xff));
+ break;
+ case ElementaryStreamTypes.AUDIO_STREAM_AC3_TRUE_HD:
+ ElementaryStreamsListBox.Items.Add(String.Format("Dolby True HD Audio Stream # {0}", si.ElementaryPID & 0xff));
+ break;
+ case ElementaryStreamTypes.AUDIO_STREAM_DTS:
+ ElementaryStreamsListBox.Items.Add(String.Format("DTS Audio Stream # {0}", si.ElementaryPID & 0xff));
+ break;
+ case ElementaryStreamTypes.AUDIO_STREAM_DTS_HD:
+ ElementaryStreamsListBox.Items.Add(String.Format("DTS-HD Audio Stream # {0}", si.ElementaryPID & 0xff));
+ break;
+ case ElementaryStreamTypes.AUDIO_STREAM_DTS_HD_MASTER_AUDIO:
+ ElementaryStreamsListBox.Items.Add(String.Format("DTS-HD Master Audio Stream # {0}", si.ElementaryPID & 0xff));
+ break;
+ case ElementaryStreamTypes.AUDIO_STREAM_LPCM:
+ ElementaryStreamsListBox.Items.Add(String.Format("Lossless PCM Audio Stream # {0}", si.ElementaryPID & 0xff));
+ break;
+ case ElementaryStreamTypes.AUDIO_STREAM_MPEG1:
+ ElementaryStreamsListBox.Items.Add(String.Format("MPEG1 Audio Stream # {0}", si.ElementaryPID & 0xff));
+ break;
+ case ElementaryStreamTypes.AUDIO_STREAM_MPEG2:
+ ElementaryStreamsListBox.Items.Add(String.Format("MPEG2 Audio Stream # {0}", si.ElementaryPID & 0xff));
+ break;
+ case ElementaryStreamTypes.PRESENTATION_GRAPHICS_STREAM:
+ ElementaryStreamsListBox.Items.Add(String.Format("Presentation Graphics Stream # {0}", si.ElementaryPID & 0xff));
+ break;
+ case ElementaryStreamTypes.INTERACTIVE_GRAPHICS_STREAM:
+ ElementaryStreamsListBox.Items.Add(String.Format("Interactive Graphics Stream # {0}", si.ElementaryPID & 0xff));
+ break;
+ case ElementaryStreamTypes.SUBTITLE_STREAM:
+ ElementaryStreamsListBox.Items.Add(String.Format("Subtitle Stream # {0}", si.ElementaryPID & 0xff));
+ break;
+ default:
+ ElementaryStreamsListBox.Items.Add(String.Format("Unknown Stream of type {0}", si.StreamType));
+ break;
+ }
+ }
+ DTCP_Descriptor ds = inFile.DtcpInfo;
+ if (null != ds)
+ {
+ DtcpInfo.Nodes[0].Nodes.Clear();
+ switch (ds.CopyStatus)
+ {
+ case DtcpCci.CopyFree:
+ DtcpInfo.Nodes[0].Nodes.Add("Copy free");
+ break;
+ case DtcpCci.CopyNever:
+ DtcpInfo.Nodes[0].Nodes.Add("Copy never");
+ break;
+ case DtcpCci.CopyOnce:
+ DtcpInfo.Nodes[0].Nodes.Add("Copy once");
+ break;
+ case DtcpCci.NoMoreCopies:
+ DtcpInfo.Nodes[0].Nodes.Add("No more copies");
+ break;
+ }
+ if (ds.AnalogConstrain)
+ DtcpInfo.Nodes[0].Nodes.Add("HD analog output is constrained");
+ else
+ DtcpInfo.Nodes[0].Nodes.Add("HD analog output is full resolution");
+ if (ds.Macrovision)
+ DtcpInfo.Nodes[0].Nodes.Add("Macrovision is on");
+ else
+ DtcpInfo.Nodes[0].Nodes.Add("Macrovision is off");
+ }
+ length = inFile.VideoLength;
+ DtcpInfo.Nodes.Add("Video Length: " + length);
+ if (length == TimeSpan.Zero)
+ {
+ TreeNode tn = new TreeNode();
+ tn.ForeColor = Color.Red;
+ tn.Text = "Warning: No PCRs available!";
+ DtcpInfo.Nodes.Add(tn);
+ }
+ RemuxProgressBar.Maximum = (int)length.TotalMinutes;
+ RemuxProgressBar.Step = 1;
+ RemuxProgressBar.Value = 0;
+ RemuxProgressTimeTextBox.Text = inFile.VideoLength.ToString();
+ if (inFile.FileType == TsFileType.M2TS)
+ {
+ DtcpInfo.Nodes.Add("File format: M2TS (192 byte packets)");
+ }
+ else if (inFile.FileType == TsFileType.TS)
+ {
+ DtcpInfo.Nodes.Add("File format: TS (188 byte packets)");
+ }
+ OutputFileBrowseButton.Enabled = true;
+ if (string.CompareOrdinal(InputFileTextBox.Text, OutputFileTextBox.Text) == 0)
+ OutputFileTextBox.Text = String.Empty;
+ ElementaryStreamsListBox.Enabled = true;
+ if (inFile.FileType == TsFileType.M2TS)
+ {
+ TsFormatRadioButton.Enabled = true;
+ TsFormatRadioButton.Checked = false;
+ M2tsFormatRadioButton.Enabled = true;
+ M2tsFormatRadioButton.Checked = true;
+ BluRayFormatRadioButton.Checked = false;
+ BluRayFormatRadioButton.Enabled = true;
+ }
+ else if (inFile.FileType == TsFileType.TS)
+ {
+ TsFormatRadioButton.Enabled = true;
+ TsFormatRadioButton.Checked = true;
+ if (length > TimeSpan.Zero)
+ {
+ M2tsFormatRadioButton.Enabled = true;
+ BluRayFormatRadioButton.Enabled = true;
+ }
+ M2tsFormatRadioButton.Checked = false;
+ BluRayFormatRadioButton.Checked = false;
+ }
+ else if (inFile.FileType == TsFileType.EVOB)
+ {
+ TsFormatRadioButton.Enabled = true;
+ TsFormatRadioButton.Checked = false;
+ M2tsFormatRadioButton.Enabled = true;
+ M2tsFormatRadioButton.Checked = true;
+ BluRayFormatRadioButton.Enabled = true;
+ BluRayFormatRadioButton.Checked = false;
+ }
+ else if (inFile.FileType == TsFileType.MKV)
+ {
+ TsFormatRadioButton.Enabled = true;
+ TsFormatRadioButton.Checked = true;
+ M2tsFormatRadioButton.Enabled = true;
+ M2tsFormatRadioButton.Checked = false;
+ BluRayFormatRadioButton.Enabled = true;
+ BluRayFormatRadioButton.Checked = false;
+ }
+ if (length > TimeSpan.Zero)
+ EnableNumerics();
+ DtcpInfo.Nodes[0].ExpandAll();
+ }
+
+ private void InputFileTextBox_TextChanged(object sender, EventArgs e)
+ {
+
+ }
+ }
+ }
+
} //namespace