[rygel/rygel-0-12: 1/2] core: Revert encodebin-based transcoder



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]