MPEG Maker Extension
From MediaCoderWiki
Contents |
Get started
Introduction
An extension is usually made up of 3 parts:
- Extension XML (description of the XML)
- One or more HTML files (user interface)
- One or more JavaScript files (control logic)
All of the files are put in a sub-folder of {MediaCoder folder}\htdocs\extensions.
Let's take MPEG maker extension as an example. This extension simplifies the procedure of setting up MediaCoder to produce MPEG-1 and MPEG-2 files. The interface is a single HTML file. A JavaScript file is included to post settings to MediaCoder.
What you need
All files that make up an extension are plain text files (.htm, .js, .xml), but still you need some good tools other than Windows notepad to editor the files. For editing HTML and JavaScript files, a good WYSIWYG HTML editor is preferred. For editing XML files, I'll suggest XML Copy Editor, a GPLed XML editor running on both Windows and Linux.
Building up
Extension XML
The extension XML must be named as "extension.xml", so that the extension loading routine can find and parse it. The following is the extension.xml of MPEG maker.
<?xml version="1.0" encoding="UTF-8"?> <MediaCoderExtension> <property id="vendor" value="Sinovation Inc."/> <property id="name" value="MPEG Maker"/> <property id="version" value="0.1"/> </MediaCoderExtension>
As you can see, this file contains some attributes of the extension, which is displayed in the extension selection dialog.
User Interface
You can find the HTML and JavaScript file of this extension in {MediaCoder Folder}\htdocs\extensions\mpeg. The main.htm presents the user interface and binds the controls with corresponding JavaScript code. There is nothing new in this if you know something about designing a web page.
Here is the HTML for this interface. Usually you should use an HTML editor to edit it.
<html>
<head>
<link rel="stylesheet" href="/mcstyle.css">
<script language="javascript">
// resize window
window.innerWidth = 500;
window.innerHeight = 350;
</script>
<script src="../extension.js" language="javascript"></script>
<script src="main.js" langauge="javascript"></script>
</head>
<body class="extension" onLoad="ApplyParams()" onUnload="Unload()" background="/img/back.png">
<div>
<h1 align="center">MediaCoder MPEG Maker </h1>
</div>
<hr>
<table width="100%" border="0">
<tr>
<td width="50%"><div align="center">
<h2>Video Settings</h2>
</div></td>
<td><div align="center">
<h2>Audio Settings</h2>
</div></td>
</tr>
<tr>
<td><table width="100%" border="0">
<tr>
<td width="80" height="30"><p>Format:</p></td>
<td> <select onChange="ApplyParams()" id="vidfmt">
<option value="MPEG1">MPEG-1</option>
<option value="MPEG2">MPEG-2</option>
</select> </td>
</tr>
<tr>
<td height="30">Bitrate:</td>
<td><select id="vb" onChange="ApplyParams()">
<option value="8000">8 Mbps</option>
<option value="5000">5 Mbps (DVD)</option>
<option value="2500">2.5 Mbps (SVCD)</option>
<option value="1152" selected>1152 Kbps (VCD)</option>
<option value="800">800 Kbps</option>
<option value="600">600 Kbps</option>
<option value="512">512 Kbps</option>
<option value="400">400 Kbps</option>
</select></td>
</tr>
<tr>
<td height="30">Frame rate:</td>
<td><select id="fps" onChange="ApplyParams()">
<option value="0">Original</option>
<option value="30">30 fps</option>
<option value="30000/1001">29.97 fps</option>
<option value="25" selected>25 fps</option>
<option value="24">24 fps</option>
</select></td>
</tr>
<tr>
<td height="30"> Resolution:</td>
<td><select id="res" onChange="ApplyParams()" >
<option value="0x0">Original</option>
<option value="720x576">720x576</option>
<option value="720x480">720x480</option>
<option value="352x288" selected>352x288</option>
<option value="352x240">352x240</option>
</select></td>
</tr>
<tr>
<td height="30">Mode:</td>
<td> <select id="pass" onChange="ApplyParams()" >
<option value="Fixed Bitrate">1-Pass</option>
<option value="Two-Pass">2-Pass</option>
</select>
<br>
</p> </td>
</tr>
</table></td>
<td valign="top"> <table width="100%" border="0">
<tr>
<td width="80" height="30"><p>Format:</p></td>
<td><select onChange="ApplyParams()" id="audfmt">
<option value="MPEG Layer 2" selected>MPEG Audio</option>
<option value="AC3">AC-3</option>
<option value="Stream Copy">Stream Copy</option>
<option value="No Audio">No Audio</option>
</select></td>
</tr>
<tr>
<td height="30"> Bitrate:</td>
<td><select id="ab" onChange="ApplyParams()">
<option value="224">224 Kbps</option>
<option value="192">192 Kbps</option>
<option value="160">160 Kbps</option>
<option value="128">128 Kbps</option>
</select></td>
</tr>
<tr>
<td height="30">Sampling Rate: </td>
<td><select id="srate" onChange="ApplyParams()">
<option value="0">Original</option>
<option value="48000">48000 Hz</option>
<option value="44100">44100 Hz</option>
</select></td>
</tr>
<tr>
<td height="30">Number of stream:</td>
<td><select name="select" id="streams" onChange="ApplyParams()">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select></td>
</tr>
</table></td>
</tr>
</table>
<p align="center">
<input type="button" value="Play" style="width: 64px" onClick="SendCommand('play')">
<input type="button" value="Preview" style="width: 64px" onClick="SendCommand('preview')">
<input type="button" value="Skip 10s" style="width: 64px" onClick="SendCommand('mpcmd skip 10')">
<input type="button" value="Crop" style="width: 64px" onClick="SendCommand('show_cropper')">
<input type="button" value="SetTime" style="width: 64px" onClick="SendCommand('set_time')">
<input type="button" value="Start" style="width: 64px" onClick="SendCommand('transcode')">
</p>
<div align="right"><a href="../">Back</a></div>
</body>
</div>
</html>
Code
The main.js contains code for getting settings from the HTML user interface and changing the settings of MediaCoder.
/*************************************************************************
* MediaCoder extension - MPEG Maker
* Distributed under GPL license
* Copyright (c) 2005-06 Stanley Huang <reachme@citiz.net>
* All rights reserved.
*************************************************************************/
function ApplyParams()
{
var doc = NewXML("MediaCoderPref");
if (!doc) {
alert("Error creating config XML");
return;
}
// container settings
var vidfmt = document.getElementById("vidfmt").value;
AddPrefNode(doc, "overall.video.muxer", "None");
AddPrefNode(doc, "overall.video.container", vidfmt);
// video settings
AddPrefNode(doc, "overall.video.encoder", "FFMPEG");
AddPrefNode(doc, "overall.video.format", vidfmt);
AddPrefNode(doc, "overall.video.bitrate", document.getElementById("vb").value);
AddPrefNode(doc, "overall.video.mode", document.getElementById("pass").value);
AddPrefNode(doc, "videofilter.frame.enabled", "true");
AddPrefNode(doc, "videofilter.frame.nofpsinc", "false");
var fps = document.getElementById("fps").value.split("/");
if (fps.length < 2) {
AddPrefNode(doc, "videofilter.frame.fps", fps[0]);
AddPrefNode(doc, "videofilter.frame.fpsScale", "1");
} else {
AddPrefNode(doc, "videofilter.frame.fps", fps[0]);
AddPrefNode(doc, "videofilter.frame.fpsScale", fps[1]);
}
var res = document.getElementById("res").value.split("x");
AddPrefNode(doc, "videofilter.scale.enabled", (res[0] != "0"));
AddPrefNode(doc, "videofilter.scale.width", res[0]);
AddPrefNode(doc, "videofilter.scale.height", res[1]);
// audio settings
var audfmt = document.getElementById("audfmt").value;
switch (audfmt) {
case "No Audio":
AddPrefNode(doc, "overall.audio.encoder", audfmt);
break;
default:
AddPrefNode(doc, "overall.audio.encoder", "ffmpeg");
AddPrefNode(doc, "audioenc.ffmpeg.codec", audfmt);
AddPrefNode(doc, "audioenc.ffmpeg.bitrate", document.getElementById("ab").value);
AddPrefNode(doc, "audioenc.ffmpeg.streams", document.getElementById("streams").value);
break;
}
AddPrefNode(doc, "audiofilter.resample.samplerate", document.getElementById("srate").srate);
// post settings to MediaCoder
PostPrefXML(doc);
}
function Unload()
{
// stop playback on window close
SendCommand("stop_play");
}
ApplyParams is called whenever a value of a control on the page is modified, so that the change can post to MediaCoder in time always.
Mechasim
Change MediaCoder's settings
Here I explain the mechanism in which a extension modify settings of MediaCoder. All MediaCoder's settings are arranged in a tree, which can be represented by an XML document. To change MediaCoder's settings, an extension needs to do the following:
- Create a XML document
- Add nodes to the XML document
- Post the XML document to MediaCoder's internal HTTP daemon
An extension can use some pre-defined functions (in {MediaCoder folder}\htdocs\extensions\extension.js) to do these jobs with ease (of course the extension.js file needs to be included.
To create an XML document, you can use following code:
var doc = NewXML("MediaCoderPref");
To add a node, use following:
AddPrefNode(doc, "overall.video.encoder", "FFMPEG");
After adding all nodes, post it to MediaCoder use following:
PostPrefXML(doc);
- Tip: You may need to know the path of the preference key, so that you can modify it. A easy way to know it is to click Settings button in MediaCoder and move you mouse over your interested option. The path of the key will be displayed on the upper-right part of the window.
Control MediaCoder's behavior
Besides change MediaCoder's settings, an extension can also control MediaCoder's behavior, like start/stop transcoding, start/stop playback etc. SendCommand function is for this purpose. It has one argument which is a string of command to be sent. Usually this function can be called in a onClick event. For example, to start transcoding you can:
SendCommand('transcode')
Following commands are available at the moment (more are adding and you can request):
- transcode - start/stop transcoding
- play - start/stop playback
- preview - start/stop preview
- mpcmd <mplayer cmd> - send <mplayercmd> to mplayer (if mplayer is running)
- show_cropper - show cropper dialog
- set_time - show time option dialog
Get it shown
To get a new extension shown in the extension dialog. What you need to do this add an entry in {MediaCoder folder}\htdocs\extensions.xml, as the following.
<?xml version="1.0" encoding="UTF-8"?> <MediaCoderPluginInfo> <catalog name="phone"/> <catalog name="dmp"/> <device id="zen"/> </catalog> <catalog name="game"/> <catalog name="disc"> <device id="mpeg"/> <device id="mpeg_zh"/> </catalog> </MediaCoderPluginInfo>
Each catalog is corresponding to a device type, you may just pick a type and put the new entry into it.
