[rygel/rygel-0-12: 1/2] core: Revert encodebin-based transcoder
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rygel/rygel-0-12: 1/2] core: Revert encodebin-based transcoder
- Date: Mon, 5 Sep 2011 15:34:28 +0000 (UTC)
commit fa2a5ca3ea78f4bc92e08b3ac3290fa61a80e1d9
Author: Jens Georg <mail jensge org>
Date: Mon Sep 5 16:32:23 2011 +0200
core: Revert encodebin-based transcoder
configure.ac | 2 -
data/rygel.conf | 6 --
doc/man/rygel.conf.xml | 20 -----
doc/man/rygel.xml | 38 ---------
po/POTFILES.in | 6 ++
po/POTFILES.skip | 5 +
src/rygel/Makefile.am | 11 ++-
src/rygel/rygel-aac-transcoder.vala | 92 ----------------------
src/rygel/rygel-avc-transcoder.vala | 100 ------------------------
src/rygel/rygel-cmdline-config.vala | 22 ------
src/rygel/rygel-configuration.vala | 4 -
src/rygel/rygel-environment-config.vala | 10 ---
src/rygel/rygel-gst-utils.vala | 5 +
src/rygel/rygel-l16-transcoder-bin.vala | 72 ++++++++++++++++++
src/rygel/rygel-l16-transcoder.vala | 79 +++++++++++++++-----
src/rygel/rygel-meta-config.vala | 38 ---------
src/rygel/rygel-mp2ts-transcoder-bin.vala | 108 ++++++++++++++++++++++++++
src/rygel/rygel-mp2ts-transcoder.vala | 117 ++++++++++++++++++----------
src/rygel/rygel-mp3-transcoder-bin.vala | 77 +++++++++++++++++++
src/rygel/rygel-mp3-transcoder.vala | 58 +++++++++++++--
src/rygel/rygel-transcode-manager.vala | 16 +----
src/rygel/rygel-transcoder.vala | 81 +-------------------
src/rygel/rygel-user-config.vala | 10 ---
src/rygel/rygel-wma-transcoder-bin.vala | 66 ++++++++++++++++
src/rygel/rygel-wma-transcoder.vala | 97 ++++++++++++++++++++++++
src/rygel/rygel-wmv-transcoder-bin.vala | 106 ++++++++++++++++++++++++++
src/rygel/rygel-wmv-transcoder.vala | 65 +++++++++-------
27 files changed, 779 insertions(+), 532 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 80a620d..5c1232e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -39,7 +39,6 @@ GUPNP_DLNA_MAX_VERSION=0.6.9999
GUPNP_DLNA_REQUIRED=0.5.0
GUPNP_VALA_REQUIRED=0.9.0
GSTREAMER_REQUIRED=0.10.23
-GSTPBU_REQUIRED=0.10.30
GIO_REQUIRED=2.26
GEE_MAX_VERSION=0.6.9999
GEE_REQUIRED=0.5.2
@@ -63,7 +62,6 @@ PKG_CHECK_MODULES(LIBGUPNP_DLNA, gupnp-dlna-1.0 >= $GUPNP_DLNA_REQUIRED
gupnp-dlna-1.0 <= $GUPNP_DLNA_MAX_VERSION)
PKG_CHECK_MODULES(LIBGSTREAMER, gstreamer-0.10 >= $GSTREAMER_REQUIRED)
PKG_CHECK_MODULES(GSTREAMER_BASE, gstreamer-base-0.10 >= $GSTREAMER_REQUIRED)
-PKG_CHECK_MODULES(GST_PBU, gstreamer-pbutils-0.10 >= $GSTPBU_REQUIRED)
PKG_CHECK_MODULES(LIBGIO, gio-2.0 >= $GIO_REQUIRED)
PKG_CHECK_MODULES(GEE, gee-1.0 >= $GEE_REQUIRED)
PKG_CHECK_MODULES(UUID, uuid >= $UUID_REQUIRED)
diff --git a/data/rygel.conf b/data/rygel.conf
index a4da341..91fa862 100644
--- a/data/rygel.conf
+++ b/data/rygel.conf
@@ -26,12 +26,6 @@ enable-mp2ts-transcoder=true
# Set it to 'false' if you want to disable WMV transcoding support.
enable-wmv-transcoder=true
-# Set it to 'false' if you want to disable AAC_ISO_320 transcoding support.
-enable-aac-transcoder=false
-
-# Set it to 'false' if you want to disable AVC_MP4 transcoding support.
-enable-avc-transcoder=false
-
# Where video files should be saved if allow-upload is true.
# Defaults to @VIDEOS@, the standard videos folder (typically ${HOME}/Videos).
video-upload-folder= VIDEOS@
diff --git a/doc/man/rygel.conf.xml b/doc/man/rygel.conf.xml
index a5c3394..1d70260 100644
--- a/doc/man/rygel.conf.xml
+++ b/doc/man/rygel.conf.xml
@@ -187,26 +187,6 @@ man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/
</varlistentry>
<varlistentry>
<term>
- <option>enable-aac-transcoder</option>
- </term>
- <listitem>
- <para>
- Set to <userinput>true</userinput> to enable transcoding to AAC.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>
- <option>enable-avc-transcoder</option>
- </term>
- <listitem>
- <para>
- Set to <userinput>true</userinput> to enable transcoding to AVC.
- </para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>
<option>log-level=<replaceable>DOMAIN</replaceable>:<replaceable>LEVEL</replaceable>[,<replaceable>DOMAIN</replaceable>:<replaceable>LEVEL</replaceable>,â]</option>
</term>
<listitem>
diff --git a/doc/man/rygel.xml b/doc/man/rygel.xml
index a37e800..12afd40 100644
--- a/doc/man/rygel.xml
+++ b/doc/man/rygel.xml
@@ -222,28 +222,6 @@ handling.</para>
</varlistentry>
<varlistentry>
<term>
- <option>-a</option>
- </term>
- <term>
- <option>--disable-aac-transcoder</option>
- </term>
- <listitem>
- <para>Disable transcoding to AAC.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>
- <option>-z</option>
- </term>
- <term>
- <option>--disable-avc-transcoder</option>
- </term>
- <listitem>
- <para>Disable transcoding to AVC.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>
<option>-U</option>
</term>
<term>
@@ -452,22 +430,6 @@ handling.</para>
</varlistentry>
<varlistentry>
<term>
- <envar>RYGEL_DISABLE_AAC_TRANS</envar>
- </term>
- <listitem>
- <para>Disable transcoding to AAC format.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>
- <envar>RYGEL_DISABLE_AVC_TRANS</envar>
- </term>
- <listitem>
- <para>Disable transcoding to AVC format.</para>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>
<envar>RYGEL_LOG</envar>
</term>
<listitem>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 57af3a4..d7fec05 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -98,6 +98,7 @@ src/rygel/rygel-icon-info.vala
src/rygel/rygel-import-resource.vala
src/rygel/rygel-item-creator.vala
src/rygel/rygel-item-destroyer.vala
+src/rygel/rygel-l16-transcoder-bin.vala
src/rygel/rygel-l16-transcoder.vala
src/rygel/rygel-log-handler.vala
src/rygel/rygel-logical-expression.vala
@@ -113,7 +114,9 @@ src/rygel/rygel-visual-item.vala
src/rygel/rygel-media-object.vala
src/rygel/rygel-media-receiver-registrar.vala
src/rygel/rygel-meta-config.vala
+src/rygel/rygel-mp2ts-transcoder-bin.vala
src/rygel/rygel-mp2ts-transcoder.vala
+src/rygel/rygel-mp3-transcoder-bin.vala
src/rygel/rygel-mp3-transcoder.vala
src/rygel/rygel-plugin-loader.vala
src/rygel/rygel-plugin.vala
@@ -135,6 +138,9 @@ src/rygel/rygel-thumbnail.vala
src/rygel/rygel-transcode-manager.vala
src/rygel/rygel-transcoder.vala
src/rygel/rygel-user-config.vala
+src/rygel/rygel-wma-transcoder-bin.vala
+src/rygel/rygel-wma-transcoder.vala
+src/rygel/rygel-wmv-transcoder-bin.vala
src/rygel/rygel-wmv-transcoder.vala
src/rygel/rygel-xbox-hacks.vala
src/rygel/rygel-changelog.vala
diff --git a/po/POTFILES.skip b/po/POTFILES.skip
index fb1cb03..0f3d1be 100644
--- a/po/POTFILES.skip
+++ b/po/POTFILES.skip
@@ -140,6 +140,7 @@ src/rygel/rygel-item-creator.c
src/rygel/rygel-item-destroyer.c
src/rygel/rygel-item-removal-queue.c
src/rygel/rygel-l16-transcoder.c
+src/rygel/rygel-l16-transcoder-bin.c
src/rygel/rygel-log-handler.c
src/rygel/rygel-logical-expression.c
src/rygel/rygel-main.c
@@ -156,7 +157,9 @@ src/rygel/rygel-media-server-plugin.c
src/rygel/rygel-meta-config.c
src/rygel/rygel-metadata-extractor.c
src/rygel/rygel-mp2ts-transcoder.c
+src/rygel/rygel-mp2ts-transcoder-bin.c
src/rygel/rygel-mp3-transcoder.c
+src/rygel/rygel-mp3-transcoder-bin.c
src/rygel/rygel-music-item.c
src/rygel/rygel-photo-item.c
src/rygel/rygel-plugin.c
@@ -185,7 +188,9 @@ src/rygel/rygel-user-config.c
src/rygel/rygel-video-item.c
src/rygel/rygel-visual-item.c
src/rygel/rygel-volume.c
+src/rygel/rygel-wma-transcoder-bin.c
src/rygel/rygel-wmv-transcoder.c
+src/rygel/rygel-wmv-transcoder-bin.c
src/rygel/rygel-writable-container.c
src/rygel/rygel-xbox-hacks.c
src/rygel/rygel-xml-utils.c
diff --git a/src/rygel/Makefile.am b/src/rygel/Makefile.am
index aec85e1..f9e6ec9 100644
--- a/src/rygel/Makefile.am
+++ b/src/rygel/Makefile.am
@@ -3,8 +3,6 @@ include ../../common.am
AM_CFLAGS += \
$(LIBGUPNP_DLNA_CFLAGS) \
$(LIBSOUP_CFLAGS) \
- $(LIBGSTREAMER_CFLAGS) \
- $(GST_PBU_CFLAGS) \
-DSMALL_ICON_DIR='"$(smallicondir)"' \
-DBIG_ICON_DIR='"$(bigicondir)"' -include config.h \
-DLOCALEDIR=\""$(datadir)/locale"\" -DG_LOG_DOMAIN='"Rygel"'
@@ -96,9 +94,13 @@ VAPI_SOURCE_FILES = \
rygel-mp2ts-transcoder.vala \
rygel-mp3-transcoder.vala \
rygel-l16-transcoder.vala \
+ rygel-mp2ts-transcoder-bin.vala \
+ rygel-mp3-transcoder-bin.vala \
+ rygel-l16-transcoder-bin.vala \
+ rygel-wma-transcoder.vala \
+ rygel-wma-transcoder-bin.vala \
rygel-wmv-transcoder.vala \
- rygel-aac-transcoder.vala \
- rygel-avc-transcoder.vala \
+ rygel-wmv-transcoder-bin.vala \
rygel-gst-utils.vala \
rygel-media-receiver-registrar.vala \
rygel-log-handler.vala \
@@ -121,7 +123,6 @@ rygel_LDADD = \
librygel-configuration.a \
$(RYGEL_COMMON_LDADD) \
$(LIBGUPNP_DLNA_LIBS) \
- $(GST_PBU_LIBS) \
$(GIO_LIBS) \
$(LIBSOUP_LIBS)
diff --git a/src/rygel/rygel-cmdline-config.vala b/src/rygel/rygel-cmdline-config.vala
index ba53c73..372c933 100644
--- a/src/rygel/rygel-cmdline-config.vala
+++ b/src/rygel/rygel-cmdline-config.vala
@@ -41,8 +41,6 @@ internal class Rygel.CmdlineConfig : GLib.Object, Configuration {
private static bool no_mp2ts_trans;
private static bool no_lpcm_trans;
private static bool no_wmv_trans;
- private static bool no_aac_trans;
- private static bool no_avc_trans;
private static bool disallow_upload;
private static bool disallow_deletion;
@@ -87,10 +85,6 @@ internal class Rygel.CmdlineConfig : GLib.Object, Configuration {
"Disable Linear PCM transcoder", null },
{ "disable-wmv-transcoder", 'w', 0, OptionArg.NONE, ref no_wmv_trans,
"Disable WMV transcoder", null },
- { "disable-aac-transcoder", 'a', 0, OptionArg.NONE, ref no_aac_trans,
- "Disable AAC_ISO_320 transcoder", null },
- { "disable-avc-transcoder", 'z', 0, OptionArg.NONE, ref no_avc_trans,
- "Disable AVC_MP4 transcoder", null },
{ "disallow-upload", 'U', 0, OptionArg.NONE,
ref disallow_upload, "Disallow upload", null },
{ "disallow-deletion", 'D', 0, OptionArg.NONE,
@@ -215,22 +209,6 @@ internal class Rygel.CmdlineConfig : GLib.Object, Configuration {
}
}
- public bool get_aac_transcoder () throws GLib.Error {
- if (!no_aac_trans) {
- throw new ConfigurationError.NO_VALUE_SET (_("No value available"));
- } else {
- return false;
- }
- }
-
- public bool get_avc_transcoder () throws GLib.Error {
- if (!no_avc_trans) {
- throw new ConfigurationError.NO_VALUE_SET (_("No value available"));
- } else {
- return false;
- }
- }
-
public bool get_allow_upload () throws GLib.Error {
if (!disallow_upload) {
throw new ConfigurationError.NO_VALUE_SET (_("No value available"));
diff --git a/src/rygel/rygel-configuration.vala b/src/rygel/rygel-configuration.vala
index ca11265..9f59d7c 100644
--- a/src/rygel/rygel-configuration.vala
+++ b/src/rygel/rygel-configuration.vala
@@ -47,10 +47,6 @@ public interface Rygel.Configuration : GLib.Object {
public abstract bool get_wmv_transcoder () throws GLib.Error;
- public abstract bool get_aac_transcoder () throws GLib.Error;
-
- public abstract bool get_avc_transcoder () throws GLib.Error;
-
public abstract bool get_allow_upload () throws GLib.Error;
public abstract bool get_allow_deletion () throws GLib.Error;
diff --git a/src/rygel/rygel-environment-config.vala b/src/rygel/rygel-environment-config.vala
index c2c8bff..e9695aa 100644
--- a/src/rygel/rygel-environment-config.vala
+++ b/src/rygel/rygel-environment-config.vala
@@ -41,8 +41,6 @@ internal class Rygel.EnvironmentConfig : GLib.Object, Configuration {
private static string MP2TS_TRANSCODING_ENV = DISABLE_PREFIX +
"_MP2TS_TRANS";
private static string WMV_TRANSCODING_ENV = DISABLE_PREFIX + "_WMV_TRANS";
- private static string AAC_TRANSCODING_ENV = DISABLE_PREFIX + "_AAC_TRANS";
- private static string AVC_TRANSCODING_ENV = DISABLE_PREFIX + "_AVC_TRANS";
private static string DISALLOW_UPLOAD_ENV = DISABLE_PREFIX + "_UPLOAD";
private static string DISALLOW_DELETION_ENV = DISABLE_PREFIX + "_DELETION";
private static string LOG_LEVELS_ENV = RYGEL_PREFIX + "_LOG";
@@ -87,14 +85,6 @@ internal class Rygel.EnvironmentConfig : GLib.Object, Configuration {
return !this.get_bool_variable (WMV_TRANSCODING_ENV);
}
- public bool get_aac_transcoder () throws GLib.Error {
- return !this.get_bool_variable (AAC_TRANSCODING_ENV);
- }
-
- public bool get_avc_transcoder () throws GLib.Error {
- return !this.get_bool_variable (AVC_TRANSCODING_ENV);
- }
-
public bool get_lpcm_transcoder () throws GLib.Error {
return !this.get_bool_variable (LPCM_TRANSCODING_ENV);
}
diff --git a/src/rygel/rygel-gst-utils.vala b/src/rygel/rygel-gst-utils.vala
index 6232baf..45521a8 100644
--- a/src/rygel/rygel-gst-utils.vala
+++ b/src/rygel/rygel-gst-utils.vala
@@ -42,6 +42,11 @@ internal abstract class Rygel.GstUtils {
return element;
}
+ public static void post_error (Element dest, Error error) {
+ Message msg = new Message.error (dest, error, error.message);
+ dest.post_message (msg);
+ }
+
public static ClockTime time_from_string (string str) {
uint64 hours, minutes, seconds;
diff --git a/src/rygel/rygel-l16-transcoder-bin.vala b/src/rygel/rygel-l16-transcoder-bin.vala
new file mode 100644
index 0000000..685ec4a
--- /dev/null
+++ b/src/rygel/rygel-l16-transcoder-bin.vala
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ * <zeeshan ali nokia com>
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rygel 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ */
+
+using Gst;
+
+/**
+ * A Gst.Bin derivative that implements transcoding of any type of media (using
+ * decodebin2) to linear PCM audio.
+ */
+internal class Rygel.L16TranscoderBin : Gst.Bin {
+ private const string DECODEBIN = "decodebin2";
+
+ private const string AUDIO_SRC_PAD = "audio-src-pad";
+ private const string AUDIO_SINK_PAD = "audio-sink-pad";
+
+ private dynamic Element audio_enc;
+
+ public L16TranscoderBin (MediaItem item,
+ Element src,
+ L16Transcoder transcoder) throws Error {
+ Element decodebin = GstUtils.create_element (DECODEBIN, DECODEBIN);
+
+ this.audio_enc = transcoder.create_encoder (item,
+ AUDIO_SRC_PAD,
+ AUDIO_SINK_PAD);
+
+ this.add_many (src, decodebin, this.audio_enc);
+ src.link (decodebin);
+
+ var src_pad = this.audio_enc.get_static_pad (AUDIO_SRC_PAD);
+ var ghost = new GhostPad (null, src_pad);
+ this.add_pad (ghost);
+
+ decodebin.pad_added.connect (this.decodebin_pad_added);
+ }
+
+ private void decodebin_pad_added (Element decodebin, Pad new_pad) {
+ Pad enc_pad = this.audio_enc.get_pad (AUDIO_SINK_PAD);
+ if (!new_pad.can_link (enc_pad)) {
+ return;
+ }
+
+ if (new_pad.link (enc_pad) != PadLinkReturn.OK) {
+ GstUtils.post_error (this,
+ new GstError.LINK
+ (_("Failed to link pad %s to %s"),
+ new_pad.name,
+ enc_pad.name));
+ return;
+ }
+ }
+}
diff --git a/src/rygel/rygel-l16-transcoder.vala b/src/rygel/rygel-l16-transcoder.vala
index 9dcf8d5..22cbe8b 100644
--- a/src/rygel/rygel-l16-transcoder.vala
+++ b/src/rygel/rygel-l16-transcoder.vala
@@ -24,8 +24,14 @@ using Gst;
using GUPnP;
using Gee;
+internal enum Endianness {
+ LITTLE = ByteOrder.LITTLE_ENDIAN,
+ BIG = ByteOrder.BIG_ENDIAN
+}
+
/**
- * Transcoder for linear PCM audio (LPCM).
+ * Transcoder for linear PCM audio (LPCM). This element uses L16TrancoderBin for
+ * actual transcoding.
*/
internal class Rygel.L16Transcoder : Rygel.Transcoder {
private const int CHANNELS = 2;
@@ -33,14 +39,28 @@ internal class Rygel.L16Transcoder : Rygel.Transcoder {
private const int WIDTH = 16;
private const int DEPTH = 16;
private const bool SIGNED = true;
- private const int ENDIANNESS = ByteOrder.BIG_ENDIAN;
- public L16Transcoder () {
+ private Endianness endianness;
+
+ private const string AUDIO_CONVERT = "audioconvert";
+ private const string AUDIO_RESAMPLE = "audioresample";
+ private const string AUDIO_RATE = "audiorate";
+ private const string CAPS_FILTER = "capsfilter";
+
+ public L16Transcoder (Endianness endianness) {
var mime_type = "audio/L" + L16Transcoder.WIDTH.to_string () +
";rate=" + L16Transcoder.FREQUENCY.to_string () +
";channels=" + L16Transcoder.CHANNELS.to_string ();
base (mime_type, "LPCM", AudioItem.UPNP_CLASS);
+
+ this.endianness = endianness;
+ }
+
+ public override Element create_source (MediaItem item,
+ Element src)
+ throws Error {
+ return new L16TranscoderBin (item, src, this);
}
public override DIDLLiteResource? add_resource (DIDLLiteItem didl_item,
@@ -85,20 +105,43 @@ internal class Rygel.L16Transcoder : Rygel.Transcoder {
return distance;
}
- protected override EncodingProfile get_encoding_profile () {
- var caps_str = "audio/x-raw-int" +
- ",channels=" + CHANNELS.to_string () +
- ",rate=" + FREQUENCY.to_string () +
- ",width=" + WIDTH.to_string () +
- ",depth=" + DEPTH.to_string () +
- ",signed=" + SIGNED.to_string () +
- ",endianness=" + ENDIANNESS.to_string();
- var format = Caps.from_string (caps_str);
-
- var encoding_profile = new EncodingAudioProfile (format,
- null,
- null,
- 1);
- return encoding_profile;
+ public Element create_encoder (MediaItem item,
+ string? src_pad_name,
+ string? sink_pad_name)
+ throws Error {
+ dynamic Element convert1 = GstUtils.create_element (AUDIO_CONVERT,
+ null);
+ dynamic Element resample = GstUtils.create_element (AUDIO_RESAMPLE,
+ AUDIO_RESAMPLE);
+ dynamic Element audiorate = GstUtils.create_element (AUDIO_RATE, null);
+ dynamic Element convert2 = GstUtils.create_element (AUDIO_CONVERT,
+ null);
+ dynamic Element capsfilter = GstUtils.create_element (CAPS_FILTER,
+ CAPS_FILTER);
+
+ var bin = new Bin ("l16-encoder-bin");
+ bin.add_many (convert1, resample, audiorate, convert2, capsfilter);
+
+ capsfilter.caps = new Caps.simple (
+ "audio/x-raw-int",
+ "channels", typeof (int), CHANNELS,
+ "rate", typeof (int), FREQUENCY,
+ "width", typeof (int), WIDTH,
+ "depth", typeof (int), DEPTH,
+ "signed", typeof (bool), SIGNED,
+ "endianness", typeof (int),
+ this.endianness);
+
+ convert1.link_many (resample, audiorate, convert2, capsfilter);
+
+ var pad = convert1.get_static_pad ("sink");
+ var ghost = new GhostPad (sink_pad_name, pad);
+ bin.add_pad (ghost);
+
+ pad = capsfilter.get_static_pad ("src");
+ ghost = new GhostPad (src_pad_name, pad);
+ bin.add_pad (ghost);
+
+ return bin;
}
}
diff --git a/src/rygel/rygel-meta-config.vala b/src/rygel/rygel-meta-config.vala
index 762c036..507f9d3 100644
--- a/src/rygel/rygel-meta-config.vala
+++ b/src/rygel/rygel-meta-config.vala
@@ -219,44 +219,6 @@ public class Rygel.MetaConfig : GLib.Object, Configuration {
return val;
}
- public bool get_aac_transcoder () throws GLib.Error {
- bool val = true;
- bool unavailable = true;
-
- foreach (var config in this.configs) {
- try {
- val = config.get_aac_transcoder ();
- unavailable = false;
- break;
- } catch (GLib.Error err) {}
- }
-
- if (unavailable) {
- throw new ConfigurationError.NO_VALUE_SET (_("No value available"));
- }
-
- return val;
- }
-
- public bool get_avc_transcoder () throws GLib.Error {
- bool val = true;
- bool unavailable = true;
-
- foreach (var config in this.configs) {
- try {
- val = config.get_avc_transcoder ();
- unavailable = false;
- break;
- } catch (GLib.Error err) {}
- }
-
- if (unavailable) {
- throw new ConfigurationError.NO_VALUE_SET (_("No value available"));
- }
-
- return val;
- }
-
public bool get_allow_upload () throws GLib.Error {
bool val = true;
bool unavailable = true;
diff --git a/src/rygel/rygel-mp2ts-transcoder-bin.vala b/src/rygel/rygel-mp2ts-transcoder-bin.vala
new file mode 100644
index 0000000..b4c4f3a
--- /dev/null
+++ b/src/rygel/rygel-mp2ts-transcoder-bin.vala
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ * <zeeshan ali nokia com>
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rygel 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ */
+
+using Gst;
+
+/**
+ * A Gst.Bin derivative that implements transcoding of any type of media (using
+ * decodebin2) to mpeg transport stream containing mpeg 2 video and mp2 audio.
+ */
+internal class Rygel.MP2TSTranscoderBin : Gst.Bin {
+ private const string DECODEBIN = "decodebin2";
+ private const string MUXER = "mpegtsmux";
+
+ private const string AUDIO_ENC_SINK = "audio-enc-sink-pad";
+ private const string VIDEO_ENC_SINK = "sink";
+
+ private dynamic Element audio_enc;
+ private dynamic Element video_enc;
+ private dynamic Element muxer;
+
+ public MP2TSTranscoderBin (MediaItem item,
+ Element src,
+ MP2TSTranscoder transcoder)
+ throws Error {
+ dynamic Element decodebin = GstUtils.create_element (DECODEBIN,
+ DECODEBIN);
+ var mp3_transcoder = new MP3Transcoder (MP3Layer.TWO);
+ this.audio_enc = mp3_transcoder.create_encoder (item,
+ null,
+ AUDIO_ENC_SINK);
+ this.video_enc = transcoder.create_encoder (item, null, VIDEO_ENC_SINK);
+ this.muxer = GstUtils.create_element (MUXER, MUXER);
+
+ this.add_many (src,
+ decodebin,
+ this.audio_enc,
+ this.video_enc,
+ this.muxer);
+ src.link (decodebin);
+
+ var src_pad = muxer.get_static_pad ("src");
+ var ghost = new GhostPad (null, src_pad);
+ this.add_pad (ghost);
+
+ decodebin.pad_added.connect (this.decodebin_pad_added);
+ decodebin.autoplug_continue.connect (this.autoplug_continue);
+ }
+
+ private bool autoplug_continue (Element decodebin,
+ Pad new_pad,
+ Caps caps) {
+ var muxer_pad = this.muxer.get_compatible_pad (new_pad, null);
+
+ if (muxer_pad == null) {
+ return true;
+ } else {
+ return new_pad.link (muxer_pad) != PadLinkReturn.OK;
+ }
+ }
+
+ private void decodebin_pad_added (Element decodebin, Pad new_pad) {
+ Element encoder;
+ Pad enc_pad;
+
+ var audio_enc_pad = this.audio_enc.get_pad (AUDIO_ENC_SINK);
+ var video_enc_pad = this.video_enc.get_pad (VIDEO_ENC_SINK);
+
+ // Check which encoder to use
+ if (new_pad.can_link (audio_enc_pad)) {
+ encoder = this.audio_enc;
+ enc_pad = audio_enc_pad;
+ } else if (new_pad.can_link (video_enc_pad)) {
+ encoder = this.video_enc;
+ enc_pad = video_enc_pad;
+ } else {
+ return;
+ }
+
+ encoder.link (this.muxer);
+
+ if (new_pad.link (enc_pad) != PadLinkReturn.OK) {
+ var error = new GstError.LINK (_("Failed to link pad %s to %s"),
+ new_pad.name,
+ enc_pad.name);
+ GstUtils.post_error (this, error);
+ }
+ }
+}
diff --git a/src/rygel/rygel-mp2ts-transcoder.vala b/src/rygel/rygel-mp2ts-transcoder.vala
index 8cf7864..79f4eaa 100644
--- a/src/rygel/rygel-mp2ts-transcoder.vala
+++ b/src/rygel/rygel-mp2ts-transcoder.vala
@@ -31,10 +31,10 @@ internal enum Rygel.MP2TSProfile {
/**
* Transcoder for mpeg transport stream containing mpeg 2 video and mp2 audio.
+ * This element uses MP2TSTrancoderBin for actual transcoding.
*/
internal class Rygel.MP2TSTranscoder : Rygel.Transcoder {
private const int VIDEO_BITRATE = 3000;
- private const int AUDIO_BITRATE = 256;
// HD
private const int[] WIDTH = {720, 1280};
@@ -43,6 +43,11 @@ internal class Rygel.MP2TSTranscoder : Rygel.Transcoder {
private const string[] PROFILES = {"MPEG_TS_SD_EU_ISO", "MPEG_TS_HD_NA_ISO"};
private const int BITRATE = 3000000;
+ private const string VIDEO_ENCODER = "ffenc_mpeg2video";
+ private const string COLORSPACE_CONVERT = "ffmpegcolorspace";
+ private const string VIDEO_RATE = "videorate";
+ private const string VIDEO_SCALE = "videoscale";
+
private MP2TSProfile profile;
public MP2TSTranscoder (MP2TSProfile profile) {
@@ -51,6 +56,12 @@ internal class Rygel.MP2TSTranscoder : Rygel.Transcoder {
this.profile = profile;
}
+ public override Element create_source (MediaItem item,
+ Element src)
+ throws Error {
+ return new MP2TSTranscoderBin (item, src, this);
+ }
+
public override DIDLLiteResource? add_resource (DIDLLiteItem didl_item,
MediaItem item,
TranscodeManager manager)
@@ -61,7 +72,7 @@ internal class Rygel.MP2TSTranscoder : Rygel.Transcoder {
resource.width = WIDTH[profile];
resource.height = HEIGHT[profile];
- resource.bitrate = (VIDEO_BITRATE + AUDIO_BITRATE) * 1000 / 8;
+ resource.bitrate = (VIDEO_BITRATE + MP3Transcoder.BITRATE) * 1000 / 8;
return resource;
}
@@ -89,45 +100,67 @@ internal class Rygel.MP2TSTranscoder : Rygel.Transcoder {
return distance;
}
- protected override EncodingProfile get_encoding_profile () {
- var cont_format = Caps.from_string ("video/mpegts," +
- "systemstream=true," +
- "packetsize=188");
- var framerate = "framerate=(fraction)%d/1".printf
- (FRAME_RATE[this.profile]);
-
- var video_format = Caps.from_string ("video/mpeg," +
- "mpegversion=2," +
- "systemstream=false," +
- framerate);
- var restriction = "video/x-raw-yuv," +
- framerate + "," +
- "width=%d,".printf (HEIGHT[this.profile]) +
- "height=%d".printf (WIDTH[this.profile]);
-
- var video_restriction = Caps.from_string (restriction);
-
- var audio_format = Caps.from_string ("audio/mpeg," +
- "mpegversion=1," +
- "layer=2");
-
- var enc_container_profile = new EncodingContainerProfile ("container",
- null,
- cont_format,
- null);
- var enc_video_profile = new EncodingVideoProfile (video_format,
- null,
- video_restriction,
- 1);
- var enc_audio_profile = new EncodingAudioProfile (audio_format,
- null,
- null,
- 1);
-
- // FIXME: We should use the preset to set bitrate
- enc_container_profile.add_profile (enc_video_profile);
- enc_container_profile.add_profile (enc_audio_profile);
-
- return enc_container_profile;
+ public Element create_encoder (MediaItem item,
+ string? src_pad_name,
+ string? sink_pad_name)
+ throws Error {
+ var videorate = GstUtils.create_element (VIDEO_RATE, VIDEO_RATE);
+ var videoscale = GstUtils.create_element (VIDEO_SCALE, VIDEO_SCALE);
+ var convert = GstUtils.create_element (COLORSPACE_CONVERT,
+ COLORSPACE_CONVERT);
+ dynamic Element encoder = GstUtils.create_element (VIDEO_ENCODER,
+ VIDEO_ENCODER);
+
+ encoder.bitrate = (int) VIDEO_BITRATE * 1000;
+
+ var bin = new Bin ("video-encoder-bin");
+ bin.add_many (videorate, videoscale, convert, encoder);
+
+ convert.link_many (videoscale, videorate);
+
+ int pixel_w;
+ int pixel_h;
+
+ var video_item = item as VideoItem;
+
+ if (video_item.pixel_width > 0 && video_item.pixel_height > 0) {
+ pixel_w = video_item.width *
+ HEIGHT[this.profile] *
+ video_item.pixel_width;
+ pixel_h = video_item.height *
+ WIDTH[this.profile] *
+ video_item.pixel_height;
+ } else {
+ // Original pixel-ratio not provided, lets just use 1:1
+ pixel_w = 1;
+ pixel_h = 1;
+ }
+
+ var caps = new Caps.simple ("video/x-raw-yuv",
+ "width",
+ typeof (int),
+ WIDTH[this.profile],
+ "height",
+ typeof (int),
+ HEIGHT[this.profile],
+ "framerate",
+ typeof (Fraction),
+ FRAME_RATE[this.profile],
+ 1,
+ "pixel-aspect-ratio",
+ typeof (Fraction),
+ pixel_w,
+ pixel_h);
+ videorate.link_filtered (encoder, caps);
+
+ var pad = convert.get_static_pad ("sink");
+ var ghost = new GhostPad (sink_pad_name, pad);
+ bin.add_pad (ghost);
+
+ pad = encoder.get_static_pad ("src");
+ ghost = new GhostPad (src_pad_name, pad);
+ bin.add_pad (ghost);
+
+ return bin;
}
}
diff --git a/src/rygel/rygel-mp3-transcoder-bin.vala b/src/rygel/rygel-mp3-transcoder-bin.vala
new file mode 100644
index 0000000..f3d5401
--- /dev/null
+++ b/src/rygel/rygel-mp3-transcoder-bin.vala
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ * <zeeshan ali nokia com>
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rygel 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ */
+
+using Gst;
+
+internal enum Rygel.MP3Layer {
+ TWO = 1,
+ THREE = 2
+}
+
+/**
+ * A Gst.Bin derivative that implements transcoding of any type of media (using
+ * decodebin2) to mpeg 1 layer 2 and 3 format.
+ */
+internal class Rygel.MP3TranscoderBin : Gst.Bin {
+ private const string DECODEBIN = "decodebin2";
+
+ private const string AUDIO_SRC_PAD = "audio-src-pad";
+ private const string AUDIO_SINK_PAD = "audio-sink-pad";
+
+ private dynamic Element audio_enc;
+
+ public MP3TranscoderBin (MediaItem item,
+ Element src,
+ MP3Transcoder transcoder) throws Error {
+ Element decodebin = GstUtils.create_element (DECODEBIN, DECODEBIN);
+
+ this.audio_enc = transcoder.create_encoder (item,
+ AUDIO_SRC_PAD,
+ AUDIO_SINK_PAD);
+
+ this.add_many (src, decodebin, this.audio_enc);
+ src.link (decodebin);
+
+ var src_pad = this.audio_enc.get_static_pad (AUDIO_SRC_PAD);
+ var ghost = new GhostPad (null, src_pad);
+ this.add_pad (ghost);
+
+ decodebin.pad_added.connect (this.decodebin_pad_added);
+ }
+
+ private void decodebin_pad_added (Element decodebin, Pad new_pad) {
+ Pad enc_pad = this.audio_enc.get_pad (AUDIO_SINK_PAD);
+ if (!new_pad.can_link (enc_pad)) {
+ return;
+ }
+
+ if (new_pad.link (enc_pad) != PadLinkReturn.OK) {
+ var error = new GstError.LINK (_("Failed to link pad %s to %s"),
+ new_pad.name,
+ enc_pad.name);
+ GstUtils.post_error (this, error);
+
+ return;
+ }
+ }
+}
diff --git a/src/rygel/rygel-mp3-transcoder.vala b/src/rygel/rygel-mp3-transcoder.vala
index d72daf9..d3463dd 100644
--- a/src/rygel/rygel-mp3-transcoder.vala
+++ b/src/rygel/rygel-mp3-transcoder.vala
@@ -25,13 +25,29 @@ using GUPnP;
using Gee;
/**
- * Transcoder for mpeg 1 layer 3 audio.
+ * Transcoder for mpeg 1 layer 2 and 3 audio. This element uses MP3TrancoderBin
+ * for actual transcoding.
*/
internal class Rygel.MP3Transcoder : Rygel.Transcoder {
public const int BITRATE = 256;
- public MP3Transcoder () {
+ private const string[] AUDIO_ENCODER = {null, "twolame", "lame"};
+ private const string AUDIO_PARSER = "mp3parse";
+
+ private const string CONVERT_SINK_PAD = "convert-sink-pad";
+
+ private MP3Layer layer;
+
+ public MP3Transcoder (MP3Layer layer) {
base ("audio/mpeg", "MP3", AudioItem.UPNP_CLASS);
+
+ this.layer = layer;
+ }
+
+ public override Element create_source (MediaItem item,
+ Element src)
+ throws Error {
+ return new MP3TranscoderBin (item, src, this);
}
public override DIDLLiteResource? add_resource (DIDLLiteItem didl_item,
@@ -63,11 +79,39 @@ internal class Rygel.MP3Transcoder : Rygel.Transcoder {
return distance;
}
- protected override EncodingProfile get_encoding_profile () {
- var format = Caps.from_string ("audio/mpeg,mpegversion=1,layer=3");
- // FIXME: We should use the preset to set bitrate
- var encoding_profile = new EncodingAudioProfile (format, null, null, 1);
+ public Element create_encoder (MediaItem item,
+ string? src_pad_name,
+ string? sink_pad_name)
+ throws Error {
+ var l16_transcoder = new L16Transcoder (Endianness.LITTLE);
+ dynamic Element convert = l16_transcoder.create_encoder
+ (item, null, CONVERT_SINK_PAD);
+ dynamic Element encoder = GstUtils.create_element
+ (AUDIO_ENCODER[this.layer],
+ AUDIO_ENCODER[this.layer]);
+ dynamic Element parser = GstUtils.create_element (AUDIO_PARSER,
+ AUDIO_PARSER);
+
+ if (this.layer == MP3Layer.THREE) {
+ // Best quality
+ encoder.quality = 0;
+ }
+
+ encoder.bitrate = BITRATE;
+
+ var bin = new Bin ("mp3-encoder-bin");
+ bin.add_many (convert, encoder, parser);
+
+ convert.link_many (encoder, parser);
+
+ var pad = convert.get_static_pad (CONVERT_SINK_PAD);
+ var ghost = new GhostPad (sink_pad_name, pad);
+ bin.add_pad (ghost);
+
+ pad = parser.get_static_pad ("src");
+ ghost = new GhostPad (src_pad_name, pad);
+ bin.add_pad (ghost);
- return encoding_profile;
+ return bin;
}
}
diff --git a/src/rygel/rygel-transcode-manager.vala b/src/rygel/rygel-transcode-manager.vala
index 47ac9e6..f6dff1e 100644
--- a/src/rygel/rygel-transcode-manager.vala
+++ b/src/rygel/rygel-transcode-manager.vala
@@ -51,8 +51,6 @@ internal abstract class Rygel.TranscodeManager : GLib.Object {
var mp3_transcoder = true;
var mp2ts_transcoder = true;
var wmv_transcoder = true;
- var aac_transcoder = true;
- var avc_transcoder = true;
try {
transcoding = config.get_transcoding ();
@@ -62,18 +60,16 @@ internal abstract class Rygel.TranscodeManager : GLib.Object {
mp3_transcoder = config.get_mp3_transcoder ();
mp2ts_transcoder = config.get_mp2ts_transcoder ();
wmv_transcoder = config.get_wmv_transcoder ();
- aac_transcoder = config.get_aac_transcoder ();
- avc_transcoder = config.get_avc_transcoder ();
}
} catch (Error err) {}
if (transcoding) {
if (lpcm_transcoder) {
- transcoders.add (new L16Transcoder ());
+ transcoders.add (new L16Transcoder (Endianness.BIG));
}
if (mp3_transcoder) {
- transcoders.add (new MP3Transcoder ());
+ transcoders.add (new MP3Transcoder (MP3Layer.THREE));
}
if (mp2ts_transcoder) {
@@ -84,14 +80,6 @@ internal abstract class Rygel.TranscodeManager : GLib.Object {
if (wmv_transcoder) {
transcoders.add (new WMVTranscoder ());
}
-
- if (aac_transcoder) {
- transcoders.add (new AACTranscoder ());
- }
-
- if (avc_transcoder) {
- transcoders.add (new AVCTranscoder ());
- }
}
}
diff --git a/src/rygel/rygel-transcoder.vala b/src/rygel/rygel-transcoder.vala
index cc4da30..af73891 100644
--- a/src/rygel/rygel-transcoder.vala
+++ b/src/rygel/rygel-transcoder.vala
@@ -27,18 +27,12 @@ using Gee;
/**
* The base Transcoder class. Each implementation derives from it and must
- * implement get_distance and get_encoding_profile methods.
+ * at least implement create_source method.
*/
internal abstract class Rygel.Transcoder : GLib.Object {
public string mime_type { get; protected set; }
public string dlna_profile { get; protected set; }
- private const string DECODE_BIN = "decodebin2";
- private const string ENCODE_BIN = "encodebin";
-
- dynamic Element decoder;
- dynamic Element encoder;
-
// Primary UPnP item class that this transcoder is meant for, doesn't
// necessarily mean it cant be used for other classes.
public string upnp_class { get; protected set; }
@@ -59,29 +53,8 @@ internal abstract class Rygel.Transcoder : GLib.Object {
*
* @return the new transcoding source
*/
- public virtual Element create_source (MediaItem item,
- Element src) throws Error {
- this.decoder = GstUtils.create_element (DECODE_BIN,
- DECODE_BIN);
- this.encoder = GstUtils.create_element (ENCODE_BIN,
- ENCODE_BIN);
-
- encoder.profile = this.get_encoding_profile ();
-
- var bin = new Bin ("transcoder-source");
- bin.add_many (src, decoder, encoder);
-
- src.link (decoder);
-
- decoder.pad_added.connect (this.on_decoder_pad_added);
- decoder.autoplug_continue.connect (this.on_autoplug_continue);
-
- var pad = encoder.get_static_pad ("src");
- var ghost = new GhostPad (null, pad);
- bin.add_pad (ghost);
-
- return bin;
- }
+ public abstract Element create_source (MediaItem item,
+ Element src) throws Error;
public virtual DIDLLiteResource? add_resource (DIDLLiteItem didl_item,
MediaItem item,
@@ -133,57 +106,11 @@ internal abstract class Rygel.Transcoder : GLib.Object {
*/
public abstract uint get_distance (MediaItem item);
- /**
- * Gets the Gst.EncodingProfile for this transcoder.
- *
- * @return the Gst.EncodingProfile for this transcoder.
- */
- protected abstract EncodingProfile get_encoding_profile ();
-
protected bool mime_type_is_a (string mime_type1, string mime_type2) {
string content_type1 = ContentType.get_mime_type (mime_type1);
string content_type2 = ContentType.get_mime_type (mime_type2);
return ContentType.is_a (content_type1, content_type2);
}
-
- private bool on_autoplug_continue (Element decodebin,
- Pad new_pad,
- Caps caps) {
- Gst.Pad sinkpad = null;
-
- Signal.emit_by_name (this.encoder, "request-pad", caps, out sinkpad);
- if (sinkpad == null) {
- return true;
- }
-
- return false;
- }
-
- private void on_decoder_pad_added (Element decodebin, Pad new_pad) {
- Gst.Pad sinkpad;
-
- sinkpad = this.encoder.get_compatible_pad (new_pad, null);
-
- if (sinkpad == null) {
- var caps = new_pad.get_caps ();
- Signal.emit_by_name (this.encoder, "request-pad", caps, out sinkpad);
- }
-
- if (sinkpad == null) {
- debug ("No compatible encodebin pad found for pad '%s', ignoring..",
- new_pad.name);
-
- return;
- }
-
- var pad_link_ok = (new_pad.link (sinkpad) == PadLinkReturn.OK);
- if (!pad_link_ok) {
- warning ("Failed to link pad '%s' to '%s'",
- new_pad.name,
- sinkpad.name);
- }
-
- return;
- }
}
+
diff --git a/src/rygel/rygel-user-config.vala b/src/rygel/rygel-user-config.vala
index e7e867c..3829b91 100644
--- a/src/rygel/rygel-user-config.vala
+++ b/src/rygel/rygel-user-config.vala
@@ -39,8 +39,6 @@ public class Rygel.UserConfig : GLib.Object, Configuration {
public static const string MP2TS_TRANSCODER_KEY = "enable-mp2ts-transcoder";
public static const string LPCM_TRANSCODER_KEY = "enable-lpcm-transcoder";
public static const string WMV_TRANSCODER_KEY = "enable-wmv-transcoder";
- public static const string AAC_TRANSCODER_KEY = "enable-aac-transcoder";
- public static const string AVC_TRANSCODER_KEY = "enable-avc-transcoder";
public static const string ALLOW_UPLOAD_KEY = "allow-upload";
public static const string ALLOW_DELETION_KEY = "allow-deletion";
public static const string LOG_LEVELS_KEY = "log-level";
@@ -91,14 +89,6 @@ public class Rygel.UserConfig : GLib.Object, Configuration {
return this.get_bool ("general", WMV_TRANSCODER_KEY);
}
- public bool get_aac_transcoder () throws GLib.Error {
- return this.get_bool ("general", AAC_TRANSCODER_KEY);
- }
-
- public bool get_avc_transcoder () throws GLib.Error {
- return this.get_bool ("general", AVC_TRANSCODER_KEY);
- }
-
public bool get_allow_upload () throws GLib.Error {
return this.get_bool ("general", ALLOW_UPLOAD_KEY);
}
diff --git a/src/rygel/rygel-wma-transcoder-bin.vala b/src/rygel/rygel-wma-transcoder-bin.vala
new file mode 100644
index 0000000..467eb22
--- /dev/null
+++ b/src/rygel/rygel-wma-transcoder-bin.vala
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2009 Jens Georg <mail jensge org>.
+ *
+ * Author: Jens Georg <mail jensge org>
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rygel 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ */
+using Gst;
+
+internal class Rygel.WMATranscoderBin : Gst.Bin {
+ private const string DECODEBIN = "decodebin2";
+
+ private const string AUDIO_SRC_PAD = "audio-src-pad";
+ private const string AUDIO_SINK_PAD = "audio-sink-pad";
+
+ private dynamic Element audio_enc;
+
+ public WMATranscoderBin (MediaItem item,
+ Element src,
+ WMATranscoder transcoder) throws Error {
+ Element decodebin = GstUtils.create_element (DECODEBIN, DECODEBIN);
+
+ this.audio_enc = transcoder.create_encoder (item,
+ AUDIO_SRC_PAD,
+ AUDIO_SINK_PAD);
+
+ this.add_many (src, decodebin, this.audio_enc);
+ src.link (decodebin);
+
+ var src_pad = this.audio_enc.get_static_pad (AUDIO_SRC_PAD);
+ var ghost = new GhostPad (null, src_pad);
+ this.add_pad (ghost);
+
+ decodebin.pad_added.connect (this.decodebin_pad_added);
+ }
+
+ private void decodebin_pad_added (Element decodebin, Pad new_pad) {
+ Pad enc_pad = this.audio_enc.get_pad (AUDIO_SINK_PAD);
+ if (!new_pad.can_link (enc_pad)) {
+ return;
+ }
+
+ if (new_pad.link (enc_pad) != PadLinkReturn.OK) {
+ var error = new GstError.LINK (_("Failed to link pad %s to %s"),
+ new_pad.name,
+ enc_pad.name);
+ GstUtils.post_error (this, error);
+
+ return;
+ }
+ }
+}
diff --git a/src/rygel/rygel-wma-transcoder.vala b/src/rygel/rygel-wma-transcoder.vala
new file mode 100644
index 0000000..30652a0
--- /dev/null
+++ b/src/rygel/rygel-wma-transcoder.vala
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2009 Jens Georg <mail jensge org>.
+ *
+ * Author: Jens Georg <mail jensge org>
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rygel 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ */
+using Gst;
+using GUPnP;
+
+internal class Rygel.WMATranscoder : Rygel.Transcoder {
+ public const int BITRATE = 64;
+
+ private const string CONVERT_SINK_PAD = "convert-sink-pad";
+
+ public WMATranscoder () {
+ base ("audio/x-wma", "WMA", AudioItem.UPNP_CLASS);
+ }
+
+ public override Element create_source (MediaItem item,
+ Element src)
+ throws Error {
+ return new WMATranscoderBin (item, src, this);
+ }
+
+ public override DIDLLiteResource? add_resource (DIDLLiteItem didl_item,
+ MediaItem item,
+ TranscodeManager manager)
+ throws Error {
+ var resource = base.add_resource (didl_item, item, manager);
+ if (resource == null)
+ return null;
+
+ // Convert bitrate to bytes/second
+ resource.bitrate = BITRATE * 1000 / 8;
+
+ return resource;
+ }
+
+ public override uint get_distance (MediaItem item) {
+ if (!(item is AudioItem)) {
+ return uint.MAX;
+ }
+
+ var audio_item = item as AudioItem;
+ var distance = uint.MIN;
+
+ if (audio_item.bitrate > 0) {
+ distance += (audio_item.bitrate - BITRATE).abs ();
+ }
+
+ return distance;
+ }
+
+ public Element create_encoder (MediaItem item,
+ string? src_pad_name,
+ string? sink_pad_name)
+ throws Error {
+ var l16_transcoder = new L16Transcoder (Endianness.LITTLE);
+ dynamic Element convert = l16_transcoder.create_encoder (
+ item,
+ null,
+ CONVERT_SINK_PAD);
+
+ dynamic Element encoder = GstUtils.create_element ("ffenc_wmav2",
+ "ffenc_wmav2");
+ encoder.bitrate = BITRATE * 1000;
+
+ var bin = new Bin("wma-encoder-bin");
+ bin.add_many (convert, encoder);
+ convert.link (encoder);
+
+ var pad = convert.get_static_pad (CONVERT_SINK_PAD);
+ var ghost = new GhostPad (sink_pad_name, pad);
+ bin.add_pad (ghost);
+
+ pad = encoder.get_static_pad ("src");
+ ghost = new GhostPad (src_pad_name, pad);
+ bin.add_pad (ghost);
+
+ return bin;
+ }
+}
diff --git a/src/rygel/rygel-wmv-transcoder-bin.vala b/src/rygel/rygel-wmv-transcoder-bin.vala
new file mode 100644
index 0000000..f50d010
--- /dev/null
+++ b/src/rygel/rygel-wmv-transcoder-bin.vala
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2009 Jens Georg <mail jensge org>.
+ *
+ * Author: Jens Georg <mail jensge org>
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rygel 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ */
+using Gst;
+
+/**
+ * A Gst.Bin derivative that implements transcoding of any type of media (using
+ * decodebin2) to mpeg transport stream containing mpeg 2 video and mp2 audio.
+ */
+internal class Rygel.WMVTranscoderBin : Gst.Bin {
+ private const string DECODEBIN = "decodebin2";
+ private const string MUXER = "ffmux_asf";
+
+ private const string AUDIO_ENC_SINK = "audio-enc-sink-pad";
+ private const string VIDEO_ENC_SINK = "sink";
+
+ private dynamic Element audio_enc;
+ private dynamic Element video_enc;
+ private dynamic Element muxer;
+
+ public WMVTranscoderBin (MediaItem item,
+ Element src,
+ WMVTranscoder transcoder)
+ throws Error {
+ dynamic Element decodebin = GstUtils.create_element (DECODEBIN,
+ DECODEBIN);
+ var wma_transcoder = new WMATranscoder ();
+ this.audio_enc = wma_transcoder.create_encoder (item,
+ null,
+ AUDIO_ENC_SINK);
+ this.video_enc = transcoder.create_encoder (item, null, VIDEO_ENC_SINK);
+ this.muxer = GstUtils.create_element (MUXER, MUXER);
+
+ this.add_many (src,
+ decodebin,
+ this.audio_enc,
+ this.video_enc,
+ this.muxer);
+ src.link (decodebin);
+
+ var src_pad = muxer.get_static_pad ("src");
+ var ghost = new GhostPad (null, src_pad);
+ this.add_pad (ghost);
+
+ decodebin.pad_added.connect (this.decodebin_pad_added);
+ decodebin.autoplug_continue.connect (this.autoplug_continue);
+ }
+
+ private bool autoplug_continue (Element decodebin,
+ Pad new_pad,
+ Caps caps) {
+ var muxer_pad = this.muxer.get_compatible_pad (new_pad, null);
+
+ if (muxer_pad == null) {
+ return true;
+ } else {
+ return new_pad.link (muxer_pad) != PadLinkReturn.OK;
+ }
+ }
+
+ private void decodebin_pad_added (Element decodebin, Pad new_pad) {
+ Element encoder;
+ Pad enc_pad;
+
+ var audio_enc_pad = this.audio_enc.get_pad (AUDIO_ENC_SINK);
+ var video_enc_pad = this.video_enc.get_pad (VIDEO_ENC_SINK);
+
+ // Check which encoder to use
+ if (new_pad.can_link (audio_enc_pad)) {
+ encoder = this.audio_enc;
+ enc_pad = audio_enc_pad;
+ } else if (new_pad.can_link (video_enc_pad)) {
+ encoder = this.video_enc;
+ enc_pad = video_enc_pad;
+ } else {
+ return;
+ }
+
+ encoder.link (this.muxer);
+
+ if (new_pad.link (enc_pad) != PadLinkReturn.OK) {
+ var error = new GstError.LINK (_("Failed to link pad %s to %s"),
+ new_pad.name,
+ enc_pad.name);
+ GstUtils.post_error (this, error);
+ }
+ }
+}
diff --git a/src/rygel/rygel-wmv-transcoder.vala b/src/rygel/rygel-wmv-transcoder.vala
index 9f93a99..18a4744 100644
--- a/src/rygel/rygel-wmv-transcoder.vala
+++ b/src/rygel/rygel-wmv-transcoder.vala
@@ -23,14 +23,24 @@ using Gst;
using GUPnP;
internal class Rygel.WMVTranscoder : Rygel.Transcoder {
- private const int BITRATE = 1200000;
private const int VIDEO_BITRATE = 1200;
- private const int AUDIO_BITRATE = 64;
+ private const int BITRATE = 1200000;
+
+ private const string VIDEO_ENCODER = "ffenc_wmv1";
+ private const string COLORSPACE_CONVERT = "ffmpegcolorspace";
+ private const string VIDEO_RATE = "videorate";
+ private const string VIDEO_SCALE = "videoscale";
public WMVTranscoder () {
base ("video/x-ms-wmv", "WMVHIGH_FULL", VideoItem.UPNP_CLASS);
}
+ public override Element create_source (MediaItem item,
+ Element src)
+ throws Error {
+ return new WMVTranscoderBin (item, src, this);
+ }
+
public override DIDLLiteResource? add_resource (DIDLLiteItem didl_item,
MediaItem item,
TranscodeManager manager)
@@ -43,7 +53,7 @@ internal class Rygel.WMVTranscoder : Rygel.Transcoder {
resource.width = video_item.width;
resource.height = video_item.height;
- resource.bitrate = (VIDEO_BITRATE + AUDIO_BITRATE) * 1000 / 8;
+ resource.bitrate = (VIDEO_BITRATE + WMATranscoder.BITRATE) * 1000 / 8;
return resource;
}
@@ -63,29 +73,30 @@ internal class Rygel.WMVTranscoder : Rygel.Transcoder {
return distance;
}
- protected override EncodingProfile get_encoding_profile () {
- var container_format = Caps.from_string ("video/x-ms-asf,parsed=true");
-
- var video_format = Caps.from_string ("video/x-wmv,wmvversion=1");
- var audio_format = Caps.from_string ("audio/x-wma,channels=2,wmaversion=1");
-
- var enc_container_profile = new EncodingContainerProfile("container",
- null,
- container_format,
- null);
- var enc_video_profile = new EncodingVideoProfile (video_format,
- null,
- null,
- 1);
- var enc_audio_profile = new EncodingAudioProfile (audio_format,
- null,
- null,
- 1);
-
- // FIXME: We should use the preset to set bitrate
- enc_container_profile.add_profile (enc_video_profile);
- enc_container_profile.add_profile (enc_audio_profile);
-
- return enc_container_profile;
+ public Element create_encoder (MediaItem item,
+ string? src_pad_name,
+ string? sink_pad_name)
+ throws Error {
+ var convert = GstUtils.create_element (COLORSPACE_CONVERT,
+ COLORSPACE_CONVERT);
+ dynamic Element encoder = GstUtils.create_element (VIDEO_ENCODER,
+ VIDEO_ENCODER);
+
+ encoder.bitrate = (int) VIDEO_BITRATE * 1000;
+
+ var bin = new Bin ("video-encoder-bin");
+ bin.add_many (convert, encoder);
+ convert.link (encoder);
+
+ var pad = convert.get_static_pad ("sink");
+ var ghost = new GhostPad (sink_pad_name, pad);
+ bin.add_pad (ghost);
+
+ pad = encoder.get_static_pad ("src");
+ ghost = new GhostPad (src_pad_name, pad);
+ bin.add_pad (ghost);
+
+ return bin;
}
+
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]