[rygel] core: Add WMV transcoder
- From: Zeeshan Ali Khattak <zeeshanak src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rygel] core: Add WMV transcoder
- Date: Mon, 22 Mar 2010 17:06:35 +0000 (UTC)
commit 500c15dab6bc540c8718b23255930abcb817c746
Author: Jens Georg <mail jensge org>
Date: Tue Dec 29 14:51:09 2009 +0100
core: Add WMV transcoder
src/rygel/Makefile.am | 4 +
src/rygel/rygel-cmdline-config.vala | 7 ++
src/rygel/rygel-configuration.vala | 2 +
src/rygel/rygel-meta-config.vala | 19 ++++++
src/rygel/rygel-transcode-manager.vala | 4 +
src/rygel/rygel-user-config.vala | 9 +++
src/rygel/rygel-wma-transcoder-bin.vala | 66 +++++++++++++++++++
src/rygel/rygel-wma-transcoder.vala | 102 ++++++++++++++++++++++++++++++
src/rygel/rygel-wmv-transcoder-bin.vala | 94 +++++++++++++++++++++++++++
src/rygel/rygel-wmv-transcoder.vala | 105 +++++++++++++++++++++++++++++++
10 files changed, 412 insertions(+), 0 deletions(-)
---
diff --git a/src/rygel/Makefile.am b/src/rygel/Makefile.am
index 395a8a3..ccd19b0 100644
--- a/src/rygel/Makefile.am
+++ b/src/rygel/Makefile.am
@@ -91,6 +91,10 @@ VAPI_SOURCE_FILES = rygel-configuration.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-wmv-transcoder-bin.vala \
rygel-gst-utils.vala \
rygel-media-db.vala \
rygel-metadata-extractor.vala \
diff --git a/src/rygel/rygel-cmdline-config.vala b/src/rygel/rygel-cmdline-config.vala
index 3da94fa..7ee7541 100644
--- a/src/rygel/rygel-cmdline-config.vala
+++ b/src/rygel/rygel-cmdline-config.vala
@@ -40,6 +40,7 @@ public class Rygel.CmdlineConfig : GLib.Object, Configuration {
private static bool no_mp3_trans;
private static bool no_mp2ts_trans;
private static bool no_lpcm_trans;
+ private static bool no_wmv_trans;
private static LogLevel log_level = LogLevel.INVALID;
@@ -75,6 +76,8 @@ public class Rygel.CmdlineConfig : GLib.Object, Configuration {
"Disable mpeg2 transport stream transcoder", null },
{ "disable-lpcm-transcoder", 'l', 0, OptionArg.NONE, ref no_lpcm_trans,
"Disable Linear PCM transcoder", null },
+ { "disable-wmv-transcoder", 'l', 0, OptionArg.NONE, ref no_wmv_trans,
+ "Disable WMV transcoder", null },
{ "log-level", 'g', 0, OptionArg.INT, ref log_level,
"Log level. 1=critical,2=error,3=warning,4=message/info,5=debug",
"N" },
@@ -165,6 +168,10 @@ public class Rygel.CmdlineConfig : GLib.Object, Configuration {
}
}
+ public bool get_wmv_transcoder () throws GLib.Error {
+ return !no_wmv_trans;
+ }
+
public LogLevel get_log_level () throws GLib.Error {
if (this.log_level == LogLevel.INVALID) {
throw new ConfigurationError.NO_VALUE_SET ("No value available");
diff --git a/src/rygel/rygel-configuration.vala b/src/rygel/rygel-configuration.vala
index bb9937d..a27a7ab 100644
--- a/src/rygel/rygel-configuration.vala
+++ b/src/rygel/rygel-configuration.vala
@@ -47,6 +47,8 @@ public interface Rygel.Configuration : GLib.Object {
public abstract bool get_lpcm_transcoder () throws GLib.Error;
+ public abstract bool get_wmv_transcoder () throws GLib.Error;
+
public abstract LogLevel get_log_level () throws GLib.Error;
public abstract bool get_enabled (string section) throws GLib.Error;
diff --git a/src/rygel/rygel-meta-config.vala b/src/rygel/rygel-meta-config.vala
index 90e2d4e..34390ee 100644
--- a/src/rygel/rygel-meta-config.vala
+++ b/src/rygel/rygel-meta-config.vala
@@ -191,6 +191,25 @@ public class Rygel.MetaConfig : GLib.Object, Configuration {
return val;
}
+ public bool get_wmv_transcoder () throws GLib.Error {
+ bool val = true;
+ bool unavailable = true;
+
+ foreach (var config in this.configs) {
+ try {
+ val = config.get_wmv_transcoder ();
+ unavailable = false;
+ break;
+ } catch (GLib.Error err) {}
+ }
+
+ if (unavailable) {
+ throw new ConfigurationError.NO_VALUE_SET ("No value available");
+ }
+
+ return val;
+ }
+
public LogLevel get_log_level () throws GLib.Error {
LogLevel val = LogLevel.DEFAULT;
bool unavailable = true;
diff --git a/src/rygel/rygel-transcode-manager.vala b/src/rygel/rygel-transcode-manager.vala
index 055a875..cedecfb 100644
--- a/src/rygel/rygel-transcode-manager.vala
+++ b/src/rygel/rygel-transcode-manager.vala
@@ -49,6 +49,10 @@ internal abstract class Rygel.TranscodeManager : GLib.Object {
transcoders.add (new MP2TSTranscoder(MP2TSProfile.SD));
transcoders.add (new MP2TSTranscoder(MP2TSProfile.HD));
}
+
+ if (config.get_wmv_transcoder ()) {
+ transcoders.add (new WMVTranscoder ());
+ }
}
}
diff --git a/src/rygel/rygel-user-config.vala b/src/rygel/rygel-user-config.vala
index d778182..11bef33 100644
--- a/src/rygel/rygel-user-config.vala
+++ b/src/rygel/rygel-user-config.vala
@@ -39,6 +39,7 @@ public class Rygel.UserConfig : GLib.Object, Configuration {
"enable-mp2ts-transcoder";
protected static const string LPCM_TRANSCODER_KEY =
"enable-lpcm-transcoder";
+ protected static const string WMV_TRANSCODER_KEY = "enable-wmv-transcoder";
protected static const string LOG_LEVEL_KEY = "log-level";
private const string DBUS_SERVICE = "org.freedesktop.DBus";
@@ -122,6 +123,14 @@ public class Rygel.UserConfig : GLib.Object, Configuration {
this.set_bool ("general", LPCM_TRANSCODER_KEY, value);
}
+ public bool get_wmv_transcoder () throws GLib.Error {
+ return this.get_bool ("general", WMV_TRANSCODER_KEY);
+ }
+
+ public void set_wmv_transcoder (bool value) {
+ this.set_bool ("general", WMV_TRANSCODER_KEY, value);
+ }
+
public LogLevel get_log_level () throws GLib.Error {
return (LogLevel) this.get_int ("general",
LOG_LEVEL_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..c4c3520
--- /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 += 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-wma-transcoder.vala b/src/rygel/rygel-wma-transcoder.vala
new file mode 100644
index 0000000..22869e9
--- /dev/null
+++ b/src/rygel/rygel-wma-transcoder.vala
@@ -0,0 +1,102 @@
+/*
+ * 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 {
+ private const int BITRATE = 64;
+
+ private const string CONVERT_SINK_PAD = "convert-sink-pad";
+
+ public WMATranscoder () {
+ base ("audio/x-wma", "WMA", MediaItem.AUDIO_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.upnp_class.has_prefix (MediaItem.IMAGE_CLASS)) {
+ return uint.MAX;
+ }
+
+ uint distance;
+
+ if (item.upnp_class.has_prefix (MediaItem.AUDIO_CLASS)) {
+ distance = uint.MIN;
+
+ if (item.bitrate > 0) {
+ distance += (item.bitrate - BITRATE).abs ();
+ }
+ } else {
+ distance = uint.MAX / 2;
+ }
+
+ 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..3f3c386
--- /dev/null
+++ b/src/rygel/rygel-wmv-transcoder-bin.vala
@@ -0,0 +1,94 @@
+/*
+ * 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 {
+ 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 += this.decodebin_pad_added;
+ }
+
+ 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) {
+ 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-wmv-transcoder.vala b/src/rygel/rygel-wmv-transcoder.vala
new file mode 100644
index 0000000..118e68f
--- /dev/null
+++ b/src/rygel/rygel-wmv-transcoder.vala
@@ -0,0 +1,105 @@
+/*
+ * 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.WMVTranscoder : Rygel.Transcoder {
+ private const int VIDEO_BITRATE = 1200;
+ 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", "WMV", MediaItem.VIDEO_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)
+ throws Error {
+ var resource = base.add_resource (didl_item, item, manager);
+ if (resource == null)
+ return null;
+
+ resource.width = item.width;
+ resource.height = item.height;
+ resource.bitrate = (VIDEO_BITRATE + WMATranscoder.BITRATE) * 1000 / 8;
+
+ return resource;
+ }
+
+ public override uint get_distance (MediaItem item) {
+ if (item.upnp_class.has_prefix (MediaItem.IMAGE_CLASS)) {
+ return uint.MAX;
+ }
+
+ uint distance;
+
+ if (item.upnp_class.has_prefix (MediaItem.VIDEO_CLASS)) {
+ distance = uint.MIN;
+
+ if (item.bitrate > 0) {
+ distance += (item.bitrate - BITRATE).abs ();
+ }
+ } else {
+ distance = uint.MAX / 2;
+ }
+
+ return distance;
+ }
+
+ 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]