/*
 * PS3 Media Server, for streaming any medias to your PS3.
 * Copyright (C) 2008  A.Brochard
 *
 * This program 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; version 2
 * of the License only.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package net.pms.encoders;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
import java.util.regex.Pattern;	//regzamod
import java.lang.Math;	//regzamod

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import net.pms.Messages;
import net.pms.PMS;
import net.pms.configuration.PmsConfiguration;
import net.pms.configuration.RendererConfiguration;
import net.pms.dlna.DLNAMediaAudio;
import net.pms.dlna.DLNAMediaInfo;
import net.pms.dlna.DLNAMediaSubtitle;
import net.pms.dlna.DLNAResource;
import net.pms.dlna.FileTranscodeVirtualFolder;
import net.pms.dlna.ChapterFileTranscodeVirtualFolder;
import net.pms.dlna.InputFile;
import net.pms.dlna.rz_ScriptExecutor;
import net.pms.dlna.RealFile;			//regzamod

import net.pms.formats.Format;
import net.pms.io.OutputParams;
import net.pms.io.PipeIPCProcess;
import net.pms.io.PipeProcess;
import net.pms.io.ProcessWrapper;
import net.pms.io.ProcessWrapperImpl;
import net.pms.io.StreamModifier;
import net.pms.network.HTTPResource;
import net.pms.newgui.FontFileFilter;
import net.pms.newgui.LooksFrame;
import net.pms.newgui.MyComboBoxModel;
import net.pms.newgui.RestrictedFileSystemView;
import net.pms.util.CodecUtil;
import net.pms.util.ProcessUtil;
import net.pms.util.PMSUtil;	// regzamod
import net.pms.util.FileUtil;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import bsh.EvalError;
import bsh.Interpreter;

import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.factories.Borders;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.sun.jna.Platform;

public class MEncoderVideo extends Player {
	private static final Logger logger = LoggerFactory.getLogger(MEncoderVideo.class);

	private JTextField mencoder_ass_scale;
	private JTextField mencoder_ass_margin;
	private JTextField mencoder_ass_outline;
	private JTextField mencoder_ass_shadow;
	private JTextField mencoder_noass_scale;
	private JTextField mencoder_noass_subpos;
	private JTextField mencoder_noass_blur;
	private JTextField mencoder_noass_outline;
	private JTextField decode;
	private JTextField langs;
	private JTextField defaultsubs;
	private JTextField forcedsub;
	private JTextField forcedtags;
	private JTextField defaultaudiosubs;
	private JTextField defaultfont;
	private JComboBox subcp;
	private JTextField subq;
	private JCheckBox forcefps;
	private JCheckBox yadif;
	private JCheckBox scaler;
	private JTextField scaleX;
	private JTextField scaleY;
	private JCheckBox assdefaultstyle;
	private JCheckBox fc;
	private JCheckBox ass;
	private JCheckBox checkBox;
	private JCheckBox mencodermt;
	private JCheckBox videoremux;
	private JCheckBox noskip;
	private JCheckBox intelligentsync;
	private JTextField alternateSubFolder;
	private JButton subColor;
	private JTextField ocw;
	private JTextField och;
	private JCheckBox subs;
	private JCheckBox fribidi;
	private final PmsConfiguration configuration;
	public static final int MENCODER_MAX_THREADS = 8;
	public static final String ID = "mencoder";
	protected boolean dtsRemux;
	protected boolean dtsEmbed;
	protected boolean pcmMod;
	protected boolean pcmRaw;
	protected boolean mux;
	protected boolean ovccopy;
	protected boolean dvd;
	protected boolean oaccopy;
	protected boolean mpegts;
	protected boolean tx_m2ts;
	protected boolean wmv;
	protected String overriddenMainArgs[];
	protected String mc_acodec;
	protected String ts_acodec;
	
	boolean noMC0NoSkip;
	boolean force_oac;	//regzamod
	boolean force_nosound;	//regzamod
	boolean force_oaccopy;	//regzamod
	boolean force_pcmmod;	//regzamod
	boolean force_pcmraw;	//regzamod
	boolean force_dtsremux;	//regzamod
	boolean force_dtsembed;	//regzamod
	boolean rawvideo;		//videoExruct format
	boolean tstest;	//test
	int script_pos=1;
	
	private static final int MC_MPEGPS =PMS.TRS_MPEGPS;
	private static final int MC_MPEGTS =PMS.TRS_MPEGTS;	// by Mencoder
	private static final int MC_MPEGTS2=PMS.TRS_MPEGTS2;	// by Mencoder+TsMuxer
	private static final int MC_M2TS   =PMS.TRS_M2TS;

	public static final String DEFAULT_CODEC_CONF_SCRIPT =
		Messages.getString("MEncoderVideo.68")
		+ Messages.getString("MEncoderVideo.69")
		+ Messages.getString("MEncoderVideo.70")
		+ Messages.getString("MEncoderVideo.71")
		+ Messages.getString("MEncoderVideo.72")
		+ Messages.getString("MEncoderVideo.73")
		+ Messages.getString("MEncoderVideo.75")
		+ Messages.getString("MEncoderVideo.76")
		+ Messages.getString("MEncoderVideo.77")
		+ Messages.getString("MEncoderVideo.78")
		+ Messages.getString("MEncoderVideo.79")
		+ "#\n"
		+ Messages.getString("MEncoderVideo.80")
		+ "container == iso :: -nosync\n"
		+ "(container == avi || container == matroska) && vcodec == mpeg4 && acodec == mp3 :: -mc 0.1\n"
		+ "container == flv :: -mc 0.1\n"
		+ "container == rm  :: -mc 0.1\n"
		+ "#container == mov :: -mc 0.1 -noass\n"
		+ "#container == matroska && framerate == 29.97  :: -nomux -mc 0\n"
		+ "#container == mp4 && vcodec == h264 :: -mc 0.1 -noass\n"
		+ "\n"
		+ Messages.getString("MEncoderVideo.87")
		+ Messages.getString("MEncoderVideo.88")
		+ Messages.getString("MEncoderVideo.89")
		+ Messages.getString("MEncoderVideo.91");

	public JCheckBox getCheckBox() {
		return checkBox;
	}

	public JCheckBox getNoskip() {
		return noskip;
	}

	public JCheckBox getSubs() {
		return subs;
	}

	public MEncoderVideo(PmsConfiguration configuration) {
		this.configuration = configuration;
	}


	@SuppressWarnings("unchecked") //regzam, for Java7 wornings at <1>
	@Override
	public JComponent config() {
		FormLayout layout = new FormLayout(
			"left:pref, 3dlu, p:grow, 3dlu, right:p:grow, 3dlu, p:grow, 3dlu, right:p:grow,3dlu, p:grow, 3dlu, right:p:grow,3dlu, pref:grow",
			"p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu,p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 9dlu, p, 2dlu, p, 2dlu, p , 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p, 2dlu, p");
		PanelBuilder builder = new PanelBuilder(layout);
		builder.setBorder(Borders.EMPTY_BORDER);
		builder.setOpaque(false);

		CellConstraints cc = new CellConstraints();

		checkBox = new JCheckBox(Messages.getString("MEncoderVideo.0"));
		checkBox.setContentAreaFilled(false);
		if (configuration.getSkipLoopFilterEnabled()) {
			checkBox.setSelected(true);
		}
		checkBox.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				configuration.setSkipLoopFilterEnabled((e.getStateChange() == ItemEvent.SELECTED));
			}
		});

		JComponent cmp = builder.addSeparator(Messages.getString("MEncoderVideo.1"), cc.xyw(1, 1, 15));
		cmp = (JComponent) cmp.getComponent(0);
		cmp.setFont(cmp.getFont().deriveFont(Font.BOLD));

		mencodermt = new JCheckBox(Messages.getString("MEncoderVideo.35"));
		mencodermt.setContentAreaFilled(false);
		if (configuration.getMencoderMT()) {
			mencodermt.setSelected(true);
		}
		mencodermt.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				configuration.setMencoderMT(mencodermt.isSelected());
			}
		});
		mencodermt.setEnabled(Platform.isWindows() || Platform.isMac());

		builder.add(mencodermt, cc.xy(1, 3));
		builder.add(checkBox, cc.xyw(3, 3, 12));

		noskip = new JCheckBox(Messages.getString("MEncoderVideo.2"));
		noskip.setContentAreaFilled(false);
		if (configuration.isMencoderNoOutOfSync()) {
			noskip.setSelected(true);
		}
		noskip.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				configuration.setMencoderNoOutOfSync((e.getStateChange() == ItemEvent.SELECTED));
			}
		});

		builder.add(noskip, cc.xy(1, 5));

		JButton button = new JButton(Messages.getString("MEncoderVideo.29"));
		button.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JPanel codecPanel = new JPanel(new BorderLayout());
				final JTextArea textArea = new JTextArea();
				textArea.setText(configuration.getCodecSpecificConfig());
				textArea.setFont(new Font("Courier", Font.PLAIN, 12));
				JScrollPane scrollPane = new JScrollPane(textArea);
				scrollPane.setPreferredSize(new java.awt.Dimension(900, 100));

				final JTextArea textAreaDefault = new JTextArea();
				textAreaDefault.setText(DEFAULT_CODEC_CONF_SCRIPT);
				textAreaDefault.setBackground(Color.WHITE);
				textAreaDefault.setFont(new Font("Courier", Font.PLAIN, 12));
				textAreaDefault.setEditable(false);
				textAreaDefault.setEnabled(configuration.isMencoderIntelligentSync());
				JScrollPane scrollPaneDefault = new JScrollPane(textAreaDefault);
				scrollPaneDefault.setPreferredSize(new java.awt.Dimension(900, 450));

				JPanel customPanel = new JPanel(new BorderLayout());
				intelligentsync = new JCheckBox(Messages.getString("MEncoderVideo.3"));
				intelligentsync.setContentAreaFilled(false);
				if (configuration.isMencoderIntelligentSync()) {
					intelligentsync.setSelected(true);
				}
				intelligentsync.addItemListener(new ItemListener() {
					public void itemStateChanged(ItemEvent e) {
						configuration.setMencoderIntelligentSync((e.getStateChange() == ItemEvent.SELECTED));
						textAreaDefault.setEnabled(configuration.isMencoderIntelligentSync());

					}
				});

				JLabel label = new JLabel(Messages.getString("MEncoderVideo.33"));
				customPanel.add(label, BorderLayout.NORTH);
				customPanel.add(scrollPane, BorderLayout.SOUTH);

				codecPanel.add(intelligentsync, BorderLayout.NORTH);
				codecPanel.add(scrollPaneDefault, BorderLayout.CENTER);
				codecPanel.add(customPanel, BorderLayout.SOUTH);
				while (JOptionPane.showOptionDialog((JFrame) (SwingUtilities.getWindowAncestor((Component) PMS.get().getFrame())),
					codecPanel, Messages.getString("MEncoderVideo.34"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null) == JOptionPane.OK_OPTION) {
					String newCodecparam = textArea.getText();
					DLNAMediaInfo fakemedia = new DLNAMediaInfo();
					DLNAMediaAudio audio = new DLNAMediaAudio();
					audio.setCodecA("ac3");
					fakemedia.setCodecV("mpeg4");
					fakemedia.setContainer("matroska");
					fakemedia.setDuration(45d*60);
					audio.setNrAudioChannels(2);
					fakemedia.setWidth(1280);
					fakemedia.setHeight(720);
					audio.setSampleFrequency("48000");
					fakemedia.setFrameRate("23.976");
					fakemedia.getAudioCodes().add(audio);
					//---- call of getSpecificCodecOptions for check scripts is valid 
					String result[] = getSpecificCodecOptions(newCodecparam, fakemedia, new OutputParams(configuration), 
						"dummy.mpg", "dummy.srt", false, true, null);
					if (result.length > 0 && result[0].startsWith("@@")) {
						String errorMessage = result[0].substring(2);
						JOptionPane.showMessageDialog((JFrame) (SwingUtilities.getWindowAncestor((Component) PMS.get().getFrame())), errorMessage);

					} else {
						configuration.setCodecSpecificConfig(newCodecparam);
						break;
					}
				}
			}
		});
		builder.add(button, cc.xyw(1, 11, 2));

		forcefps = new JCheckBox(Messages.getString("MEncoderVideo.4"));
		forcefps.setContentAreaFilled(false);
		if (configuration.isMencoderForceFps()) {
			forcefps.setSelected(true);
		}
		forcefps.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				configuration.setMencoderForceFps(e.getStateChange() == ItemEvent.SELECTED);
			}
		});

		builder.add(forcefps, cc.xyw(1, 7, 2));

		yadif = new JCheckBox(Messages.getString("MEncoderVideo.26"));
		yadif.setContentAreaFilled(false);
		if (configuration.isMencoderYadif()) {
			yadif.setSelected(true);
		}
		yadif.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				configuration.setMencoderYadif(e.getStateChange() == ItemEvent.SELECTED);
			}
		});

		builder.add(yadif, cc.xyw(3, 7, 7));

		scaler = new JCheckBox(Messages.getString("MEncoderVideo.27"));
		scaler.setContentAreaFilled(false);
		scaler.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				configuration.setMencoderScaler(e.getStateChange() == ItemEvent.SELECTED);
				scaleX.setEnabled(configuration.isMencoderScaler());
				scaleY.setEnabled(configuration.isMencoderScaler());
			}
		});

		builder.add(scaler, cc.xyw(3, 5, 7));

		builder.addLabel(Messages.getString("MEncoderVideo.28"), cc.xyw(10, 5, 3, CellConstraints.RIGHT, CellConstraints.CENTER));
		scaleX = new JTextField("" + configuration.getMencoderScaleX());
		scaleX.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				try {
					configuration.setMencoderScaleX(Integer.parseInt(scaleX.getText()));
				} catch (NumberFormatException nfe) {
				}
			}
		});
		builder.add(scaleX, cc.xyw(13, 5, 3));

		builder.addLabel(Messages.getString("MEncoderVideo.30"), cc.xyw(10, 7, 3, CellConstraints.RIGHT, CellConstraints.CENTER));
		scaleY = new JTextField("" + configuration.getMencoderScaleY());
		scaleY.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				try {
					configuration.setMencoderScaleY(Integer.parseInt(scaleY.getText()));
				} catch (NumberFormatException nfe) {
				}
			}
		});
		builder.add(scaleY, cc.xyw(13, 7, 3));

		if (configuration.isMencoderScaler()) {
			scaler.setSelected(true);
		} else {
			scaleX.setEnabled(false);
			scaleY.setEnabled(false);
		}



		videoremux = new JCheckBox("<html>" + Messages.getString("MEncoderVideo.38") + "</html>");
		videoremux.setContentAreaFilled(false);
		if (configuration.isMencoderMuxWhenCompatible()) {
			videoremux.setSelected(true);
		}
		videoremux.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				configuration.setMencoderMuxWhenCompatible((e.getStateChange() == ItemEvent.SELECTED));
			}
		});

		builder.add(videoremux, cc.xyw(1, 9, 13));

		cmp = builder.addSeparator(Messages.getString("MEncoderVideo.5"), cc.xyw(1, 19, 15));
		cmp = (JComponent) cmp.getComponent(0);
		cmp.setFont(cmp.getFont().deriveFont(Font.BOLD));

		builder.addLabel(Messages.getString("MEncoderVideo.6"), cc.xy(1, 21));
		decode = new JTextField(configuration.getMencoderDecode());
		decode.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderDecode(decode.getText());
			}
		});
		builder.add(decode, cc.xyw(3, 21, 13));

		builder.addLabel(Messages.getString("MEncoderVideo.7"), cc.xyw(1, 23, 15));
		langs = new JTextField(configuration.getMencoderAudioLanguages());
		langs.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderAudioLanguages(langs.getText());
			}
		});
		builder.add(langs, cc.xyw(3, 23, 8));

		cmp = builder.addSeparator(Messages.getString("MEncoderVideo.8"), cc.xyw(1, 25, 15));
		cmp = (JComponent) cmp.getComponent(0);
		cmp.setFont(cmp.getFont().deriveFont(Font.BOLD));

		builder.addLabel(Messages.getString("MEncoderVideo.9"), cc.xy(1, 27));
		defaultsubs = new JTextField(configuration.getMencoderSubLanguages());
		defaultsubs.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderSubLanguages(defaultsubs.getText());
			}
		});

		builder.addLabel(Messages.getString("MEncoderVideo.94"), cc.xy(5, 27));
		forcedsub = new JTextField(configuration.getMencoderForcedSubLanguage());
		forcedsub.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderForcedSubLanguage(forcedsub.getText());
			}
		});

		builder.addLabel(Messages.getString("MEncoderVideo.95"), cc.xy(9, 27));
		forcedtags = new JTextField(configuration.getMencoderForcedSubTags());
		forcedtags.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderForcedSubTags(forcedtags.getText());
			}
		});
		builder.add(defaultsubs, cc.xyw(3, 27, 2));

		builder.add(forcedsub, cc.xy(7, 27));

		builder.add(forcedtags, cc.xyw(11, 27, 5));

		builder.addLabel(Messages.getString("MEncoderVideo.10"), cc.xy(1, 29));
		defaultaudiosubs = new JTextField(configuration.getMencoderAudioSubLanguages());
		defaultaudiosubs.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderAudioSubLanguages(defaultaudiosubs.getText());
			}
		});
		builder.add(defaultaudiosubs, cc.xyw(3, 29, 8));

		builder.addLabel(Messages.getString("MEncoderVideo.11"), cc.xy(1, 31));
		Object data[] = new Object[]{
			configuration.getMencoderSubCp(),
			"/* None */",
			"cp1250  /* Windows - Eastern Europe */",
			"cp1251  /* Windows - Cyrillic */",
			"cp1252  /* Windows - Western Europe */",
			"cp1253  /* Windows - Greek */",
			"cp1254  /* Windows - Turkish */",
			"cp1255  /* Windows - Hebrew */",
			"cp1256  /* Windows - Arabic */",
			"cp1257  /* Windows - Baltic */",
			"cp1258  /* Windows - Vietnamese */",
			"ISO-8859-1 /* Western Europe */",
			"ISO-8859-2 /* Western and Central Europe */",
			"ISO-8859-3 /* Western Europe and South European */",
			"ISO-8859-4 /* Western Europe and Baltic countries */",
			"ISO-8859-5 /* Cyrillic alphabet */",
			"ISO-8859-6 /* Arabic */",
			"ISO-8859-7 /* Greek */",
			"ISO-8859-8 /* Hebrew */",
			"ISO-8859-9 /* Western Europe with amended Turkish */",
			"ISO-8859-10 /* Western Europe with Nordic languages */",
			"ISO-8859-11 /* Thai */",
			"ISO-8859-13 /* Baltic languages plus Polish */",
			"ISO-8859-14 /* Celtic languages */",
			"ISO-8859-15 /* Added the Euro sign */",
			"ISO-8859-16 /* Central European languages */",
			"cp932   /* Japanese */",
			"cp936   /* Chinese */",
			"cp949   /* Korean */",
			"cp950   /* Big5, Taiwanese, Cantonese */", 
			"UTF-8   /* Unicode */"
		};
		MyComboBoxModel cbm = new MyComboBoxModel(data);
		
		//@SuppressWarnings("unchecked") //cause Compile Error, if anotated here
		subcp = new JComboBox(cbm);  //<1>
		subcp.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				if (e.getStateChange() == ItemEvent.SELECTED) {
					String s = (String) e.getItem();
					if (s.indexOf("/*") > -1) {
						s = s.substring(0, s.indexOf("/*")).trim();
					}
					configuration.setMencoderSubCp(s);
					//PMS.dbg("MencoderVideo: SubCp Changed to='"+s+"'");
				}
			}
		});
		subcp.setEditable(true);
		builder.add(subcp, cc.xyw(3, 31, 7));

		fribidi = new JCheckBox(Messages.getString("MEncoderVideo.23"));
		fribidi.setContentAreaFilled(false);
		if (configuration.isMencoderSubFribidi()) {
			fribidi.setSelected(true);
		}
		fribidi.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				configuration.setMencoderSubFribidi(e.getStateChange() == ItemEvent.SELECTED);
			}
		});
		builder.add(fribidi, cc.xyw(11, 31, 4));

		builder.addLabel(Messages.getString("MEncoderVideo.24"), cc.xy(1, 33));
		defaultfont = new JTextField(configuration.getMencoderFont());
		defaultfont.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderFont(defaultfont.getText());
			}
		});
		builder.add(defaultfont, cc.xyw(3, 33, 8));

		JButton fontselect = new JButton("...");
		fontselect.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JFileChooser chooser = new JFileChooser();
				chooser.setFileFilter(new FontFileFilter());
				int returnVal = chooser.showDialog((Component) e.getSource(), Messages.getString("MEncoderVideo.25"));
				if (returnVal == JFileChooser.APPROVE_OPTION) {
					defaultfont.setText(chooser.getSelectedFile().getAbsolutePath());
					configuration.setMencoderFont(chooser.getSelectedFile().getAbsolutePath());
				}
			}
		});
		builder.add(fontselect, cc.xyw(11, 33, 2));

		builder.addLabel(Messages.getString("MEncoderVideo.37"), cc.xyw(1, 35, 3));
		alternateSubFolder = new JTextField(configuration.getAlternateSubsFolder());
		alternateSubFolder.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setAlternateSubsFolder(alternateSubFolder.getText());
			}
		});
		builder.add(alternateSubFolder, cc.xyw(3, 35, 8));

		JButton select = new JButton("...");
		select.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JFileChooser chooser = null;
				try {
					chooser = new JFileChooser();
				} catch (Exception ee) {
					chooser = new JFileChooser(new RestrictedFileSystemView());
				}
				chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
				int returnVal = chooser.showDialog((Component) e.getSource(), Messages.getString("FoldTab.28"));
				if (returnVal == JFileChooser.APPROVE_OPTION) {
					alternateSubFolder.setText(chooser.getSelectedFile().getAbsolutePath());
					configuration.setAlternateSubsFolder(chooser.getSelectedFile().getAbsolutePath());
				}
			}
		});
		builder.add(select, cc.xyw(11, 35, 2));

		builder.addLabel(Messages.getString("MEncoderVideo.12"), cc.xy(1, 39, CellConstraints.RIGHT, CellConstraints.CENTER));
		mencoder_ass_scale = new JTextField(configuration.getMencoderAssScale());
		mencoder_ass_scale.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderAssScale(mencoder_ass_scale.getText());
			}
		});

		builder.addLabel(Messages.getString("MEncoderVideo.13"), cc.xy(5, 39));
		mencoder_ass_outline = new JTextField(configuration.getMencoderAssOutline());
		mencoder_ass_outline.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderAssOutline(mencoder_ass_outline.getText());
			}
		});

		builder.addLabel(Messages.getString("MEncoderVideo.14"), cc.xy(9, 39));
		mencoder_ass_shadow = new JTextField(configuration.getMencoderAssShadow());
		mencoder_ass_shadow.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderAssShadow(mencoder_ass_shadow.getText());
			}
		});

		builder.addLabel(Messages.getString("MEncoderVideo.15"), cc.xy(13, 39));
		mencoder_ass_margin = new JTextField(configuration.getMencoderAssMargin());
		mencoder_ass_margin.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderAssMargin(mencoder_ass_margin.getText());
			}
		});
		builder.add(mencoder_ass_scale, cc.xy(3, 39));

		builder.add(mencoder_ass_outline, cc.xy(7, 39));

		builder.add(mencoder_ass_shadow, cc.xy(11, 39));

		builder.add(mencoder_ass_margin, cc.xy(15, 39));


		builder.addLabel(Messages.getString("MEncoderVideo.16"), cc.xy(1, 41, CellConstraints.RIGHT, CellConstraints.CENTER));
		mencoder_noass_scale = new JTextField(configuration.getMencoderNoAssScale());
		mencoder_noass_scale.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderNoAssScale(mencoder_noass_scale.getText());
			}
		});

		builder.addLabel(Messages.getString("MEncoderVideo.17"), cc.xy(5, 41));
		mencoder_noass_outline = new JTextField(configuration.getMencoderNoAssOutline());
		mencoder_noass_outline.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderNoAssOutline(mencoder_noass_outline.getText());
			}
		});

		builder.addLabel(Messages.getString("MEncoderVideo.18"), cc.xy(9, 41));
		mencoder_noass_blur = new JTextField(configuration.getMencoderNoAssBlur());
		mencoder_noass_blur.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderNoAssBlur(mencoder_noass_blur.getText());
			}
		});

		builder.addLabel(Messages.getString("MEncoderVideo.19"), cc.xy(13, 41));
		mencoder_noass_subpos = new JTextField(configuration.getMencoderNoAssSubPos());
		mencoder_noass_subpos.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderNoAssSubPos(mencoder_noass_subpos.getText());
			}
		});
		builder.add(mencoder_noass_scale, cc.xy(3, 41));

		builder.add(mencoder_noass_outline, cc.xy(7, 41));

		builder.add(mencoder_noass_blur, cc.xy(11, 41));

		builder.add(mencoder_noass_subpos, cc.xy(15, 41));


		ass = new JCheckBox(Messages.getString("MEncoderVideo.20"));
		ass.setContentAreaFilled(false);
		ass.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				if (e != null) {
					configuration.setMencoderAss(e.getStateChange() == ItemEvent.SELECTED);
				}

				mencoder_ass_scale.setEnabled(configuration.isMencoderAss());
				mencoder_ass_outline.setEnabled(configuration.isMencoderAss());
				mencoder_ass_shadow.setEnabled(configuration.isMencoderAss());
				mencoder_ass_margin.setEnabled(configuration.isMencoderAss());
				mencoder_noass_scale.setEnabled(!configuration.isMencoderAss());
				mencoder_noass_outline.setEnabled(!configuration.isMencoderAss());
				mencoder_noass_blur.setEnabled(!configuration.isMencoderAss());
				mencoder_noass_subpos.setEnabled(!configuration.isMencoderAss());
			}
		});

		builder.add(ass, cc.xy(1, 37));
		ass.setSelected(configuration.isMencoderAss());
		ass.getItemListeners()[0].itemStateChanged(null);

		fc = new JCheckBox(Messages.getString("MEncoderVideo.21"));
		fc.setContentAreaFilled(false);
		fc.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				configuration.setMencoderFontConfig(e.getStateChange() == ItemEvent.SELECTED);
			}
		});

		builder.add(fc, cc.xyw(3, 37, 5));
		fc.setSelected(configuration.isMencoderFontConfig());

		assdefaultstyle = new JCheckBox(Messages.getString("MEncoderVideo.36"));
		assdefaultstyle.setContentAreaFilled(false);
		assdefaultstyle.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				configuration.setMencoderAssDefaultStyle(e.getStateChange() == ItemEvent.SELECTED);
			}
		});

		builder.add(assdefaultstyle, cc.xyw(8, 37, 4));
		assdefaultstyle.setSelected(configuration.isMencoderAssDefaultStyle());

		subs = new JCheckBox(Messages.getString("MEncoderVideo.22"));
		subs.setContentAreaFilled(false);
		if (configuration.getUseSubtitles()) {
			subs.setSelected(true);
		}
		subs.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				configuration.setUseSubtitles((e.getStateChange() == ItemEvent.SELECTED));
			}
		});
		builder.add(subs, cc.xyw(1, 43, 15));

		builder.addLabel(Messages.getString("MEncoderVideo.92"), cc.xy(1, 45));
		subq = new JTextField(configuration.getMencoderVobsubSubtitleQuality());
		subq.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderVobsubSubtitleQuality(subq.getText());
			}
		});
		builder.add(subq, cc.xyw(3, 45, 1));

		builder.addLabel(Messages.getString("MEncoderVideo.93"), cc.xyw(1, 47, 6));

		builder.addLabel(Messages.getString("MEncoderVideo.28"), cc.xy(1, 49, CellConstraints.RIGHT, CellConstraints.CENTER));
		ocw = new JTextField(configuration.getMencoderOverscanCompensationWidth());
		ocw.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderOverscanCompensationWidth(ocw.getText());
			}
		});
		builder.add(ocw, cc.xyw(3, 49, 1));

		builder.addLabel(Messages.getString("MEncoderVideo.30"), cc.xy(5, 49));
		och = new JTextField(configuration.getMencoderOverscanCompensationHeight());
		och.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}

			@Override
			public void keyReleased(KeyEvent e) {
				configuration.setMencoderOverscanCompensationHeight(och.getText());
			}
		});
		builder.add(och, cc.xyw(7, 49, 1));

		subColor = new JButton();
		subColor.setText(Messages.getString("MEncoderVideo.31"));
		subColor.setBackground(new Color(configuration.getSubsColor()));
		subColor.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				Color newColor = JColorChooser.showDialog(
					(JFrame) (SwingUtilities.getWindowAncestor((Component) PMS.get().getFrame())),
					"Choose Subtitles Color",
					subColor.getBackground());
				if (newColor != null) {
					subColor.setBackground(newColor);
					configuration.setSubsColor(newColor.getRGB());
				}
			}
		});
		builder.add(subColor, cc.xyw(12, 37, 4));

		JCheckBox disableSubs = ((LooksFrame) PMS.get().getFrame()).getTr().getDisableSubs();
		disableSubs.addItemListener(new ItemListener() {
			public void itemStateChanged(ItemEvent e) {
				configuration.setMencoderDisableSubs(e.getStateChange() == ItemEvent.SELECTED);

				subs.setEnabled(!configuration.isMencoderDisableSubs());
				subq.setEnabled(!configuration.isMencoderDisableSubs());
				defaultsubs.setEnabled(!configuration.isMencoderDisableSubs());
				subcp.setEnabled(!configuration.isMencoderDisableSubs());
				ass.setEnabled(!configuration.isMencoderDisableSubs());
				assdefaultstyle.setEnabled(!configuration.isMencoderDisableSubs());
				fribidi.setEnabled(!configuration.isMencoderDisableSubs());
				fc.setEnabled(!configuration.isMencoderDisableSubs());
				mencoder_ass_scale.setEnabled(!configuration.isMencoderDisableSubs());
				mencoder_ass_outline.setEnabled(!configuration.isMencoderDisableSubs());
				mencoder_ass_shadow.setEnabled(!configuration.isMencoderDisableSubs());
				mencoder_ass_margin.setEnabled(!configuration.isMencoderDisableSubs());
				mencoder_noass_scale.setEnabled(!configuration.isMencoderDisableSubs());
				mencoder_noass_outline.setEnabled(!configuration.isMencoderDisableSubs());
				mencoder_noass_blur.setEnabled(!configuration.isMencoderDisableSubs());
				mencoder_noass_subpos.setEnabled(!configuration.isMencoderDisableSubs());

				if (!configuration.isMencoderDisableSubs()) {
					ass.getItemListeners()[0].itemStateChanged(null);
				}
			}
		});
		if (configuration.isMencoderDisableSubs()) {
			disableSubs.setSelected(true);
		}

		return builder.getPanel();
	}

	@Override
	public int purpose() {
		return VIDEO_SIMPLEFILE_PLAYER;
	}

	@Override
	public String id() {
		return ID;
	}

	@Override
	public boolean avisynth() {
		return false;
	}

	@Override
	public boolean isTimeSeekable() {
		return true;
	}

	protected String[] getDefaultArgs() {
		return new String[]{
			(PMS.rz_debug>1?"-quiet":"-really-quiet"),
			"-oac", oaccopy ? "copy" : ((pcmMod||pcmRaw) ? "pcm" : "lavc"),
			"-of", (wmv || mpegts) ? "lavf" : ((pcmMod||pcmRaw) && avisynth()) ? "avi" : (((pcmMod||pcmRaw||dtsRemux||dtsEmbed||mux) ? "rawvideo" : "mpeg")),
			(wmv || mpegts) ? "-lavfopts" : "-quiet",
			wmv ? "format=asf" : (mpegts ? "format=mpegts" : "-quiet"),
			"-mpegopts", "format=mpeg2:muxrate=500000:vbuf_size=1194:abuf_size=64",
			"-ovc", (mux || ovccopy) ? "copy" : "lavc"
		};
	}

	@Override
	public String[] args() {
		String args[] = null;
		String defaultArgs[] = getDefaultArgs();
		if (overriddenMainArgs != null) {
			args = new String[defaultArgs.length + overriddenMainArgs.length];
			for (int i = 0; i < defaultArgs.length; i++) {
				args[i] = defaultArgs[i];
			}
			for (int i = 0; i < overriddenMainArgs.length; i++) {
				if ("-of".equals(overriddenMainArgs[i]) || "-oac".equals(overriddenMainArgs[i]) || "-ovc".equals(overriddenMainArgs[i]) || "-mpegopts".equals(overriddenMainArgs[i])) {
					if(PMS.rz_debug>1) PMS.dbg("MEncoder encoder settings: You cannot change Muxer, Muxer options, Video Codec or Audio Codec");
					overriddenMainArgs[i] = "-quiet";
					if (i + 1 < overriddenMainArgs.length) {
						overriddenMainArgs[i + 1] = "-quiet";
					}
				}
				args[i + defaultArgs.length] = overriddenMainArgs[i];
			}
		} else {
			args = defaultArgs;
		}
		return args;

	}

	@Override
	public String executable() {
		return configuration.getMencoderPath();
	}
	
	private String executable_in(DLNAResource dlna,int mode) {
		String path=dlna.getForcedTransProg();
		if(path!=null) {
			return path;
		}
		return configuration.getMencoderPath();
	}

	private int[] getVideoBitrateConfig(String bitrate) {
		int bitrates[] = new int[2];
		if (bitrate.contains("(") && bitrate.contains(")")) {
			bitrates[1] = Integer.parseInt(bitrate.substring(bitrate.indexOf("(") + 1, bitrate.indexOf(")")));
		}
		if (bitrate.contains("("))
		{
			bitrate = bitrate.substring(0, bitrate.indexOf("(")).trim();
		}
		if (StringUtils.isBlank(bitrate)) {
			bitrate = "0";
		}
		bitrates[0] = (int) Double.parseDouble(bitrate);
		return bitrates;
	}

	/**
	 * Note: This is not exact, the bitrate can go above this but it is generally pretty good.
	 * @return The maximum bitrate the video should be along with the buffer size using MEncoder vars
	 */
	private String addMaximumBitrateConstraints(String encodeSettings, DLNAMediaInfo media, String quality, RendererConfiguration mediaRenderer, String audioType) {
		int defaultMaxBitrates[] = getVideoBitrateConfig(configuration.getMaximumBitrate());
		int rendererMaxBitrates[] = new int[2];
		if (mediaRenderer.getMaxVideoBitrate() != null) {
			rendererMaxBitrates = getVideoBitrateConfig(mediaRenderer.getMaxVideoBitrate());
		}
		if ((defaultMaxBitrates[0] == 0 && rendererMaxBitrates[0] > 0) || rendererMaxBitrates[0] < defaultMaxBitrates[0] && rendererMaxBitrates[0] > 0) {
			defaultMaxBitrates = rendererMaxBitrates;
		}
		if (defaultMaxBitrates[0] > 0 && !quality.contains("vrc_buf_size") && !quality.contains("vrc_maxrate") && !quality.contains("vbitrate")) {
			// Convert value from Mb to Kb
			defaultMaxBitrates[0] = 1000 * defaultMaxBitrates[0];

			// Halve it since it seems to send up to 1 second of video in advance
			defaultMaxBitrates[0] = defaultMaxBitrates[0] / 2;

			int bufSize = 1835;
			if (media.isHDVideo()) {
				bufSize = defaultMaxBitrates[0] / 3;
			}
			if (bufSize > 7000) {
				bufSize = 7000;
			}

			if (defaultMaxBitrates[1] > 0) {
				bufSize = defaultMaxBitrates[1];
			}

			if (mediaRenderer.isDefaultVBVSize() && rendererMaxBitrates[1] == 0) {
				bufSize = 1835;
			}

			// Make room for audio
			// If audio is PCM, subtract 4600kb/s
			if ("pcm".equals(audioType)) {
				defaultMaxBitrates[0] = defaultMaxBitrates[0] - 4600;
			}
			// If audio is DTS, subtract 1510kb/s
			else if ("dts".equals(audioType)) {
				defaultMaxBitrates[0] = defaultMaxBitrates[0] - 1510;
			}
			// If audio is AC3, subtract 640kb/s to be safe
			else if ("ac3".equals(audioType)) {
				defaultMaxBitrates[0] = defaultMaxBitrates[0] - 640;
			}

			// Round down to the nearest Mb
			defaultMaxBitrates[0] = defaultMaxBitrates[0] / 1000 * 1000;

			encodeSettings += ":vrc_maxrate=" + defaultMaxBitrates[0] + ":vrc_buf_size=" + bufSize;
		}
		return encodeSettings;
	}

	@Override
	public ProcessWrapper launchTranscode(
		String fileName,
		DLNAResource dlna,
		DLNAMediaInfo media,
		OutputParams params
	) throws IOException {
		
		//PMS.dbg("MencoderVideo: Start file="+fileName);
		if(media==null) {
			logger.error("MencoderVideo: media=null, return noop");
			return null;
		}
		
		//---- tuning params for start playing
		//params.manageFastStart();
		params.manageStart(params.mediaRenderer.getRZ_TransStartWait());  //set default
		
		//must be initted
		mc_acodec="lavc";
		ts_acodec="A_AC3";
		noMC0NoSkip = false;
		
		String mencoder_path=executable_in(dlna,0);
		dtsRemux=false;
		dtsEmbed=false;
		pcmMod=false;
		pcmRaw=false;
		mux=false;
		ovccopy=false;
		oaccopy=false;
		dvd=false;
		rawvideo=false;

		force_oac=false;	//regzamod
		force_nosound=false;	//regzamod
		force_oaccopy=false;	//regzamod
		force_pcmmod=false;	//regzamod
		force_pcmraw=false;	//regzamod
		//force_dtsremux=false;	//regzamod
		force_dtsembed=false;	//regzamod
		
		String shortFileName;
		if(dlna instanceof RealFile) {
			/*
			File f=new File(fileName);
			if(!f.exists()) {
				logger.error("MencoderVideo: file not exists name="+fileName);
				return null;
			}
			*/
			shortFileName=ProcessUtil.getShortFileNameIfWideChars(fileName);
		}
		else {
			shortFileName=fileName;
		}
		
		boolean avisynth = avisynth();

		setAudioAndSubs(fileName, dlna, media, params, configuration);

		if(script_pos==1) {  //exec as early as possible
			if(PMS.rz_is_rend_script_enabled && params.sess.scex!=null) {
				//Remux container format & specific options
				int trans_format=params.mediaRenderer.getRZ_TransVFormat();
				//---- override by rz_MetaTransFormat in pxm/pxf 
				if(dlna.getForcedRemuxFormat()>=0) {
					trans_format=dlna.getForcedTransFormat();
				}
				
				rz_ScriptExecutor.medAddOpts spec_addopts=new rz_ScriptExecutor.medAddOpts();
				spec_addopts.player=this.toString();
				//spec_addopts.trans_type=rz_ScriptExecutor.trans_type_int2string(PMS.ENC_TRANSCODE);
				spec_addopts.trans_type=rz_ScriptExecutor.trans_type_int2string(dlna.getEncMode());
				spec_addopts.trans_format=rz_ScriptExecutor.trans_format_int2string(trans_format);

				//execScripts(type,when,taget,dlna,..)
				// int type;	//=1:load,=2:exec
				// int when;	//=1:list,=2:play,  =3:list|play,  =4:oneshot
				// int target;	//=1:file,=2:folder,=3:file|folder,=4:other

				params.sess.scex.execScripts(2,2,1,dlna,dlna.getSrcPath(),params,spec_addopts);
				//if(dlna.rz_MetaMencoderOpt[1]!=null) {		//from scripts
				//	opt_add +=dlna.rz_MetaMencoderOpt[1];
				//}
			}
			mencoder_path=executable_in(dlna,0);  //may be forced by scripts
		}

		String subString = null;
		if (params.sid != null && params.sid.getPlayableFile() != null) {
			subString = ProcessUtil.getShortFileNameIfWideChars(params.sid.getPlayableFile().getAbsolutePath());
		}

		InputFile newInput = new InputFile();
		newInput.setFilename(fileName);
		newInput.setPush(params.stdin);

		dvd = false;
		if (media != null && media.getDvdtrack() > 0) {
			dvd = true;
		}

		// don't honour "Switch to tsMuxeR..." if the resource is being streamed via an MEncoder entry in
		// the #--TRANSCODE--# folder
		boolean forceMencoder = !configuration.getHideTranscodeEnabled()
			&& dlna.isNoName()
			&& 	((dlna.getParent() instanceof FileTranscodeVirtualFolder)
		    ||(dlna.getParent() instanceof ChapterFileTranscodeVirtualFolder));

		ovccopy = false;

		int intOCW = Integer.parseInt(configuration.getMencoderOverscanCompensationWidth());
		int intOCH = Integer.parseInt(configuration.getMencoderOverscanCompensationHeight());

		if(PMS.rz_debug>1) {
			PMS.dbg("==> MEncoderVideo: width=" +media.getWidth()+" Height="+media.getHeight());	//regzamod
			PMS.dbg("==> MEncoderVideo: intOCW=" +intOCW+" intOCH="+intOCH);//regzamod	

			//this is heavy, PMS.dbg("==> MEncoderVideo: isVideoPS3Compatible(newInput)=" +media.isVideoPS3Compatible(newInput));		
			PMS.dbg("==> MEncoderVideo: mediaRenderer.isH264Level41Limited=" +params.mediaRenderer.isH264Level41Limited());		
			
			PMS.dbg("==> MEncoderVideo: isMuxable(params.mediaRenderer)=" +media.isMuxable(params.mediaRenderer));		
			PMS.dbg("==> MEncoderVideo: isMencoderMuxWhenCompatible()="+configuration.isMencoderMuxWhenCompatible());	
			PMS.dbg("==> MEncoderVideo: mediaRenderer.isMuxH264MpegTS()=" +params.mediaRenderer.isMuxH264MpegTS()); 

			PMS.dbg("MEncoderVideo: media=" + media);	//regzamod
			if(media!=null && media.getCodecV()!=null) {
				PMS.dbg("MEncoderVideo: media.getCodecV()="+media.getCodecV());	//regzamod
				PMS.dbg("MEncoderVideo: media.getCodecV().equals(h264)"+media.getCodecV().equals("h264"));	//regzamod
			}
			PMS.dbg("MEncoderVideo: nomux1 params.sid"+params.sid);	//regzamod
			PMS.dbg("MEncoderVideo: nomux2 configuration.isMencoderRemuxMPEG2()"+configuration.isMencoderRemuxMPEG2());	//regzamod
			PMS.dbg("MEncoderVideo: nomux3 params.mediaRenderer.isMpeg2Supported()"+params.mediaRenderer.isMpeg2Supported());	//regzamod
		}
		
		//---- regzamod start --------------------
		String aspect_str="4/3";
		double aspect_d=1.333333;
		double	aspect_f;
		double zoom1=1,zoom2=1,zoom=1;
		int height=0;
		int	width=0;
		height= media.getHeight();
		width=  media.getWidth();
		String	exp_str="";
		String	crop_str="";
		double	shiftx=dlna.rz_MetaShift[0];
		double	shifty=dlna.rz_MetaShift[1];

		int ew=(params.mediaRenderer.getMaxVideoWidth() > 0 ? params.mediaRenderer.getMaxVideoWidth() : configuration.getMencoderScaleX());
		int eh=(params.mediaRenderer.getMaxVideoHeight() > 0 ? params.mediaRenderer.getMaxVideoHeight() : configuration.getMencoderScaleY());
		if(dvd) {
			zoom1=params.mediaRenderer.getRZ_SDsizeZoomDVD();
		}
		else {
			zoom1=params.mediaRenderer.getRZ_SDsizeZoom();
		}
		//if(dlna.rz_MetaZoom>0) {
		//	zoom2=dlna.rz_MetaZoom;
		//}
		if(dlna.getForcedZoom()>0) {
			zoom2=dlna.getForcedZoom();
		}
		if(eh<=480 && zoom1!=1.0) {	// zoom to nagete TV's overscan that chopps video edge erea
			zoom=zoom1*zoom2;
		}
		else {
			zoom=zoom2;
		}

		//height= Integer.parseInt(media.getHeight());
		if(dlna.rz_MetaAspect!=null) {	//meta_file param, forced! 
			aspect_f=Double.parseDouble(dlna.rz_MetaAspect);
			//aspect_str=dlna.rz_MetaAspect;
		}
		else {
			aspect_f=media.getAspect_f();
			if(aspect_f<=0) {
				aspect_f= (float)width/(float)height;	//fail safe
			}
		}
		// mencoder aspect must be 16/9 or 4/3 for regza
		//if(aspect_f >= 1.4 || zoom>1.0 || shiftx!=0) {
		if(aspect_f >= 1.35 || shiftx!=0 || (zoom>0.9 && zoom!=1)) {
			aspect_str= "16/9";
			aspect_d=1.777778;
		}
		if(configuration.getMencoderScaleY()>480 && params.mediaRenderer.getRZ_AspectHack()>0) {	
			//fake up: REGZA can't display mpeg2video designated as aspect 16/9 when over 480p, 
			//but REGZA expand 4/3 to full wide 16/9
			aspect_str= "4/3";	
			aspect_d=1.777778;
		}
		
		if(PMS.rz_debug>1) {
			PMS.dbg("MencoderVideo: Start rz_mod="+PMS.rz_mod+", codecV="+media.getCodecV()
				+", width="+width+" ,height="+height+", real_aspect="+aspect_f+ ", param_aspect="+aspect_str);	//regzamod
			PMS.dbg("MencoderVideo: params.timeseek="+params.timeseek);	//regzamod
			//PMSUtil.strace();	// stack trace
		}
		
		//PMS.dbg("PMS.getConfiguration().getUseSubtitles()="+PMS.getConfiguration().getUseSubtitles());
		//PMS.dbg("dlna.rz_MetaMencoderOpt="+dlna.rz_MetaMencoderOpt);
		
		boolean use_subs=false;
		if(params.sid!=null) {
			use_subs=true;
		}
		else {
			if(false && PMS.getConfiguration().getUseSubtitles()) {
				//no-use: already checked by setAudioAndSubs()
				File f=new File(fileName);
				use_subs=FileUtil.doesSubtitlesExists(f, null);
				//PMS.dbg("subTitle exists, use_subs");
				//use_subs=true;	//!!
				
			}
			/*
			 Pattern p = Pattern.compile("a*b");
			 Matcher m = p.matcher("aaaaab");
			 boolean b = m.matches();
			 for oneshot use -->  boolean b = Pattern.matches("a*b", "aaaaab");
			 */
			if(dlna.rz_MetaMencoderOpt[0]!=null && dlna.rz_MetaMencoderOpt[0].indexOf("-sub ")>=0) {
				//PMS.dbg("-sub exists in MetaFile params, use_subs");
				use_subs=true;
			}
			if(dlna.rz_MetaMencoderOpt[1]!=null && dlna.rz_MetaMencoderOpt[1].indexOf("-sub ")>=0) {
				//PMS.dbg("-sub exists in MetaFile params, use_subs");
				use_subs=true;
			}
		}
		//PMS.dbg("use_subs="+use_subs);

		boolean judgeForRegza=params.mediaRenderer.isRZ_RemuxJudgeForRegza();
		boolean tsmuxable=false;
		if (true || judgeForRegza) {
			if(
				!forceMencoder
				&& !use_subs
				&& !dvd 
				&& !avisynth() 
				&& media != null 
				&& media.isMuxable(params.mediaRenderer)
				&& configuration.isMencoderMuxWhenCompatible() 
				&& (intOCW == 0 &&intOCH == 0)
				&& params.mediaRenderer.isRZ_NonTranscodeEx(width,height,aspect_f,dlna.getExt()==null?null:dlna.getExt().getMatchedId())		
			) tsmuxable=true;
			if(tsmuxable) {
				if(media.getCodecV().startsWith("h264") && params.mediaRenderer.isH264Level41Limited()) {
					//PMS.dbg("MEncoderVideo: getCodecV="+media.getCodecV());
					media.getH264Details(newInput,dlna);
					if(media.h264_level>41) {
						if(params.mediaRenderer.isRZ_AcceptH264L41Compatible()) {
							if(!media.h264_L41Compatible) tsmuxable=false;
						}
						else {
							tsmuxable=false;
						}
					}
				}
			}
		} 
		else {
			if(
				!forceMencoder &&
				params.sid == null &&
				!dvd &&
				!avisynth() &&
				media != null && (
					media.isVideoPS3Compatible(newInput,dlna) ||
					!params.mediaRenderer.isH264Level41Limited()
				) &&
				media.isMuxable(params.mediaRenderer) &&
				configuration.isMencoderMuxWhenCompatible() &&
				params.mediaRenderer.isMuxH264MpegTS() && (
					intOCW == 0 &&
					intOCH == 0
				) 
			) tsmuxable=true;
		}

		//--- extra judge for remux & capability
	    //--- shoud be better to do by TransScript, instead of hard-coding here!!
		//--- b/c condition may change by time
		/*
		if(media!=null && 
			(  media.getCodecV()==null
			|| media.getCodecV().startsWith("hevc") //H265
			|| media.getCodecV().contains("High 4:4:4")) ){
			//--- newer vcodec(h26X) : can't handle old ffmpeg,mencoder
			tsmuxable=false;
			mencoder_path=executable_in(dlna,1);  // need newer version
		}
		if(params.aid!=null && 
			(  params.aid.getCodecA().toLowerCase().startsWith("opus")
			|| params.aid.getCodecA().toLowerCase().startsWith("none")) ){
			//---- newer acodec :can't handle old ffmpeg,mencoder
			tsmuxable=false;
			mencoder_path=executable_in(dlna,1);
		}
		*/
			
		int ForcedTransType=dlna.getForcedTransType();
		int ForcedTransFormat=dlna.getForcedTransFormat();
		int ForcedTransProc=dlna.getForcedTransProc();
		if(PMS.rz_debug>1) {
			PMS.dbg("MencoderVideo: tsmuxable="+tsmuxable+", ForcedTransType="+ForcedTransType);
			PMS.dbg("MencoderVideo: rz_MetaTransType[0]="+dlna.rz_MetaTransType[0]);
			PMS.dbg("MencoderVideo: rz_MetaTransType[1]="+dlna.rz_MetaTransType[1]);
		}
		//---- regzamod End -----------------------
		
		//if(dlna.rz_MetaTransType!=PMS.ENC_TRANSCODE 
		//  && (tsmuxable || dlna.rz_MetaTransType==PMS.ENC_REMUX)) { 
		if(ForcedTransType!=PMS.ENC_TRANSCODE 
		  && (tsmuxable || ForcedTransType==PMS.ENC_REMUX)) { 
		  	//----------------------------------------------------------------
		  	// tsmuxable & not forced transcode
		  	//----------------------------------------------------------------
			boolean nomux = false;
			if(ForcedTransType==PMS.ENC_REMUX) {	//forced remux
				//Noop
			}
			else {
				//---- 1st call of getSpecificCodecOptions
				String opt=configuration.getCodecSpecificConfig();
				//String sArgs[] = getSpecificCodecOptions(configuration.getCodecSpecificConfig(), media, params, fileName, subString, configuration.isMencoderIntelligentSync(), false);
				String sArgs[] = getSpecificCodecOptions(opt, media, params, fileName, subString, 
					configuration.isMencoderIntelligentSync(), false, null);
				for (String s : sArgs) {
					if (s.equals("-nomux")) {
						nomux = true;
					}
					else if (s.equals("-nonomux")) {	// cansel nomux
						nomux = false;
					}
				}
			}
			if(!nomux) { //suitable or forced remux
				if(PMS.rz_debug>1) {
					PMS.dbg("MEncoderVideo: Exec REMUX by tsMuxer");	//regzamod
				}
					
				TSMuxerVideo tv = new TSMuxerVideo(configuration);
				params.forceFps = media.getValidFps(false);
				//if (media.getCodecV().equals("h264")) {
				if (media.getCodecV().startsWith("h264")) {	//regzamod, h264 may have subsequences
					params.forceType = "V_MPEG4/ISO/AVC";
				} else if (media.getCodecV().startsWith("mpeg2")) {
					params.forceType = "V_MPEG-2";
				} else if (media.getCodecV().equals("vc1")) {
					params.forceType = "V_MS/VFW/WVC1";
				}
				//PMS.dbg("MEncoderVideo: params.forceType=" + params.forceType);	//regzamod
				dlna.setEncMode(PMS.ENC_REMUX);	//regzamod, Remuxing by TsMuxer
				return tv.launchTranscode(fileName, dlna, media, params);
			}
			//PMS.dbg("MEncoderVideo: Failed Remux condition: nomux is true");	//regzamod

		} else if (params.sid == null && dvd && configuration.isMencoderRemuxMPEG2() 
		    && (params.mediaRenderer.isMpeg2Supported() || judgeForRegza)) {	
		    //------------------------------------------------------------------
		    // DVD remux 
		    //------------------------------------------------------------------
			String opt=configuration.getCodecSpecificConfig();
			if(dlna.rz_MetaMencoderOpt!=null) {
					//opt +="\nwidth > 0 :: "+dlna.rz_MetaMencoderOpt;
			}
			//---- 2nd call of getSpecificCodecOptions
			//String sArgs[] = getSpecificCodecOptions(configuration.getCodecSpecificConfig(), media, params, fileName, subString, configuration.isMencoderIntelligentSync(), false);
			String sArgs[] = getSpecificCodecOptions(opt, media, params, fileName, subString, 
				configuration.isMencoderIntelligentSync(), false, null);
			boolean nomux = false;
			for (String s : sArgs) {
				if (s.equals("-nomux")) {
					nomux = true;
				}
				else if (s.equals("-nonomux")) {	//cancel nomux
					nomux = false;
				}
			}
			if (!nomux) {
				ovccopy = true;
			}
			else if(judgeForRegza) {	//regzamod
				if(PMS.rz_debug>1) PMS.dbg("getSpecificCodecOptions insists nomux, But Anyway, force remux!!");	//regzamod
				ovccopy = true;		// force remux
			}
			if(zoom!=1.0 || shiftx!=0.0 || shifty!=0.0) {
				ovccopy = false;		// need transcode
			}
		}
		
		if(ovccopy) {
			dlna.setEncMode(PMS.ENC_REMUX);	//regzamod, remuxing by Mencoder
		}
		else {
			dlna.setEncMode(PMS.ENC_TRANSCODE);	//regzamod, Transcoding
		}
		if(PMS.rz_debug>1 && dvd) {
			PMS.dbg("MEncoderVideo: ==== Exec Transcoding by myself, video_remuxing="+ovccopy);	//regzamod
			PMS.dbg("MEncoderVideo: params.sid="+params.sid);	//regzamod
			PMS.dbg("MEncoderVideo: configuration.isMencoderRemuxMPEG2()="+configuration.isMencoderRemuxMPEG2());	//regzamod
			PMS.dbg("MEncoderVideo: mediaRenderer.isMpeg2Supported()="+params.mediaRenderer.isMpeg2Supported());	//regzamod
		}

		String vcodec = "mpeg2video";

		wmv = false;
		if (params.mediaRenderer.isTranscodeToWMV()) {
			wmv = true;
			vcodec = "wmv2"; // http://wiki.megaframe.org/wiki/Ubuntu_XBOX_360#MEncoder not usable in streaming
		}

		//--- judge transcode format, by regzamod
		int	trans_form;
		int trans_proc= 113;
		//boolean tx_m2ts=params.mediaRenderer.isRZ_TranscodeToM2ts();
		int useFFmpegMuxer=params.mediaRenderer.getRZ_UseFFmpegMuxer();	//regzamod, for test
		if(true) {
			trans_form=params.mediaRenderer.getRZ_TransVFormat();
		}
		else {
			//---- TranscodeVideo
			if(params.mediaRenderer.isTranscodeToMPEGPSAC3()){
				trans_form=MC_MPEGPS;
			}
			else {
				trans_form=MC_MPEGTS;
			}
			//---- Override by RZ_TransFormat
			if(true) {
				trans_form=params.mediaRenderer.getRZ_TransVFormat();
			}
			else {
				String form=params.mediaRenderer.getRZ_TransFormat();
				if(form.equals("mpegps")) {
					trans_form=MC_MPEGPS;
				}
				else if(form.equals("mpegts")) {	//mpegts by Mencoder only
					trans_form=MC_MPEGTS;
				}
				else if(form.equals("mpegts2")) {	//mpegts by tsMuxeR + Mencoder
					trans_form=MC_MPEGTS2;
				}
				else if(form.equals("m2ts")) {
					trans_form=MC_M2TS;
				}
			}
		}
		
		//---- override when specific case ---------------
		if(dlna.sotype==dlna.SO_DVDDEV && params.mediaRenderer.getRZ_TransFormatDVD().equals("mpegps")) {
			trans_form=MC_MPEGPS;
			//dlna.rz_MetaTransFormat=MC_MPEGPS;	// too late to set?
		}
		//if((!tx_m2ts && (media.isMpegTS() || dlna.isM2TS()))
		if(trans_form!=MC_M2TS && (media.isMpegTS() || dlna.isM2TS())) { //ts by mencoder+tsmuxer
			//convert ts/m2ts by Mencoder_only cause abnormal video/audio speed 
			//--> convert by Mencoder+TsMuxer 
			trans_form=MC_MPEGTS2;	// by Mencoder+TsMuxer
		}
		
		//---- override by rz_MetaTransFormat in pxm/pxf 
		//if(dlna.rz_MetaTransFormat>=0) {
		if(ForcedTransFormat>=0) {
			trans_form=ForcedTransFormat;
		}
		
		//---- set flags -----------------
		tx_m2ts=false;	//tsMuxer's output format(container_type)
		mpegts=false;	//mencoder's output format(container_type)
		if(trans_form==MC_MPEGTS || useFFmpegMuxer==1) {
			mpegts=true;	// ts by Mencoder only
		}
		else if(trans_form==MC_M2TS) {
			tx_m2ts=true;
		}
		
		//---- audio tracks -----------------
		int aid_num = -1;
		if(params.aid != null) {
			aid_num = params.aid.getId();
		}
		if(dlna.rz_MetaChannel_a>=0 && media != null) {	// forced audio_track
			if(dlna.rz_MetaChannel_a<media.getAudioCodes().size()) { //valid
				//aid_num = dlna.rz_MetaChannel_a-1;
				aid_num = media.getAudioCodes().get(dlna.rz_MetaChannel_a).getId();
			}
		}
		
		if(PMS.rz_debug>1) {
			PMS.dbg("MencoderVideo: isMpegTS="+media.isMpegTS()+", isM2TS="+dlna.isM2TS());
			PMS.dbg("MencoderVideo: trans_form="+trans_form+", tx_m2ts="+tx_m2ts+", mpegts="+mpegts);
			PMS.dbg("MencoderVideo: (trans_form: PS="+MC_MPEGPS+", TS="+MC_MPEGTS
				+", TS2="+MC_MPEGTS2+", M2TS="+MC_M2TS+")");
			PMS.dbg("MencoderVideo: aid_num="+aid_num);
		}

		oaccopy = false;
		if (configuration.isRemuxAC3() && params.aid != null && params.aid.isAC3() && !avisynth() && params.mediaRenderer.isTranscodeToAC3()) {
			oaccopy = true;
		}

		//---- dts embed/remux
		dtsEmbed = params.aid != null && params.aid.isDTS() 
			&& configuration.isDTSEmbedInPCM() 
			&& (!dvd || configuration.isMencoderRemuxMPEG2()) 
			&& !avisynth() && params.mediaRenderer.isDTSPlayable();
		dtsRemux=params.aid != null && params.aid.isDTS() 
			&& params.mediaRenderer.isDTSPlayable() && params.mediaRenderer.isMuxDTSToMpeg();
		
		//---- transcode to pcm
		pcmMod = (params.aid != null && (params.aid.isDTS() || params.aid.isLossless())) 
			&& configuration.isMencoderUsePcm() 
			&& (!dvd || configuration.isMencoderRemuxMPEG2()) 
			&& params.mediaRenderer.isMuxLPCMToMpeg();

		if (dtsRemux || pcmMod || pcmRaw) {
			if (dtsRemux) {
				oaccopy = true;
			}
			params.losslessaudio = true;
			params.forceFps = media.getValidFps(false);
		}

		// mpeg2 remux still buggy with mencoder :\
		if(PMS.rz_debug>1) {
			PMS.dbg("pcmMod="+pcmMod+", dtsRemux="+dtsRemux+", mux="+mux+", RZ_RemuxDvdAnyAudio="+params.mediaRenderer.isRZ_RemuxDvdAnyAudio());
		}
		if (!(pcmMod||pcmRaw) && !dtsRemux && !mux && ovccopy) {	
			ovccopy = false;
			if(params.mediaRenderer.isRZ_RemuxDvdAnyAudio()) {	//regzamod
				if(PMS.rz_debug>1) {
					PMS.dbg("==> Anyway, force Remux!!");
				}
				ovccopy = true;
			}
		}
		if(ForcedTransType==PMS.ENC_TRANSCODE) {
			ovccopy=false;
		}

		if ((pcmMod||pcmRaw) && avisynth()) {
			params.avidemux = true;
		}

		String add = "";
		if (configuration.getMencoderDecode() == null || configuration.getMencoderDecode().indexOf("-lavdopts") == -1) {
			add = " -lavdopts debug=0";
		}

		String alternativeCodec = "";//"-ac ffac3,ffdca, "; 
		if (dvd) {
			alternativeCodec = "";
		}
		int channels = wmv ? 2 : configuration.getAudioChannelCount();
		if (media != null && params.aid != null) {
			channels = wmv ? 2 : CodecUtil.getRealChannelCount(configuration, params.aid);
		}
		logger.trace("channels=" + channels);

		StringTokenizer st = new StringTokenizer(alternativeCodec + "-channels " + channels + " " + configuration.getMencoderDecode() + add, " ");
		overriddenMainArgs = new String[st.countTokens()];
		int i = 0;
		boolean processToken = false;
		int nThreads = (dvd || fileName.toLowerCase().endsWith("dvr-ms")) ?
			1 : configuration.getMencoderMaxThreads();

		while (st.hasMoreTokens()) {
			String token = st.nextToken().trim();
			if (processToken) {
				token += ":threads=" + nThreads;
				if (configuration.getSkipLoopFilterEnabled() && !avisynth()) {
					token += ":skiploopfilter=all";
				}
				processToken = false;
			}
			if (token.toLowerCase().contains("lavdopts")) {
				processToken = true;
			}

			overriddenMainArgs[i++] = token;
		}

		if (configuration.getMencoderMainSettings() != null) {
			String mainConfig = configuration.getMencoderMainSettings();
			if (params.mediaRenderer.getCustomMencoderQualitySettings() != null) {
				mainConfig = params.mediaRenderer.getCustomMencoderQualitySettings();
			}
			if (mainConfig.contains("/*")) // in case of
			{
				mainConfig = mainConfig.substring(mainConfig.indexOf("/*"));
			}

			// Ditlew - WDTV Live (+ other byte asking clients), CBR. This probably ought to be placed in addMaximumBitrateConstraints(..)
			int cbr_bitrate = params.mediaRenderer.getCBRVideoBitrate();
			String cbr_settings = (cbr_bitrate > 0) ? ":vrc_buf_size=1835:vrc_minrate=" + cbr_bitrate + ":vrc_maxrate=" + cbr_bitrate + ":vbitrate=" + cbr_bitrate : "";
			// regzamod, String encodeSettings = "-lavcopts autoaspect=1:vcodec=" + vcodec +
			
			 //String encodeSettings = "-lavcopts aspect="+ media.getValidAspect(true)+
			 
			 
			 String encodeSettings = "-lavcopts aspect="+ aspect_str +
			 	":vcodec=" + vcodec +
				(wmv ? ":acodec=wmav2:abitrate=448" : (cbr_settings + ":acodec=" + (configuration.isMencoderAc3Fixed() ? "ac3_fixed" : "ac3") +
				":abitrate=" + CodecUtil.getAC3Bitrate(configuration, params.aid))) +
				":threads=" + (wmv ? 1 : configuration.getMencoderMaxThreads()) + ":" + mainConfig;

			String audioType = "ac3";
			if (dtsRemux) {
				audioType = "dts";
			} else if (pcmMod||pcmRaw) {
				audioType = "pcm";
			}

			encodeSettings = addMaximumBitrateConstraints(encodeSettings, media, mainConfig, params.mediaRenderer, audioType);
			st = new StringTokenizer(encodeSettings, " ");
			int oldc = overriddenMainArgs.length;
			overriddenMainArgs = Arrays.copyOf(overriddenMainArgs, overriddenMainArgs.length + st.countTokens());
			i = oldc;
			while (st.hasMoreTokens()) {
				overriddenMainArgs[i++] = st.nextToken();
			}
		}

		boolean needAssFixPTS = false;

		boolean foundNoassParam = false;
		if (media != null) {
			String opt=configuration.getCodecSpecificConfig();
			if(dlna.rz_MetaMencoderOpt!=null) {
					//opt +="\nwidth > 0 :: "+dlna.rz_MetaMencoderOpt;
			}
			//---- 3rd call of getSpecificCodecOptions
			String sArgs [] = getSpecificCodecOptions(opt, media, params, fileName, subString, 
				configuration.isMencoderIntelligentSync(), false, null);
			//int ic=0; //regzamod
			for(String s:sArgs) {
				//PMS.dbg("sarg i="+ic+", val="+s);
				//ic++;
				if (s.equals("-noass")) {
					foundNoassParam = true;
				}
			}
		}

		StringBuilder sb = new StringBuilder();

		// Use ASS & Fontconfig flags (and therefore ASS font styles) for all subtitled files except vobsub, embedded, dvd and mp4 container with srt
		// Note: The MP4 container with SRT rule is a workaround for MEncoder r30369. If there is ever a later version of MEncoder that supports external srt subs we should use that. As of r32848 that isn't the case
		//regzamod , delete mp4 from exception
		if(PMS.rz_debug>1) {
			PMS.dbg("use_subs="+use_subs+", params.sid="+params.sid);
			if(params.sid!=null) PMS.dbg("sid.getType()="+params.sid.getType());
			PMS.dbg("DLNAMediaSubtitle.EMBEDDED="+DLNAMediaSubtitle.EMBEDDED);
			PMS.dbg("DLNAMediaSubtitle.VOBSUB="+DLNAMediaSubtitle.VOBSUB);
			PMS.dbg("DLNAMediaSubtitle.SUBRIP="+DLNAMediaSubtitle.SUBRIP);
			PMS.dbg("isMencoderDisableSubs()="+configuration.isMencoderDisableSubs());
			PMS.dbg("isMencoderAss()="+configuration.isMencoderAss());
			PMS.dbg("foundNoassParam="+foundNoassParam+", DVD="+dvd+", avisynth()="+avisynth());
		}
		
		
		if (
			/* origin
			&& (params.sid != null 
				params.sid.getType() != DLNAMediaSubtitle.EMBEDDED &&
				params.sid.getType() != DLNAMediaSubtitle.VOBSUB &&
				!(params.sid.getType() == DLNAMediaSubtitle.SUBRIP && media.getContainer().equals("mp4")
			)
			&& !dvd
			&& params.sid != null 
			*/
			use_subs 
			&& (
				params.sid==null || 
				( params.sid.getType() != DLNAMediaSubtitle.EMBEDDED
				  && params.sid.getType() != DLNAMediaSubtitle.VOBSUB )
			)
			&& configuration.isMencoderAss()
			&& !foundNoassParam
			&& !configuration.isMencoderDisableSubs()
			&& !avisynth()
		) {
			//PMS.dbg("use ASS=true");
			sb.append("-ass -").append(configuration.isMencoderFontConfig() ? "" : "no").append("fontconfig ");
			if (mpegts || wmv) {
				needAssFixPTS = Platform.isWindows(); // don't think the fixpts filter is in the mplayer trunk
			}
		}
		else {
			//PMS.dbg("use ASS=false");
		}

		// Apply DVD/VOBsub subtitle quality
		if (params.sid != null && params.sid.getType() == DLNAMediaSubtitle.VOBSUB && configuration.getMencoderVobsubSubtitleQuality() != null) {
			String subtitleQuality = configuration.getMencoderVobsubSubtitleQuality();

			sb.append("-spuaa ").append(subtitleQuality).append(" ");
		}

		// Apply overscan compensation
		// -vf scale to original resolution seems to fix most cases of video warping
		// TODO: Integrate with Video Scaler option
		if (intOCW > 0 || intOCH > 0) {
			String scaleAppend = "";

			if (media != null && media.getWidth() > 0 && media.getHeight() > 0) {
				scaleAppend = ",scale=" + media.getWidth() + ":" + media.getHeight();
			}

			sb.append("-vf softskip,expand=-").append(intOCW).append(":-").append(intOCH).append(scaleAppend).append(",harddup ");
		}

		//if (params.sid != null && !params.sid.isFileUtf8() && !configuration.isMencoderDisableSubs() 
		//	  && configuration.getMencoderSubCp() != null && configuration.getMencoderSubCp().length() > 0) {
			
		if (params.sid != null && /*!params.sid.isFileUtf8() &&*/ !configuration.isMencoderDisableSubs() 
			  && configuration.getMencoderSubCp() != null && configuration.getMencoderSubCp().length() > 0) {
		  	if(params.sid.isFileUtf8()) {
				sb.append("-subcp ").append("UTF-8").append(" ");
		  	}
		  	else {
				sb.append("-subcp ").append(configuration.getMencoderSubCp()).append(" ");
		  	}
			if (configuration.isMencoderSubFribidi()) {
				sb.append("-fribidi-charset ").append(configuration.getMencoderSubCp()).append(" ");
			}
		}

		if (!configuration.isMencoderDisableSubs() && !avisynth()) {
			if (configuration.getMencoderFont() != null && configuration.getMencoderFont().length() > 0) {
				sb.append("-subfont ").append(configuration.getMencoderFont()).append(" ");
			} else {
				String font = CodecUtil.getDefaultFontPath();
				if (StringUtils.isNotBlank(font)) {
					sb.append("-subfont ").append(font).append(" ");
				}
			}
			if (configuration.isMencoderAss() && !foundNoassParam) {
				if (!configuration.isMencoderAssDefaultStyle() || (subString != null && params.sid.getType() != DLNAMediaSubtitle.ASS)) {
					String assSubColor = "ffffff00";
					if (configuration.getSubsColor() != 0) {
						assSubColor = Integer.toHexString(configuration.getSubsColor());
						if (assSubColor.length() > 2) {
							assSubColor = assSubColor.substring(2) + "00";
						}
					}
					sb.append("-ass-color ").append(assSubColor).append(" -ass-border-color 00000000 -ass-font-scale ").append(configuration.getMencoderAssScale());
					sb.append(" -ass-force-style FontName=Arial,Outline=").append(configuration.getMencoderAssOutline()).append(",Shadow=").append(configuration.getMencoderAssShadow()).append(",MarginV=").append(configuration.getMencoderAssMargin()).append(" ");
				}
			} else {
				sb.append("-subfont-text-scale ").append(configuration.getMencoderNoAssScale());
				sb.append(" -subfont-outline ").append(configuration.getMencoderNoAssOutline());
				sb.append(" -subfont-blur ").append(configuration.getMencoderNoAssBlur());
				int subpos = 1;
				try {
					subpos = Integer.parseInt(configuration.getMencoderNoAssSubPos());
				} catch (NumberFormatException n) {
				}
				sb.append(" -subpos ").append(100 - subpos);
			}
		}

		st = new StringTokenizer(sb.toString(), " ");
		int oldc = overriddenMainArgs.length;
		overriddenMainArgs = Arrays.copyOf(overriddenMainArgs, overriddenMainArgs.length + st.countTokens());
		i = oldc;
		processToken = false;
		while (st.hasMoreTokens()) {
			String s = st.nextToken();
			if (processToken) {
				s = "-quiet";
				processToken = false;
			}
			//if ((!configuration.isMencoderAss() || dvd) && s.contains("-ass")) {
			if ((!configuration.isMencoderAss()) && s.contains("-ass")) {
				s = "-quiet";
				processToken = true;
			}
			overriddenMainArgs[i++] = s;
		}
		
		//---- default args fixed here 
		String cmdArray[] = new String[18 + args().length];
			

		cmdArray[0] = mencoder_path;

		// Choose which time to seek to
		cmdArray[1] = "-ss";
		if (params.timeseek > 0) {
			cmdArray[2] = "" + params.timeseek;
		} else {
			cmdArray[2] = "0";
		}
		cmdArray[3] = "-quiet";
		//if (media != null && media.getDvdtrack() > 0) {	//regzamod, this judge already setted to dvd
		if (dvd) {
			cmdArray[3] = "-dvd-device";
		}
		if (avisynth && !fileName.toLowerCase().endsWith(".iso")) {
			File avsFile = FFMpegVideo.getAVSScript(fileName, params.sid, params.fromFrame, params.toFrame);
			cmdArray[4] = ProcessUtil.getShortFileNameIfWideChars(avsFile.getAbsolutePath());
		} else {
			//cmdArray[4] = fileName;
			cmdArray[4] = shortFileName;
			if (params.stdin != null) {
				cmdArray[4] = "-";
			}
		}
		cmdArray[5] = "-quiet";
		//if (media != null && media.getDvdtrack() > 0) {
		if (dvd) {
			cmdArray[5] = "dvd://" + media.getDvdtrack();
			/* cause error
			if(dlna.rz_MetaDVDchapter!=null) {	//regzamod
				//what a terrible heavy way! is there any more smart way?
				cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 2);
				cmdArray[cmdArray.length - 4] = "-chapter";
				cmdArray[cmdArray.length - 3] = dlna.rz_MetaDVDchapter;
				PMS.dbg("dlna.rz_MetaDVDchapter="+dlna.rz_MetaDVDchapter+", cmdArray.length="+cmdArray.length);
				for(int j=0;j<cmdArray.length;j++) {
					PMS.dbg("cmdArray["+j+"]="+cmdArray[j]);
				}
			}
			*/
		}

		String arguments[] = args();
		for (i = 0; i < arguments.length; i++) {
			cmdArray[6 + i] = arguments[i];
			if (arguments[i].contains("format=mpeg2") && media.getAspect() != null && media.getValidAspect(true) != null) {
				if(!params.mediaRenderer.isRZ_ResizeForRegza()) {	//regzamod
					cmdArray[6 + i] += ":vaspect=" + media.getValidAspect(true);
				}
			}
		}

		cmdArray[cmdArray.length - 12] = "-quiet";
		cmdArray[cmdArray.length - 11] = "-quiet";
		cmdArray[cmdArray.length - 10] = "-quiet";
		cmdArray[cmdArray.length - 9] = "-quiet";
		if (!dtsRemux && !(pcmMod||pcmRaw) && !avisynth() && params.aid != null && media.getAudioCodes().size() > 1) {
			cmdArray[cmdArray.length - 12] = "-aid";
			boolean lavf = false; // Need to add support for LAVF demuxing
			//cmdArray[cmdArray.length - 11] = "" + (lavf ? params.aid.getId() + 1 : params.aid.getId());
			cmdArray[cmdArray.length - 11] = "" + (aid_num);
		}

		if (subString == null && params.sid != null) {
			cmdArray[cmdArray.length - 10] = "-sid";
			cmdArray[cmdArray.length - 9] = "" + params.sid.getId();
		} else if (subString != null && !avisynth()) { // Trick necessary for mencoder to skip the internal embedded track ?
			cmdArray[cmdArray.length - 10] = "-sid";
			cmdArray[cmdArray.length - 9] = "100";
		} else if (subString == null && !use_subs) { // Trick necessary for MEncoder to not display the internal embedded track
			cmdArray[cmdArray.length - 10] = "-subdelay";
			cmdArray[cmdArray.length - 9] = "20000";
		}

		cmdArray[cmdArray.length - 8] = "-quiet";
		cmdArray[cmdArray.length - 7] = "-quiet";

		if (configuration.isMencoderForceFps() && !configuration.isFix25FPSAvMismatch()) {
			cmdArray[cmdArray.length - 8] = "-fps";
			cmdArray[cmdArray.length - 7] = "24000/1001";
		}
		String forcefps_tsmuxer=null;	//regzamod
		cmdArray[cmdArray.length - 6] = "-ofps";
		cmdArray[cmdArray.length - 5] = "24000/1001";
		String frameRate = null;
		if (media != null) {
			frameRate = media.getValidFps(true);
		}
		if (frameRate != null) {
			cmdArray[cmdArray.length - 5] = frameRate;
			forcefps_tsmuxer=media.getValidFps(false);	//regzamod
			if (configuration.isMencoderForceFps()) {
				if (configuration.isFix25FPSAvMismatch()) {
					cmdArray[cmdArray.length - 8] = "-mc";
					cmdArray[cmdArray.length - 7] = "0.005";
					cmdArray[cmdArray.length - 5] = "25";
					forcefps_tsmuxer="25";	//regzamod
				} else {
					cmdArray[cmdArray.length - 7] = cmdArray[cmdArray.length - 5];
				}
			}
		}
		
		//--- regzamod add start , for not normal fps (10fps,12fps 15fps etc.) 
		else {	
			// not valid fps (for Mencoder)
			// In this case, Mencoder seems NOT convert fps at all, but set fps as if he converted!!
			// so, force real fps to tsMuxer
			if(media != null) {
				String fps_tx=media.getFrameRate();
				if(fps_tx!=null) {
					Double fps=Double.parseDouble(media.getFrameRate());
					if(fps<(Double)22.0) {
						logger.warn("MencoderVideo : Not normal fps="+fps_tx+" as for mpeg2, but go on as is.");
						//cmdArray[cmdArray.length - 5]= "10"; // fake up Mencoder !! bad for 15fps
						cmdArray[cmdArray.length - 5]= "15"; // fake up Mencoder !! good for all 10,12,15 fps
						forcefps_tsmuxer=media.getFrameRate();
					}
				}
			}
		}
		String fps_audio=null;
		if(forcefps_tsmuxer!=null) {
			fps_audio=forcefps_tsmuxer;	//regzamod, memory for later use on audio_extract
		}
		else {
			fps_audio=cmdArray[cmdArray.length - 5];	//regzamod, memory for later use on audio_extract
		}
		//PMS.dbg("fps_audio="+ofps_audio);
		//--- regzamod add end 

		if (subString != null && !configuration.isMencoderDisableSubs() && !avisynth()) {
			if (params.sid.getType() == DLNAMediaSubtitle.VOBSUB) {
				cmdArray[cmdArray.length - 4] = "-vobsub";
				cmdArray[cmdArray.length - 3] = subString.substring(0, subString.length() - 4);
				cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 2);
				cmdArray[cmdArray.length - 4] = "-slang";
				cmdArray[cmdArray.length - 3] = "" + params.sid.getLang();
			} else {
				cmdArray[cmdArray.length - 4] = "-sub";
				cmdArray[cmdArray.length - 3] = subString.replace(",", "\\,"); // commas in mencoder separates multiple subtitles files
				//if (false && params.sid.isFileUtf8() && params.sid.getPlayableFile() != null) {
				if (false && params.sid.isFileUtf8() && params.sid.getPlayableFile() != null) { 
					//regzam, seems only have bad effects
					cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 1);
					cmdArray[cmdArray.length - 3] = "-utf8";
				}
			}
		} else {
			cmdArray[cmdArray.length - 4] = "-quiet";
			cmdArray[cmdArray.length - 3] = "-quiet";
		}

		if (fileName.toLowerCase().endsWith(".evo")) {
			cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 2);
			cmdArray[cmdArray.length - 4] = "-psprobe";
			cmdArray[cmdArray.length - 3] = "10000";
		}

		if (needAssFixPTS) {
			cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 2);
			cmdArray[cmdArray.length - 4] = "-vf";
			cmdArray[cmdArray.length - 3] = "ass,fixpts";
		}

		boolean deinterlace = configuration.isMencoderYadif();
		// check if the media renderer supports this resolution
		boolean mediaRendererScaler = params.mediaRenderer.isVideoRescale() && media != null && (media.getWidth() > params.mediaRenderer.getMaxVideoWidth() || (media.getHeight() > params.mediaRenderer.getMaxVideoHeight()));
		// use scaler?
		boolean scaleBool = mediaRendererScaler || (configuration.isMencoderScaler() && (configuration.getMencoderScaleX() != 0 || configuration.getMencoderScaleY() != 0));
		
		if(dvd) {
			if(params.mediaRenderer.getRZ_ForceResizeDVD()==0) {
				//ForceResizeDVD no-ways
				scaleBool=false;
			}
			else if(params.mediaRenderer.getRZ_ForceResizeDVD()==1) {
				//ForceResizeDVD when no_subs
				if(use_subs) scaleBool=false;
			}
		}
		
		if ((deinterlace || scaleBool) && !avisynth()) {
			String scalerString;
			cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 2);
			cmdArray[cmdArray.length - 4] = "-vf";

			//---- regzamod change Start ------------
			if(params.mediaRenderer.isRZ_ResizeForRegza()) {	
				//----------------------------------------------------
				// Specific way of resizing for REGZA:
				// REGZA can't disp when aspectRatio isn't 4v3 or 16v9
				// so, make aspectRatio become 4v3 or 16v9 by adding borders
				//----------------------------------------------------
				
				//int ew=(params.mediaRenderer.getMaxVideoWidth() > 0 ? params.mediaRenderer.getMaxVideoWidth() : configuration.getMencoderScaleX());
				//int eh=(params.mediaRenderer.getMaxVideoHeight() > 0 ? params.mediaRenderer.getMaxVideoHeight() : configuration.getMencoderScaleY());
				int sw=ew,sh=eh,expf=0,cropf=0;
				
				if(aspect_f > aspect_d) {	// wider than disp area
					expf=1;	//need expand
					sw=ew;
					sh= (int)((float)eh*aspect_d/aspect_f);
				}
				else if(aspect_f < aspect_d){	//narrower than disp_area
					expf=1;	//need expand
					sh=eh;
					sw=(int)((float)ew*aspect_f/aspect_d);
				}
				
				if(zoom<1.4) {
					//---- type1 :zoom by scale
					//type2(zoom by crop) cause abnormal cropping when zoom>1.0 to <1.4, why? 
					//use type1(zoom by scale)
					sw=(int)(sw*zoom);
					sh=(int)(sh*zoom);
					//-- force even value
					sw=(sw+1)/2*2;
					sh=(sh+1)/2*2;
					if(zoom>1.0 || shiftx!=0 || shifty!=0) {
						//need wider area than source
						cropf=1;
						double cw=ew;
						double ch=eh;
						double ew2=(ew*2.0);	
						double eh2=(eh*2.0);
						double bx=((ew2-cw)/2.0);
						double by=((eh2-ch)/2.0);
						//float by=0;
						bx -= ew*shiftx/100.0;
						by += eh*shifty/100.0;	
						scalerString="scale="+sw+":"+sh
							+",expand="+(int)ew2+":"+(int)eh2
							+",crop="+(int)cw+":"+(int)ch+":"+(int)bx+":"+(int)by
							+",expand="+ew+":"+eh;
					}
					else {	// only zoom (no shift)
						scalerString="scale="+sw+":"+sh;
						if(expf>0) {
							scalerString +=",expand="+ew+":"+eh;
						}
					}
				}
				else if(zoom>1 || shiftx!=0 || shifty!=0) {
					//---- type2 :zoom by crop
					//cropping may be light cpu-load than scale
					double cw=ew/(sw*zoom)*width;
					double ch=eh/(sh*zoom)*height;
					sw=ew;	// must after calc cw 
					sh=eh;
					//-- force even value
					sw=(sw+1)/2*2;
					sh=(sh+1)/2*2;
					
					//---- expand canvas, to avoid error when crop rectangle exceed the origin rect
					double ew2=(width*2.0);	
					double eh2=(height*2.0);
					
					//---- crop at center
					double bx=((ew2-cw)/2.0);
					double by=((eh2-ch)/2.0);
					
					//---- crop at center+shift
					if(shiftx!=0) bx -= ew/zoom*shiftx/100.0;
					if(shifty!=0) by += eh/zoom*shifty/100.0;	
					scalerString="expand="+(int)ew2+":"+(int)eh2
						+",crop="+(int)cw+":"+(int)ch+":"+(int)bx+":"+(int)by
						+",scale="+sw+":"+sh;
				}
				else {
					//-- force even value
					sw=(sw+1)/2*2;
					sh=(sh+1)/2*2;
					//---- type3: no zoom & no shift
					scalerString="scale="+sw+":"+sh;
					if(expf>0) {
						scalerString +=",expand="+ew+":"+eh;
					}
				}
				if(PMS.rz_debug>1) {
					PMS.dbg("zoom="+zoom+", expf="+expf+", cropf="+cropf+", aspect_f="+aspect_f
						+", aspect_d="+aspect_d+", crop="+crop_str+", scale="+sw+"x"+sh+", expand="+ew+"x"+eh);
					PMS.dbg("scale_str: "+scalerString);
				}
			}
			else {	// Original way
				scalerString = "scale=" + (params.mediaRenderer.getMaxVideoWidth() > 0 ? params.mediaRenderer.getMaxVideoWidth() : configuration.getMencoderScaleX()) + ":" + (params.mediaRenderer.getMaxVideoHeight() > 0 ? params.mediaRenderer.getMaxVideoHeight() : configuration.getMencoderScaleY());
			}
			//---- regzamod change End ---------------
			
			if (deinterlace) {
				scalerString = "," + scalerString;
			}
			cmdArray[cmdArray.length - 3] = (deinterlace ? "yadif" : "") + (scaleBool ? scalerString : "");
			
		}

		if (configuration.getMencoderMT() && !avisynth && !dvd && !(media.getCodecV() != null && (media.getCodecV().equals("mpeg2video")))) {
			cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 2);
			cmdArray[cmdArray.length - 4] = "-lavdopts";
			cmdArray[cmdArray.length - 3] = "fast";
		}

		scAddOpts addopts=new scAddOpts();  //pms special options

		//---- process additional options from PMS.conf/Renderer.conf/pxf/pxm
		if (media != null) {
			//---- codec_specific_config in PMS.conf
			String opt="";
			String opt1=configuration.getCodecSpecificConfig();			//from PMS.conf
			if(opt1!=null) opt=opt1;
			
			//---- option params from pxf/pxm/script
			String opt_add="";
			//String script=params.sess.scex.getRz_TransOptScript(2); //get only normal scripts
			if(script_pos==2) {  // exec later 
				if(PMS.rz_is_rend_script_enabled && params.sess.scex!=null) {
					//Remux container format & specific options
					int trans_format=params.mediaRenderer.getRZ_TransVFormat();
					//---- override by rz_MetaTransFormat in pxm/pxf 
					if(dlna.getForcedRemuxFormat()>=0) {
						trans_format=dlna.getForcedTransFormat();
					}
					
					rz_ScriptExecutor.medAddOpts spec_addopts=new rz_ScriptExecutor.medAddOpts();
					spec_addopts.player=this.toString();
					//spec_addopts.trans_type=rz_ScriptExecutor.trans_type_int2string(PMS.ENC_TRANSCODE);
					spec_addopts.trans_type=rz_ScriptExecutor.trans_type_int2string(dlna.getEncMode());
					spec_addopts.trans_format=rz_ScriptExecutor.trans_format_int2string(trans_format);

					//execScripts(type,when,taget,dlna,..)
					// int type;	//=1:load,=2:exec
					// int when;	//=1:list,=2:play,  =3:list|play,  =4:oneshot
					// int target;	//=1:file,=2:folder,=3:file|folder,=4:other

					params.sess.scex.execScripts(2,2,1,dlna,dlna.getSrcPath(),params,spec_addopts);
					//if(dlna.rz_MetaMencoderOpt[1]!=null) {		//from scripts
					//	opt_add +=dlna.rz_MetaMencoderOpt[1];
					//}
				}
			}
			
			if(dlna.rz_MetaMencoderOpt[1]!=null) {		//from scripts
				opt_add +=dlna.rz_MetaMencoderOpt[1];
			}
			if(dlna.rz_MetaMencoderOpt[0]!=null) {		//from pxf/pxm
				opt_add +=dlna.rz_MetaMencoderOpt[0];
			}
			if(dlna.rz_MetaSoundVolume>=0) {
				opt_add +=" -af volume="+Math.log10((double)dlna.rz_MetaSoundVolume/100.0)*20.0;
			}
			if(opt_add.length()>0) {
				opt += "\n true :: "+opt_add;
			}
			
			//need  AFTER execScripts AND BEFORE mencoder params judge
			ForcedTransProc=dlna.getForcedTransProc();  //re-get after execScripts
			if (ForcedTransProc>0) {
				trans_proc=ForcedTransProc;
			}
			else if(useFFmpegMuxer!=0) {
					trans_proc=112;
			}
			else if((trans_form==MC_M2TS || trans_form==MC_MPEGTS2)
				 || (pcmMod||pcmRaw||dtsRemux||dtsEmbed||mux) ) {
					trans_proc=113;
			}
			else {
					trans_proc=111;
			}
			if(trans_proc==112) {
				if(PMS.rz_debug>1) {
					PMS.dbg("MencoderVideo: Using ffmpeg for Muxer, instead of TsMuxer");
					PMS.dbg("---> This ia TestMode: may not work well!!");
				}
			}
			
			if(true) {
				// need change speed ONLY for Video, widthout Audio!!
				// i.e. need designate valid vid by -vid
				//PMS.dbg("For TEST !! isMpegTS()="+media.isMpegTS()+", isM2TS()="+dlna.isM2TS()
				//	+"speed="+params.mediaRenderer.getRZ_MpegtsFpsMnt());
				
				if((media.isMpegTS() || dlna.isM2TS()) && params.mediaRenderer.getRZ_MpegtsFpsMnt()>0) {
					//PMS.dbg("MencoderVideo : set -speed "+params.mediaRenderer.getRZ_MpegtsFpsMnt());
					opt +="\n true :: -speed "+params.mediaRenderer.getRZ_MpegtsFpsMnt();
					if(dlna.isM2TS()) {  //really?
						params.timeseek /=params.mediaRenderer.getRZ_MpegtsFpsMnt();
					}
				}
			}
			
			//---- final call of getSpecificCodecOptions
			if(opt.length()>0) {
				String sArgs[] = getSpecificCodecOptions(opt, media, params, fileName, subString, 
					configuration.isMencoderIntelligentSync(), false, addopts);
				//PMS.dbg("MetaMencoderOpt="+dlna.rz_MetaMencoderOpt);
				//PMS.dbg("opt="+opt);
				if(PMS.rz_debug>1) {
					PMS.dbg("MencoderVideo: additional options="+opt);
					PMS.dbg("MencoderVideo: additional sArgs[]="+Arrays.toString(sArgs));
				}
				
				if (sArgs != null && sArgs.length > 0) {
					boolean vfConsumed = false;
					boolean afConsumed = false;
					for (int s = 0; s < sArgs.length; s++) {
						if (sArgs[s].equals("-noass")) {
							for (int c = 0; c < cmdArray.length; c++) {
								if (cmdArray[c] != null && cmdArray[c].equals("-ass"))
								{
									cmdArray[c] = "-quiet";
								}
							}
						} else if (sArgs[s].equals("-ofps")) {
							if(s < sArgs.length-1) {//regzamod 
								fps_audio=sArgs[s+1];
								forcefps_tsmuxer=sArgs[s+1];	
								//PMS.dbg("fps_audio="+fps_audio);
							}
							for (int c = 0; c < cmdArray.length; c++) {
								if (cmdArray[c] != null && cmdArray[c].equals("-ofps")) {
									cmdArray[c] = "-quiet";
									cmdArray[c + 1] = "-quiet";
									s++;
								}
							}
						} else if (sArgs[s].equals("-fps")) {
							for (int c = 0; c < cmdArray.length; c++) {
								if (cmdArray[c] != null && cmdArray[c].equals("-fps")) {
									cmdArray[c] = "-quiet";
									cmdArray[c + 1] = "-quiet";
									s++;
								}
							}
						} else if (sArgs[s].equals("-of")) {	//regzamod, add
							if(sArgs[s+1].equals("rawvideo")) {
								rawvideo=true;
							}
							for (int c = 0; c < cmdArray.length; c++) {
								if (cmdArray[c] != null && cmdArray[c].equals("-of")) {
									cmdArray[c] = "-quiet";
									cmdArray[c + 1] = "-quiet";
									s++;
								}
							}
						} else if (sArgs[s].equals("-ovc")) {
							for (int c = 0; c < cmdArray.length; c++) {
								if (cmdArray[c] != null && cmdArray[c].equals("-ovc")) {
									cmdArray[c] = "-quiet";
									cmdArray[c + 1] = "-quiet";
									s++;
								}
							}
						} else if (sArgs[s].equals("-channels")) {
							for (int c = 0; c < cmdArray.length; c++) {
								if (cmdArray[c] != null && cmdArray[c].equals("-channels")) {
									cmdArray[c] = "-quiet";
									cmdArray[c + 1] = "-quiet";
									s++;
								}
							}
						} else if (sArgs[s].equals("-oac")) {
							force_oac=true;
							if(sArgs[s+1].equals("copy")) {
								//force_oaccopy=true;
							}
							for (int c = 0; c < cmdArray.length; c++) {
								if (cmdArray[c] != null && cmdArray[c].equals("-oac")) {
									cmdArray[c] = "-quiet";
									cmdArray[c + 1] = "-quiet";
									s++;
								}
							}
						} else if (sArgs[s].equals("-nosound")) {
							force_nosound=true;
						} else if (sArgs[s].equals("-quality")) {
							for (int c = 0; c < cmdArray.length; c++) {
								if (cmdArray[c] != null && cmdArray[c].equals("-lavcopts")) {
									cmdArray[c + 1] = "autoaspect=1:vcodec=" + vcodec +
										":acodec=" + (configuration.isMencoderAc3Fixed() ? "ac3_fixed" : "ac3") +
										":abitrate=" + CodecUtil.getAC3Bitrate(configuration, params.aid) +
										":threads=" + configuration.getMencoderMaxThreads() + ":" + sArgs[s + 1];
									addMaximumBitrateConstraints(cmdArray[c + 1], media, cmdArray[c + 1], params.mediaRenderer, "");
									sArgs[s + 1] = "-quality";
									s++;
								}
							}
						} else if (sArgs[s].equals("-mpegopts")) {
							for (int c = 0; c < cmdArray.length; c++) {
								if (cmdArray[c] != null && cmdArray[c].equals("-mpegopts")) {
									cmdArray[c + 1] += ":" + sArgs[s + 1];
									sArgs[s + 1] = "-mpegopts";
									s++;
								}
							}
						} else if (sArgs[s].equals("-vf")) {
							//PMS.dbg("-vf found, next sArgs[s]="+sArgs[s+1]);
							for (int c = 0; c < cmdArray.length; c++) {
								if (cmdArray[c] != null && cmdArray[c].equals("-vf")) {
									cmdArray[c + 1] += "," + sArgs[s + 1];
									sArgs[s + 1] = "-vf";
									s++;
									vfConsumed = true;
								}
							}
						} else if (sArgs[s].equals("-af")) {
							for (int c = 0; c < cmdArray.length; c++) {
								if (cmdArray[c] != null && cmdArray[c].equals("-af")) {
									cmdArray[c + 1] += "," + sArgs[s + 1];
									sArgs[s + 1] = "-af";
									s++;
									afConsumed = true;
								}
							}
						} else if (sArgs[s].equals("-nosync")) {
							noMC0NoSkip = true;
						} else if (sArgs[s].equals("-mc")) {
							noMC0NoSkip = true;
						}
						else if(sArgs[s].equals("-oac_copy")){	//regzamod
							force_oaccopy=true;
							sArgs[s]="-quiet";
						}
						else if(sArgs[s].equals("-pcm_mod")){	//regzamod
							force_pcmmod=true;
							sArgs[s]="-quiet";
						}
						else if(sArgs[s].equals("-pcm_raw")){	//regzamod
							force_pcmraw=true;
							sArgs[s]="-quiet";
						}
						else if(sArgs[s].equals("-dts_embed")){	//regzamod
							if(PMS.rz_debug>1) PMS.dbg("MencoderVideo: -dts_embed: found in opt_args!!");
							force_dtsembed=true;
							sArgs[s]="-quiet";
						}
						else if(sArgs[s].equals("-dts_remux")){	//regzamod
							force_dtsremux=true;
							sArgs[s]="-quiet";
						}
					}
					cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + sArgs.length);
					for (int s = 0; s < sArgs.length; s++) {
						if (sArgs[s].equals("-noass") || sArgs[s].equals("-nomux") || sArgs[s].equals("-nonomux")|| sArgs[s].equals("-mpegopts") || (sArgs[s].equals("-vf") & vfConsumed) || (sArgs[s].equals("-af") && afConsumed) || sArgs[s].equals("-quality") || sArgs[s].equals("-nosync") || sArgs[s].equals("-mt")) {
							cmdArray[cmdArray.length - sArgs.length - 2 + s] = "-quiet";
						} else {
							cmdArray[cmdArray.length - sArgs.length - 2 + s] = sArgs[s];
						}
					}
				}
			}
		}
		//---- End of process additional options

		if ((pcmMod || pcmRaw || dtsRemux || mux) || (configuration.isMencoderNoOutOfSync() && !noMC0NoSkip)) {
			cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 3);
			cmdArray[cmdArray.length - 5] = "-mc";
			cmdArray[cmdArray.length - 4] = "0";
			cmdArray[cmdArray.length - 3] = "-noskip";
			if (configuration.isFix25FPSAvMismatch()) {
				cmdArray[cmdArray.length - 4] = "0.005";
				cmdArray[cmdArray.length - 3] = "-quiet";
			}
		}

		if (params.timeend > 0) {
			if(PMS.rz_debug>1) PMS.dbg("MencoderVideo: params.timeend>0 ("+params.timeend+") -->set -endpos");
			cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 2);
			cmdArray[cmdArray.length - 4] = "-endpos";
			cmdArray[cmdArray.length - 3] = "" + params.timeend;
		}

		String rate = "48000";
		if (params.mediaRenderer.isXBOX()) {
			rate = "44100";
		}

		// force srate -> cause ac3's mencoder doesn't like anything other than 48khz
		if (media != null && !(pcmMod||pcmRaw) && !dtsRemux && !mux) {
			cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 4);
			cmdArray[cmdArray.length - 6] = "-af";
			cmdArray[cmdArray.length - 5] = "lavcresample=" + rate;
			cmdArray[cmdArray.length - 4] = "-srate";
			cmdArray[cmdArray.length - 3] = rate;
		}

		// add a -cache option for piped media (e.g. rar/zip file entries):
		// https://code.google.com/p/ps3mediaserver/issues/detail?id=911
		if (params.stdin != null) {
			cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 2);
			cmdArray[cmdArray.length - 4] = "-cache";
			cmdArray[cmdArray.length - 3] = "8192";
		}
		
		if (dvd) {
			if(dlna.rz_MetaDVDchapter!=null) {	//regzamod
				//what a terrible heavy way! is there any more smart way?
				cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 2);
				cmdArray[cmdArray.length - 4] = "-chapter";
				cmdArray[cmdArray.length - 3] = dlna.rz_MetaDVDchapter;
				/*
				//PMS.dbg("dlna.rz_MetaDVDchapter="+dlna.rz_MetaDVDchapter+", cmdArray.length="+cmdArray.length);
				for(int j=0;j<cmdArray.length;j++) {
					//PMS.dbg("cmdArray["+j+"]="+cmdArray[j]);
				}
				*/
			}
		}
		//---- pre-process mencoder_opta 
		String opt="";
		String[] mencoderOptA=null;
		if(dlna.rz_MetaMencoderOptA[1]!=null) {	// from script
			opt+=" "+dlna.rz_MetaMencoderOptA[1];
		}
		if(dlna.rz_MetaMencoderOptA[0]!=null) {	// from pxf/pxm
			opt+=" "+dlna.rz_MetaMencoderOptA[0];
		}
		if(opt.length()>0) {	//audio options
			String[] opts=opt.split("\\s");
			mencoderOptA=opts;
			for (int s = 0; s < opts.length; s++) {
				if(opts[s].equals("-oac")) {
					if(opts[s+1].equals("copy")) {
						force_oaccopy=true;
					}
				}
			}
		}
		
		//---- Last Judge & final args
		if(force_pcmmod) pcmMod=true;
		if(force_pcmraw) pcmRaw=true;
		if(force_dtsremux) dtsRemux=true;
		if(force_dtsembed) dtsEmbed=true;
		
		PipeProcess main_pipe = null;
		cmdArray[cmdArray.length - 2] = "-o";
		ProcessWrapperImpl pw = null;
		
		//need  for No Mediainfo Object (is exsist really?)
		ForcedTransProc=dlna.getForcedTransProc();  //re-get after execScripts
		if (ForcedTransProc>0) {
			trans_proc=ForcedTransProc;
		}
		else if(useFFmpegMuxer!=0) {
				trans_proc=112;
		}
		else if((trans_form==MC_M2TS || trans_form==MC_MPEGTS2)
			 || (pcmMod||pcmRaw||dtsRemux||dtsEmbed||mux) ) {
				trans_proc=113;
		}
		else {
				trans_proc=111;
		}
		if(trans_proc==112) {
			logger.warn("MencoderVideo: Using ffmpeg for Muxer, instead of TsMuxer");
			logger.warn("---> This ia TestMode: may not work well !!");
		}

		
		//-----------------------------------------------------------------------------------------------
		// Last: Now all given-parameters should be fixed.
		// Let's Begin transcode
		//-----------------------------------------------------------------------------------------------
		if(PMS.rz_debug>1) {
			PMS.dbg("trans_form="+trans_form
				+", trans_proc="+trans_proc
				+", pcmMod="+pcmMod
				+", pcmRaw="+pcmRaw
				+", dtsEmbed="+dtsEmbed
				+", dtsRemux="+dtsRemux
				+", oaccopy="+oaccopy
				+", force_oaccopy="+force_oaccopy
				+", force_pcmmod="+force_pcmmod
				+", force_pcmraw="+force_pcmraw
				+", force_dtsembed="+force_dtsembed
				+", force_dtsremux="+force_dtsremux
				);
		}
		
		if (trans_proc==113) {
			//-------------------------------------------------------------------------
			//	transproc type-1 (trans to ts/m2ts by Mencoder + tsMuxer)
			//-------------------------------------------------------------------------
			if(PMS.rz_debug>1) PMS.dbg("---- MencoderVideo: trasco type-1 (trans to ts/m2ts by Mencoder+TsMuxer)");
			boolean channels_filter_present = false;
			for (String s : cmdArray) {
				if (StringUtils.isNotBlank(s) && s.startsWith("channels")) {
					channels_filter_present = true;
					break;
				}
			}

			if (params.avidemux) {
				//-------------------------------------------------------------------------
				//	transproc type-1-1 use avidemux??
				//-------------------------------------------------------------------------
				if(PMS.rz_debug>1) PMS.dbg("---- MencoderVideo: trasco type-1-1");
				main_pipe = new PipeProcess("mencoder" + System.currentTimeMillis(), (pcmMod||dtsRemux||dtsEmbed||mux) ? null : params);
				params.input_pipes[0] = main_pipe;
				cmdArray[cmdArray.length - 1] = main_pipe.getInputPipe();

				if (pcmMod && !channels_filter_present) {
					cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 2);
					cmdArray[cmdArray.length - 2] = "-af";
					cmdArray[cmdArray.length - 1] = CodecUtil.getMixerOutput(true, configuration.getAudioChannelCount());
				}

				pw = new ProcessWrapperImpl(cmdArray, params);

				PipeProcess videoPipe = new PipeProcess("videoPipe" + System.currentTimeMillis(), "out", "reconnect");
				PipeProcess audioPipe = new PipeProcess("audioPipe" + System.currentTimeMillis(), "out", "reconnect");

				ProcessWrapper videoPipeProcess = videoPipe.getPipeProcess();
				ProcessWrapper audioPipeProcess = audioPipe.getPipeProcess();

				params.output_pipes[0] = videoPipe;
				params.output_pipes[1] = audioPipe;

				pw.attachProcess(videoPipeProcess);
				pw.attachProcess(audioPipeProcess);
				videoPipeProcess.runInNewThread();
				audioPipeProcess.runInNewThread();
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
				}
				videoPipe.deleteLater();
				audioPipe.deleteLater();
			} else {
				//-------------------------------------------------------------------------
				//	transproc type-1-2: (Trans to ts/m2ts)
				//-------------------------------------------------------------------------
				if(PMS.rz_debug>1) PMS.dbg("---- MencoderVideo: trasco type-1-2: (Trans to ts/m2ts by Mencoder+TsMuxer)");
				//---- regzamod2 start
				boolean seekmnt=media.isMpegTS(); //container==m2ts,ts
				double	timeseek_v=0;
				double	timeseek_a=0;
				double	endpos=0;
				double  rewind=0;
				double  sound_delay=0;
				double	sound_delay_mc=0;	//sound delay by mencoder (sec)
				double	sound_delay_ts=0;	//sound delay by tsMuxer(msec)
				boolean	sound_delay_by_mencoder=false; // timeshift(sound delay) by TsMuxer
				double	start_skip=0;	//start from (msec) when directed play from top
			  	String[] fparams=PMSUtil.rz_getFnameParams(fileName);
				
				if(params.timeseek>0) {
					// tuning param for video delay on pause/restart/skip on REMUX
					if(seekmnt) {//regzamod
						rewind=params.mediaRenderer.getRZ_TransRestartRewind();
						sound_delay=params.mediaRenderer.getRZ_TransAudioDelayRestartTs();
						//timeseek_v=(params.timeseek -rewind)/2.0;
						//timeseek_a=(params.timeseek -rewind)/2.0;
						timeseek_v=(params.timeseek -rewind);
						timeseek_a=(params.timeseek -rewind);
						if(params.mediaRenderer.isRZ_TransAudioDelayByTimeSeek()){
							//timeseek_a=(params.timeseek -rewind - sound_delay)/2.0;
							timeseek_a=(params.timeseek -rewind - sound_delay);
							sound_delay=0;	//done
						}
						//PMS.dbg("timeseek rewind="+rewind+", sound_delay="+sound_delay);
					}
					else {
						timeseek_v=params.timeseek;
						timeseek_a=params.timeseek;
					}
					/*
					if(dlna.rz_SoundDelay!=0) {	//by Metafile param
						sound_delay=dlna.rz_SoundDelay;
					}
					*/
					cmdArray[2] = "" + timeseek_v;
				}
				else {	//play from top
			  		if((start_skip=params.mediaRenderer.getRZ_TransStartSkip())!=0) {
		  		  		//skip when playstart from top
						//PMS.dbg("getRZ_TransStartSkip="+start_skip+" msec");
						timeseek_v=start_skip;
						timeseek_a=start_skip;
						cmdArray[2] = "" + timeseek_v;
			  		}
	  				double delay=params.mediaRenderer.getRZ_TransAudioDelayStart();
	  				if(delay!=0) {
	  					sound_delay +=delay/1000.0;  //conv msec to secs
					}
					/*
					if(dlna.rz_SoundDelay!=0) {	//by Metafile param
						sound_delay +=dlna.rz_SoundDelay;	//secs
					}
					*/
				}
				
				//---- sound_delay by constant_delay in renderer.conf
				if(params.mediaRenderer.getRZ_TransAudioDelay()!=0) {	//RZ_TransAudioDelay in renderer.conf
					sound_delay +=params.mediaRenderer.getRZ_TransAudioDelay();
				}
				//---- sound_delay by conditional codecSpacificpts in renderer.conf
				//PMS.dbg("MencoderVideo: addopts adelay_add="+addopts.adelay_add+", adelay_rep="+addopts.adelay_rep);
				if(addopts.adelay_add!=null) {
					sound_delay+=addopts.adelay_add;
				}
				if(addopts.adelay_rep!=null) {
					sound_delay =addopts.adelay_rep;
				}
				
				//---- sound_delay by pxm/pxf/script
				sound_delay +=dlna.getForcedSoundDelay();	//secs
				if(sound_delay!=0) {
					if(sound_delay_by_mencoder) {
						sound_delay_mc=sound_delay;
					}
					else {
						sound_delay_ts=sound_delay;
					}
				}
				if(sound_delay_mc!=0) {
					cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 2);
					cmdArray[cmdArray.length - 4] = "-delay";	// minus means video delay
					cmdArray[cmdArray.length - 3] = ""+ (sound_delay_mc);
					cmdArray[cmdArray.length - 2] = "-o";
				}
				//---- play strat/end pos designated in filename_params
				// start pos will be present at params.timeseek: already done
				//if(dlna.getSplitRange().isEndLimitAvailable()) {
				if(dlna.rz_isPartPlay) {
					//endpos=dlna.getSplitRange().getEnd();
					//endpos=endpos-timeseek_v;	//mencoder's endpos is duration!!
					endpos=dlna.rz_PartPlayDuration;
					if(endpos>0) {
						//PMS.dbg("MencoderVideo: set video endpos="+endpos);
						cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 2);
						cmdArray[cmdArray.length - 4] = "-endpos";	// end time for video
						cmdArray[cmdArray.length - 3] = ""+endpos;
						cmdArray[cmdArray.length - 2] = "-o";
					}
				}	
				//---- regzamod2 end 

				// remove the -oac switch, otherwise too many video packets errors appears again
				// On some cases, "-oac copy" make better than "-nosound" as for A/V sync , 
				// but may cause block noizing and or more heavy async.
				// so really, the merits to use "-oac copy" less than the demerits
				//boolean need_nosound=media.isMpegTS() || (params.aid!=null && params.aid.isWMA());
				//boolean can_acopy=!media.isMpegTS() && params.aid!=null && (params.aid.isMP3() || params.aid.isAC3());
				//boolean can_acopy=!media.isMpegTS() && params.aid!=null && (params.aid.isMP3());
				boolean can_acopy=false;
				for (int s = 0; s < cmdArray.length; s++) {
					/*
					if (cmdArray[s]!=null && (cmdArray[s].equals("-oac")||cmdArray[s].equals("-aid"))) {
						cmdArray[s] = "-nosound";
						cmdArray[s + 1] = "-nosound";
						//break;
					}
					*/
					if (cmdArray[s]!=null) {
						if(cmdArray[s].equals("-oac")) {
							if(force_oac) {
								//noop
							}
							else if(can_acopy && !force_nosound) {
								cmdArray[s + 1] = "copy";
							}
							else {
								// in many case, "-oac copy" may cause serious error and/or has no effect
								cmdArray[s] = "-nosound";
								cmdArray[s + 1] = "-nosound";
							}
						}
						else if(cmdArray[s].equals("-aid")) {
							if(force_oac) {
								//noop
							}
							else if(!can_acopy || force_nosound) {
								// -aid must be erased , when -nosound used
								cmdArray[s] = "-nosound";
								cmdArray[s + 1] = "-nosound";
							} 
						}
					}
				}
				//PMS.dbg("MencoderVideo: timeseek_v="+timeseek_v+", timeseek_a="+timeseek_a);
				//PMS.dbg("  	sound_delay_mc="+sound_delay_mc+", sound_delay_ts="+sound_delay_ts);
				//PMS.dbg("MEncoderVideo: use m2ts, instead of ts");
				if(tx_m2ts) {
					main_pipe = new PipeProcess(System.currentTimeMillis() + "tsmuxerout.m2ts"); //regzamod2 for TEST
				}
				else {
					main_pipe = new PipeProcess(System.currentTimeMillis() + "tsmuxerout.ts");	//origin
				}

				//---- prepair tsmuxer proc
				TSMuxerVideo ts = new TSMuxerVideo(configuration);
				File f = new File(configuration.getTempFolder(), "pms-tsmuxer-mc("+params.sess.id+").meta");
				String cmd[] = new String[]{ts.executable(), f.getAbsolutePath(), main_pipe.getInputPipe()};
				pw = new ProcessWrapperImpl(cmd, params);

				
				//---- prepair video extractor proc
				// this proc is in [MencoderVideo: trasco type-1-2: (Trans to ts/m2ts by Mencoder+TsMuxer)]
				// --> mencoder output should be always mpg(or raw), not ts
				
				//PipeIPCProcess ffVideoPipe = new PipeIPCProcess(System.currentTimeMillis() + "ffmpegvideo", System.currentTimeMillis() + "videoout", false, true);	//original
				//regzamod, tsMuxer output will be damaged, if output_filename has no suffix(i.e. .mpg)
				//PipeIPCProcess ffVideoPipe = new PipeIPCProcess(System.currentTimeMillis() + "ffmpegvideo", System.currentTimeMillis() + (mpegts?"videoout.ts":"videoout.mpg"), false, true);	//regzamod
				PipeIPCProcess ffVideoPipe = new PipeIPCProcess(System.currentTimeMillis() + "ffmpegvideo", System.currentTimeMillis() + (rawvideo?"videoout":"videoout.mpg"), false, true);	//regzamod

				cmdArray[cmdArray.length - 1] = ffVideoPipe.getInputPipe();

				OutputParams ffparams = new OutputParams(configuration);
				ffparams.maxBufferSize = 1;
				ffparams.stdin = params.stdin;
				ProcessWrapperImpl ffVideo = new ProcessWrapperImpl(cmdArray, ffparams);

				//---- kick video extractor proc
				/* moved below
				ProcessWrapper ff_video_pipe_process = ffVideoPipe.getPipeProcess();
				pw.attachProcess(ff_video_pipe_process);
				ff_video_pipe_process.runInNewThread();
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
				}
				ffVideoPipe.deleteLater();
				pw.attachProcess(ffVideo);
				ffVideo.runInNewThread();
				*/

				/* moved upper
				String aid_num = null;
				if (media != null && media.getAudioCodes().size() > 1 && params.aid != null) {
					aid_num = params.aid.getId() + "";
				}
				if(rz_MetaChannel_a>=0) {	//forced audio_track
					aid_num = rz_MetaChannel_a + "";
				}
				*/

				//---- prepair audio proc
				PipeIPCProcess ffAudioPipe = new PipeIPCProcess(System.currentTimeMillis() + "ffmpegaudio01", System.currentTimeMillis() + "audioout", false, true);

				// it seems the -really-quiet prevents mencoder to stop the pipe output after some time...
				// -mc 0.1 make the DTS-HD extraction works better with latest mencoder builds, and makes no impact on the regular DTS one
				String ffmpegLPCMextract[];
				boolean usepcm=false;
				usepcm= (dtsRemux||dtsEmbed||pcmMod||pcmRaw) && !force_oaccopy;
				/*
				if ((configuration.isMencoderUsePcm()||configuration.isDTSEmbedInPCM()) 
					&& (params.aid.isLossless() ||params.aid.isDTS()) 
					&& params.mediaRenderer.isDTSPlayable()) {
					usepcm=true;
				}
				else if(params.aid==null) usepcm=true;
				*/
				
				// regzamod , TEST for -oac copy for AAC
				// but Head-Crashed Mencoder can't handle aac copy!!, 
				// even if using -audio-demuxer aac -fafmttag 0x706D etc. output is damaged yet
				// boolean RemuxAAC=params.aid.getAudioCodec().equals("aac");	//regzamod
				boolean RemuxAAC=false;	//regzamod
				boolean isAC3=(params.aid!=null && params.aid.isAC3())?true:false;
				boolean singleMediaAudio = media != null && media.getAudioCodes().size() <= 1;
				
				if(usepcm) {	//origin, use PCM/DTS as audio_codec 
					if(PMS.rz_debug>1) PMS.dbg("MencoderVideo: use PCM/DTS as audio_codec");
					StreamModifier sm = new StreamModifier();
					sm.setPcm(pcmMod);
					sm.setDtsembed(dtsEmbed);
					sm.setNbchannels(sm.isDtsembed() ? 2 : CodecUtil.getRealChannelCount(configuration, params.aid));
					sm.setSampleFrequency(48000);
					sm.setBitspersample(16);
					String mixer = CodecUtil.getMixerOutput(!sm.isDtsembed(), sm.getNbchannels());
					//if (!params.mediaRenderer.isMuxDTSToMpeg()) {
					if (dtsEmbed|pcmMod) {
						// no need to use the PCM trick when media renderer supports DTS
						ffAudioPipe.setModifier(sm);
					}
					//"-oac", sm.isDtsembed() ? "copy" : "pcm"
					if(dtsRemux) {
						mc_acodec="copy";
						ts_acodec="A_DTS";
					}
					else if(dtsEmbed) {
						mc_acodec="copy";
						ts_acodec="A_LPCM";
					}
					else {  //pcmMod
						mc_acodec="pcm";
						ts_acodec="A_LPCM";
					} 
				 	 
					ffmpegLPCMextract= new String[]{
						mencoder_path, 	//0
						"-ss", "0",		//2
						shortFileName,		//3
						"-quiet",		//4
						"-quiet",		//5
						"-really-quiet",
						"-msglevel", "statusline=2",//8
						"-channels", "" + sm.getNbchannels(), //10
						"-ovc", "copy",
						"-of", "rawaudio",
							
						"-quiet",	//regzamod 15
						"-quiet",	//regzamod 16
						"-quiet",	//regzamod 17
						"-quiet",	//regzamod 18
						"-quiet",	//regzamod 19
						"-quiet",	//regzamod 20
						"-quiet",	//regzamod 21
						"-quiet",	//regzamod 22
						"-quiet",	//regzamod 23
							
						"-mc", dtsRemux ? "0.1" : "0",
						"-noskip",
						(aid_num <0) ? "-quiet" : "-aid", (aid_num <0) ? "-quiet" : ""+aid_num,
						//"-oac", sm.isDtsembed() ? "copy" : "pcm", 
						"-oac", mc_acodec, 
						(mixer != null && !channels_filter_present) ? "-af" : "-quiet", (mixer != null && !channels_filter_present) ? mixer : "-quiet",
						"-srate", "48000",
						"-o", ffAudioPipe.getInputPipe()
					};
				}
				else {
					//regzamod2, bollowed from TSMuxerVideo, for no-sound bugs
					//PMS.dbg("MencoderVideo: use Dolby AC3 as audio_codec");
					if((oaccopy || force_oaccopy)&& params.aid!=null) {
						//A_AC3 - DD (AC3) / DD (E-AC3) / True HD (True HD only tracks with AC3 core inside).
						//A_AAC - AAC
						//A_DTS - DTS / DTS-HD
						//A_MP3 - MPEG audio layer 1/2/3
						//A_LPCM - raw pcm data or PCM WAVE file
						mc_acodec="copy";
						if(params.aid.isAC3()||params.aid.isTrueHD()) {
							ts_acodec="A_AC3";
						} else if(params.aid.isAAC()) {
							ts_acodec="A_AAC";
						} else if(params.aid.isDTS()) {
							ts_acodec="A_DTS";
						} else if(params.aid.isPCM()) {
							ts_acodec="A_LPCM";
						} else {
							logger.warn("MencoderVideo: audio="+params.aid.getCodecA()+" not supported by tsMuxeR, encode to AC3");
							mc_acodec="lavc";
							ts_acodec="A_AC3";
						}
					}
					else {
						if(isAC3 && configuration.isRemuxAC3()) {  
							mc_acodec="copy";
							ts_acodec="A_AC3";
						}
						else if(RemuxAAC) {
							mc_acodec="copy";
							ts_acodec="A_AAC";
						}
						else {
							mc_acodec="lavc";
							ts_acodec="A_AC3";
						} 
					}

					ffmpegLPCMextract = new String[]{
						mencoder_path,
						"-ss", "0",
						shortFileName,	//3
						"-quiet",	//4
						"-quiet",	//5
						"-really-quiet",
						"-msglevel", "statusline=2",//8
						"-channels", "" + CodecUtil.getAC3ChannelCount(configuration, params.aid),//10
						"-ovc", "copy",		//12
						"-of", "rawaudio",	//14
						"-quiet",	//regzamod 15
						"-quiet",	//regzamod 16
						"-quiet",	//regzamod 17
						"-quiet",	//regzamod 18
						"-quiet",	//regzamod 19
						"-quiet",	//regzamod 20
						"-quiet",	//regzamod 21
						"-quiet",	//regzamod 22
						"-quiet",	//regzamod 23
						"-quiet",	//regzamod 24
						"-quiet",	//regzamod 25
						"-quiet",	//regzamod 26
						"-mc", "0",
						"-noskip",
						//"-oac", (isAC3 && configuration.isRemuxAC3() || RemuxAAC) ? "copy" : "lavc",
						"-oac", mc_acodec,
						isAC3 ? "-fafmttag" : "-quiet", 
						isAC3 ? "0x2000" : "-quiet",
						"-lavcopts", "acodec=" + (configuration.isMencoderAc3Fixed() ? "ac3_fixed" : "ac3") + ":abitrate=" + CodecUtil.getAC3Bitrate(configuration, params.aid),
						"-af", "lavcresample=48000",
						"-srate", "48000",
						singleMediaAudio ? "-quiet" : "-aid", singleMediaAudio ? "-quiet" : ""+aid_num,
						"-o", ffAudioPipe.getInputPipe()
					};
				}


				if(fps_audio!=null && fps_audio.length()>0) {	//regzamod 
					//force same fps as video, to audio_extract to avoid audio duration unmatch
					//PMS.dbg("fps_audio="+fps_audio);
					ffmpegLPCMextract[16]= "-ofps";
					ffmpegLPCMextract[17]= fps_audio;
				}
				if(sound_delay_mc!=0) {	//regzamod3
					ffmpegLPCMextract[18]= "-delay";
					ffmpegLPCMextract[19]= ""+ (sound_delay_mc);
				}
				if(endpos>0) {//regzamod3, play end pos for audio
					//PMS.dbg("MencoderVideo: set audio endpos="+endpos);
					ffmpegLPCMextract[20]= "-endpos";
					ffmpegLPCMextract[21]= ""+(endpos);
				}
				if(dlna.rz_isPartPlay) {
					//PMS.dbg("MencoderVideo PartPlay : set audio -fps="+media.getFrameRate());
					ffmpegLPCMextract[22]= "-fps";
					ffmpegLPCMextract[23]= ""+media.getFrameRate();
				}
				if (dvd && dlna.rz_MetaDVDchapter!=null) {	//regzamod
						//what a terrible heavy way! is there any more smart way?
						ffmpegLPCMextract[24] = "-chapter";
						ffmpegLPCMextract[25] = dlna.rz_MetaDVDchapter;
						/*
						//PMS.dbg("dlna.rz_MetaDVDchapter="+dlna.rz_MetaDVDchapter+", cmdArray.length="+ffmpegLPCMextract.length);
						for(int j=0;j<ffmpegLPCMextract.length;j++) {
							PMS.dbg("ffmpegLPCMextract["+j+"]="+ffmpegLPCMextract[j]);
						}
						*/
				}
				if(dlna.rz_MetaSoundVolume>=0) {
					//PMS.dbg("MencoderVideo: set rz_MetaSoundVolume="+dlna.rz_MetaSoundVolume);
					for (int c = 0; c < ffmpegLPCMextract.length; c++) {
						if(ffmpegLPCMextract[c].equals("-af")) {
							ffmpegLPCMextract[c+1] += ",volume="+Math.log10((double)dlna.rz_MetaSoundVolume/100.0)*20.0;
						}
					}
				}

				if (media != null && media.getDvdtrack() > 0) {
					ffmpegLPCMextract[3] = "-dvd-device";
					ffmpegLPCMextract[4] = shortFileName;
					ffmpegLPCMextract[5] = "dvd://" + media.getDvdtrack();
				} else if (params.stdin != null) {
					ffmpegLPCMextract[3] = "-";
				}
				if (fileName.toLowerCase().endsWith(".evo")) {
					ffmpegLPCMextract[4] = "-psprobe";
					ffmpegLPCMextract[5] = "1000000";
				}
				//if (params.timeseek > 0) {
				if (timeseek_a!= 0.0f) {
					//ffmpegLPCMextract[2] = "" + params.timeseek;
					ffmpegLPCMextract[2] = "" + timeseek_a;
				}
				
				//---- options
				/*
				String opt="";
				if(dlna.rz_MetaMencoderOptA[1]!=null) {	// from script
					opt+=" "+dlna.rz_MetaMencoderOptA[1];
				}
				if(dlna.rz_MetaMencoderOptA[0]!=null) {	// from pxf/pxm
					opt+=" "+dlna.rz_MetaMencoderOptA[0];
				}
				*/
				if(mencoderOptA!=null && mencoderOptA.length>0) {	//audio options
					//String[] opts=opt.split("\\s");
					ffmpegLPCMextract = Arrays.copyOf(ffmpegLPCMextract, 
						ffmpegLPCMextract.length + mencoderOptA.length);
					int pos=ffmpegLPCMextract.length - mencoderOptA.length;
					for (int s = 0; s < mencoderOptA.length; s++) {
						if(mencoderOptA[s].length()>0) {
							ffmpegLPCMextract[pos - 2 + s] = mencoderOptA[s];
						}
						else {
							ffmpegLPCMextract[pos - 2 + s] = "-quiet";
						}
					}
					ffmpegLPCMextract[ffmpegLPCMextract.length -2]="-o";
					ffmpegLPCMextract[ffmpegLPCMextract.length -1]=ffAudioPipe.getInputPipe();
					//PMS.dbg("rz_MetaMencoderOptA="+dlna.rz_MetaMencoderOptA+", opts="+opts);
					//PMS.dbg("ffmpegLPCMextract="+ffmpegLPCMextract);
				}

				OutputParams ffaudioparams = new OutputParams(configuration);
				ffaudioparams.maxBufferSize = 1;
				ffaudioparams.stdin = params.stdin;
				ProcessWrapperImpl ffAudio = new ProcessWrapperImpl(ffmpegLPCMextract, ffaudioparams);

				params.stdin = null;

				//---- prepair tsmuxer proc
				PrintWriter pwMux = new PrintWriter(f);
				pwMux.println("MUXOPT --no-pcr-on-video-pid --no-asyncio --new-audio-pes --vbr --vbv-len=500");
				//pwMux.println("MUXOPT --no-pcr-on-video-pid --new-audio-pes --vbr --vbv-len=500");	//regzamod
				
				//video 
				String videoType = "V_MPEG-2";
				if (params.no_videoencode && params.forceType != null) {
					videoType = params.forceType;
				}
				String fps = "";
				if (params.forceFps != null) {
					fps = "fps=" + params.forceFps + ", ";
				}
				else if (forcefps_tsmuxer!=null) {	//regzamod
					fps = "fps=" + forcefps_tsmuxer + ", ";
				}
					
					
				//for audio
				if(true) {
					//Noop: ts_acodec is alreay fixed
					//when disiding mencoder's -oac codec
				}
				else {
					//---> yoou shouldn't new judge Here,
					//---> must match with mencoder's -oac codec that previously desided !!
					ts_acodec = "A_LPCM";
					if (params.mediaRenderer.isMuxDTSToMpeg()) {
						ts_acodec = "A_DTS";
					}
					//if (params.lossyaudio) {	//origin
					if (params.lossyaudio || media.isMpegTS() || dlna.isM2TS()) {	//regzamod2
						ts_acodec = "A_AC3";
					}
					else if (trans_form==MC_M2TS||trans_form==MC_MPEGTS2) {	//regzamod2
						ts_acodec = "A_AC3";
					}
					if (RemuxAAC) {	//regzamod2
						ts_acodec = "A_AAC";
					}
				}
				
				String timeshift_s="";
				String timeshift_s0="timeshift=0ms";
				if (params.aid != null && params.aid.getDelay() != 0) {
					timeshift_s = "timeshift=" + params.aid.getDelay() + "ms, ";
					timeshift_s0 = "timeshift=" + params.aid.getDelay() + "ms";
					//PMS.dbg("params.aid.getDelay()="+timeshift_s);
				}
				else if(sound_delay_ts!=0) {	
					timeshift_s="timeshift="+(int)(sound_delay_ts*1000)+"ms, ";
					timeshift_s0="timeshift="+(int)(sound_delay_ts*1000)+"ms";
				}
				
				//---- video params
				String optv=videoType + ", \"" + ffVideoPipe.getOutputPipe() + "\", " + fps + "level=4.1, insertSEI, contSPS, track=224";
				String str1=dlna.rz_MetaTsmuxerOptV[1];
				if(str1!=null && str1.length()>0) {
					if(PMS.rz_debug>1) PMS.dbg("MencoderVideo: rz_MetaTsmuxerOptA(org)="+str1);
					optv=dlna.getTsmuxerOptVReprace(str1,videoType,
						ffVideoPipe.getOutputPipe(),
						fps,
						"level=4.1, insertSEI, contSPS",
						"track=224");
					if(PMS.rz_debug>1) PMS.dbg("MencoderVideo: rz_MetaTsmuxerOptV(Replaced)="+optv);
				}
				pwMux.println(optv);

				//---- audio params
				String opta=ts_acodec + ", \"" + ffAudioPipe.getOutputPipe() + "\", " + timeshift_s +"track=2";
				String str2=dlna.rz_MetaTsmuxerOptA[1];
				if(str2!=null && str2.length()>0) {
					if(PMS.rz_debug>1) PMS.dbg("MencoderVideo: rz_MetaTsmuxerOptA(org)="+str2);
					opta=dlna.getTsmuxerOptAReprace(str2,ts_acodec,
						ffAudioPipe.getOutputPipe(),
						timeshift_s0,
						"track=2");
					if(PMS.rz_debug>1) PMS.dbg("MencoderVideo: rz_MetaTsmuxerOptA(Replaced)="+opta);
				}
				pwMux.println(opta);
				
				pwMux.close();
				
				//---- kick video extractor proc
				ProcessWrapper ff_video_pipe_process = ffVideoPipe.getPipeProcess();
				pw.attachProcess(ff_video_pipe_process);
				ff_video_pipe_process.runInNewThread();
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
				}
				ffVideoPipe.deleteLater();
				pw.attachProcess(ffVideo);
				ffVideo.runInNewThread(dlna);
				
				//---- kick audio extractor proc
				ProcessWrapper ff_pipe_process = ffAudioPipe.getPipeProcess();
				pw.attachProcess(ff_pipe_process);
				ff_pipe_process.runInNewThread();
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
				}
				ffAudioPipe.deleteLater();
				pw.attachProcess(ffAudio);
				ffAudio.runInNewThread(dlna);
				
				//---- kick tsMuxer proc
				ProcessWrapper pipe_process = main_pipe.getPipeProcess();
				pw.attachProcess(pipe_process);
				pipe_process.runInNewThread();
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
				}
				main_pipe.deleteLater();
				params.input_pipes[0] = main_pipe;	// trasco buffer
				
			}
		} else {
			//-------------------------------------------------------------------------
			//	transproc type-2 (Trans to mpeg/mpegts by mencoder WITHOUT tsmuxer)
			//-------------------------------------------------------------------------
			double delay=0;
			if(params.mediaRenderer.getRZ_TransAudioDelay()!=0) {	// RZ_TransAudioDelay in renderer.conf
				delay +=params.mediaRenderer.getRZ_TransAudioDelay();
			}
			//---- sound_delay by conditional codecSpacificpts in renderer.conf
			//PMS.dbg("MencoderVideo: addopts adelay_add="+addopts.adelay_add+", adelay_rep="+addopts.adelay_rep);
			if(addopts.adelay_add!=null) {
				delay+=addopts.adelay_add;
			}
			if(addopts.adelay_rep!=null) {
				delay =addopts.adelay_rep;
			}
			delay +=dlna.getForcedSoundDelay();  //from pxm/script
			if(delay!=0) {
				cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 2);
				cmdArray[cmdArray.length - 4] = "-delay";	// minus means video delay
				cmdArray[cmdArray.length - 3] = ""+ (-delay);
				cmdArray[cmdArray.length - 2] = "-o";
			}

			//mpeg or mpegts is judeged by boolean mpegts
			//if(useFFmpegMuxer>0) {	//regzamod
			if(trans_proc==112) {	//regzamod, useFFmpegMuxer
				//---------------------------------------------------------------
				// setup trasco pipe (muxer to PMS)
				//---------------------------------------------------------------
				if(PMS.rz_debug>1) PMS.dbg("---- MencoderVideo: trasco type2b (Trans to mpeg/ts by Mencoder + ffmpeg)");
				//---- create main pipe (ffmpeg to PMS)(trasco buffer)
				String sfx=".ts";
				if(trans_form==MC_M2TS) sfx=".m2ts";
				else if(trans_form==MC_MPEGPS) sfx=".mpg";
				main_pipe = new PipeProcess("mencoder" + System.currentTimeMillis() + sfx, 
					(pcmMod || dtsRemux || mux) ? null : params);
				params.input_pipes[0] = main_pipe;	// this is trasco buffer body
				ProcessWrapper pipe_process = main_pipe.getPipeProcess();
				//---- kick main_pipe proc
				
				//---------------------------------------------------------------
				// setup inter app pipe (transcoder to muxer)
				//---------------------------------------------------------------
				//---- create mencoder_pipe (mencoder to ffmpeg)
				PipeIPCProcess mcVideoPipe = new PipeIPCProcess(System.currentTimeMillis() + "mencoder_out.mpg", System.currentTimeMillis() + "ffmpeg_in.mpg", false, false);
				//PipeIPCProcess mcVideoPipe = new PipeIPCProcess(System.currentTimeMillis() + "mencoder_out.ts", System.currentTimeMillis() + "ffmpeg_in.ts", false, true);	//[false, true] don't work well why?
				
				//---------------------------------------------------------------
				// setup ffmpeg proc (muxer)
				//---------------------------------------------------------------
				if(useFFmpegMuxer==9) {	//test
					String ffcmd_test[] = new String[]{
						"C:\\Python27\\python.exe",
						"regzamod\\pipe_cat.py",
						"2",
						mcVideoPipe.getOutputPipe(),	//ffmpeg input i.e. mencoder's output
						main_pipe.getInputPipe(),	//ffmpeg's output
					};
					params.input_pipes[0] = main_pipe;
					//pw= new ProcessWrapperImpl(ffcmd_test, params);
					pw= new ProcessWrapperImpl(ffcmd_test, params);
				}
				else {
					String ffcmd[] = new String[]{
						configuration.getFfmpegPath(),		// 0
						
						//"-fflags","+genpts",				// 1, 2 : not necessary
						"-y","-y",							// 1, 2
						
						"-ss","-2.0",						// 3, 4 tricky start
						"-itsoffset","0.0",					// 5, 6 must be before input
						"-i", mcVideoPipe.getOutputPipe(),	// 7, 8 ffmpeg input i.e. mencoder's output
						"-vcodec", "copy",					// 9,10
						"-acodec", "copy",  				//11,12
						
						//"-async", "10",					//13,14 : not necessary
						"-y", "-y",							//13,14
						
						"-loglevel","warning",				//15,16
						"-y","-y",							//17,18
						"-y","-y",							//19,20
						
						//"-copytb","1",						//21,22 : necessary
						"-y","-y",							//21,22
						
						//"-vbsf","h264_mp4toannexb",
						//"-fflags","+genpts",
						main_pipe.getInputPipe(),			//23 ffmpeg's output
					};
					if(false && media.isMpegTS()) {  
						//1st, ffmpeg v1.0 doesn't supprt -af atempo
						//2nd, atempo seems to have no effects when remuxing, even if supported 
						ffcmd[17]="-af";
						ffcmd[18]="atempo=2.0";
					}
					
					//---- add rz_MetaFFmpegOpt, if exists
					String ffmpeg_addopts="";
					if(dlna.rz_MetaFFmpegOpt[1]!=null) {  //from scripts
						ffmpeg_addopts+=dlna.rz_MetaFFmpegOpt[1];
					}
					if(dlna.rz_MetaFFmpegOpt[0]!=null) {  //from pxm
						ffmpeg_addopts+=dlna.rz_MetaFFmpegOpt[0];
					}
					//PMS.dbg("MencoderVideo: ffmpeg_addopts="+ffmpeg_addopts);
					
					String[] sArgs=ffmpeg_addopts.split("\\s");
					if(sArgs.length>0) {
						int	length_org=ffcmd.length;
						String last_para_org=ffcmd[length_org-1];	//memory last param(== outpot file(pipe))
						ffcmd = Arrays.copyOf(ffcmd, ffcmd.length + sArgs.length);
						for(int j=0;j<sArgs.length; j++) {
							ffcmd[length_org-1+j]=sArgs[j];
						}
						ffcmd[ffcmd.length-1]=last_para_org;		//recover last param(== outpot file(pipe))
					}

					params.input_pipes[0] = main_pipe;
					//pw= new ProcessWrapperImpl(ffcmd, params);
					pw= new ProcessWrapperImpl(ffcmd, params);
				}
				//---- ffmpeg pipe -----------
				pw.attachProcess(pipe_process);
				pipe_process.runInNewThread();
				try {
						Thread.sleep(50);
				} catch (InterruptedException e) {
				}
				main_pipe.deleteLater();

				//---------------------------------------------------------------
				// setup mencoder proc (transcoder)
				//---------------------------------------------------------------
				//---- mencoder pipe -----------
				ProcessWrapper mc_video_pipe_process = mcVideoPipe.getPipeProcess();
				pw.attachProcess(mc_video_pipe_process);
				mc_video_pipe_process.runInNewThread();
				
				//---- setup mencoder & run -----------
				ProcessWrapperImpl mcVideo;
				//---- plug-in interface that may modify params here
				cmdArray[cmdArray.length - 1] = mcVideoPipe.getInputPipe();
				cmdArray = finalizeTranscoderArgs(
					this,
					fileName,
					dlna,
					media,
					params,
					cmdArray
				);
				
				OutputParams mcparams = new OutputParams(configuration);
				mcparams.maxBufferSize = 1;
				mcparams.stdin = params.stdin;
				
				if(useFFmpegMuxer==9) {	//test
					String mcmd_test[] = new String[]{
						"C:\\Python27\\python.exe",
						"regzamod\\pipe_cat.py",
						"1",	// transcoder
						fileName,
						mcVideoPipe.getInputPipe(),
					};
					mcVideo = new ProcessWrapperImpl(mcmd_test, mcparams);
				}
				else {	// useFFmpegMuxer>1
					mcVideo = new ProcessWrapperImpl(cmdArray, mcparams);
				}
				pw.attachProcess(mcVideo);
				mcVideo.runInNewThread(dlna);
			}
			else { //original
				if(PMS.rz_debug>1) PMS.dbg("---- MencoderVideo: trasco type2a (Trans to mpeg/ts by Mencoder only)");
				/*
				//---- param tunings -- moved upper
				float delay=0;
				if(params.mediaRenderer.getRZ_TransAudioDelay()!=0) {	// RZ_TransAudioDelay in renderer.conf
					delay +=params.mediaRenderer.getRZ_TransAudioDelay();
				}
				if(dlna.rz_SoundDelay!=0) { 		// sound_delay in pxm/pxf
					delay +=(float)dlna.rz_SoundDelay;
				}	
				if(delay!=0) {
					cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 2);
					cmdArray[cmdArray.length - 4] = "-delay";	// minus means video delay
					cmdArray[cmdArray.length - 3] = ""+ (-delay);
					cmdArray[cmdArray.length - 2] = "-o";
				}
				*/
				//---- prepair pipe
				boolean directpipe = Platform.isMac() || Platform.isFreeBSD();
				if (directpipe) {
					cmdArray = Arrays.copyOf(cmdArray, cmdArray.length + 3);
					cmdArray[cmdArray.length - 3] = "-really-quiet";
					cmdArray[cmdArray.length - 2] = "-msglevel";
					cmdArray[cmdArray.length - 1] = "statusline=2";
					cmdArray[cmdArray.length - 4] = "-";
					params.input_pipes = new PipeProcess[2];
				} else {
					main_pipe = new PipeProcess("mencoder" + System.currentTimeMillis(), (pcmMod || dtsRemux || mux) ? null : params);
					params.input_pipes[0] = main_pipe;
					cmdArray[cmdArray.length - 1] = main_pipe.getInputPipe();
				}

				// plug-in interface that may modify params here
				cmdArray = finalizeTranscoderArgs(
					this,
					fileName,
					dlna,
					media,
					params,
					cmdArray
				);

				pw = new ProcessWrapperImpl(cmdArray, params);

				if (!directpipe) {
					ProcessWrapper mkfifo_process = main_pipe.getPipeProcess();
					pw.attachProcess(mkfifo_process);
					mkfifo_process.runInNewThread();
					try {
						Thread.sleep(50);
					} catch (InterruptedException e) {
					}
					main_pipe.deleteLater();
				}
			}

		}

		//pw.runInNewThread();
		pw.runInNewThread(dlna);	//regzamod
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
		}
		return pw;
	}

	@Override
	public String mimeType() {
		return HTTPResource.VIDEO_TRANSCODE;
	}

	@Override
	public String name() {
		return "MEncoder";
	}

	@Override
	public int type() {
		return Format.VIDEO;
	}

	public static class scAddOpts { // for getSpecificCodecOptions()
		public Float adelay_add=null;
		public Float adelay_rep=null;
	}
	//private String[] getSpecificCodecOptions(String codecParam, DLNAMediaInfo media, OutputParams params, 
	//	String filename, String srtFileName, boolean enable, boolean verifyOnly) {
	public static String[] getSpecificCodecOptions(String codecParam, DLNAMediaInfo media, OutputParams params, 
		String filename, String srtFileName, boolean enable, boolean verifyOnly, scAddOpts opts) {

		StringBuilder sb = new StringBuilder();

		String codecs = enable ? DEFAULT_CODEC_CONF_SCRIPT : "";
		codecs += "\n" + codecParam;
		StringTokenizer stLines = new StringTokenizer(codecs, "\n");
		try {
			Interpreter interpreter = new Interpreter();
			interpreter.setStrictJava(true);
			ArrayList<String> types = CodecUtil.getPossibleCodecs();
			int rank = 1;
			if (types != null) {
				for (String type : types) {
					int r = rank++;
					interpreter.set("" + type, r);
					String secondaryType = "dummy";
					if ("matroska".equals(type)) {
						secondaryType = "mkv";
						interpreter.set(secondaryType, r);
					} else if ("rm".equals(type)) {
						secondaryType = "rmvb";
						interpreter.set(secondaryType, r);
					} else if ("mpeg2video".equals(type)) {
						secondaryType = "mpeg2";
						interpreter.set(secondaryType, r);
					} else if ("mpeg1video".equals(type)) {
						secondaryType = "mpeg1";
						interpreter.set(secondaryType, r);
					}
					if (media.getContainer() != null && (media.getContainer().equals(type) || media.getContainer().equals(secondaryType))) {
						interpreter.set("container", r);
					//} else if (media.getCodecV() != null && (media.getCodecV().equals(type) || media.getCodecV().equals(secondaryType))) {
					} else if (media.getCodecV() != null 
						&& (media.getCodecV().startsWith(type) || media.getCodecV().startsWith(secondaryType))) {
						interpreter.set("vcodec", r);
					//} else if (params.aid != null && params.aid.getCodecA() != null && params.aid.getCodecA().equals(type)) {
					} else if (params.aid != null && params.aid.getCodecA() != null 
						&& params.aid.getCodecA().startsWith(type)) {
						interpreter.set("acodec", r);
					}
				}
			} else {
				return null;
			}

			interpreter.set("filename", filename);
			interpreter.set("audio", params.aid != null);
			interpreter.set("subtitles", params.sid != null);
			interpreter.set("srtfile", srtFileName);
			if (params.aid != null) {
				interpreter.set("samplerate", params.aid.getSampleRate());
			}
			try {
				//String framerate = media.getValidFps(false);	//regzamod
				// media.getValidFps doesn't return correct value
				String framerate = media.getFrameRate();	//regzamod
				if (framerate != null) {
					interpreter.set("framerate", Double.parseDouble(framerate));
				}
			} catch (NumberFormatException e) {
			}
			interpreter.set("duration", media.getDurationInSeconds());
			if (params.aid != null) {
				interpreter.set("channels", params.aid.getNrAudioChannels());
			}
			interpreter.set("height", media.getHeight());
			interpreter.set("width", media.getWidth());
			while (stLines.hasMoreTokens()) {
				String line = stLines.nextToken();
				if (!line.startsWith("#") && line.trim().length() > 0) {
					int separator = line.indexOf("::");
					if (separator > -1) {
						String key = null;
						try {
							key = line.substring(0, separator).trim();
							String value = line.substring(separator + 2).trim();

							if (value.length() > 0) {
								if (key.length() == 0) {
									key = "1 == 1";
								}
								Object result = interpreter.eval(key);
								if (result != null && result instanceof Boolean && ((Boolean) result).booleanValue()) {
									sb.append(" ");
									sb.append(value);
								}
							}
						} catch (Throwable e) {
							logger.debug("Error while executing: " + key + " : " + e.getMessage());
							if (verifyOnly) {
								return new String[]{"@@Error while parsing: " + e.getMessage()};
							}
						}
					} else if (verifyOnly) {
						return new String[]{"@@Malformatted line: " + line};
					}
				}
			}
		} catch (EvalError e) {
			logger.debug("BeanShell error: " + e.getMessage());
		}
		String completeLine = sb.toString();

		ArrayList<String> args = new ArrayList<String>();
		StringTokenizer st = new StringTokenizer(completeLine, " ");
		String arg;
		while (st.hasMoreTokens()) {
			arg= st.nextToken().trim();
			if (arg.length() > 0) {
				args.add(arg);
			}
		}
		//---- regzamod ----------
		//extract special options
		int max=args.size()-1;
		for(int i=max; i>=0; i--) {
			//must backword loop , to retain remaining list index after some removed
			arg=args.get(i);
			if(arg.equals("-adelay_add")) {
				//PMS.dbg("getSpecificCodecOptions: found specific opt:-adelay_add");
				if(opts!=null) {
					opts.adelay_add=Float.parseFloat(args.get(i+1));
				}
				args.remove(i+1);
				args.remove(i);
			}
			else if(arg.equals("-adelay_rep")) {
				//PMS.dbg("getSpecificCodecOptions: found specific opt:-adelay_rep");
				if(opts!=null) {
					opts.adelay_rep=Float.parseFloat(args.get(i+1));
				}
				args.remove(i+1);
				args.remove(i);
			}
		}

		String definitiveArgs[] = new String[args.size()];
		args.toArray(definitiveArgs);
		
		return definitiveArgs;
	}
}
