+++ /dev/null
-/*
- * 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;
- }
- }
-}
using Gee;
/**
- * Transcoder for mpeg 1 layer 2 and 3 audio. This element uses MP3TrancoderBin
- * for actual transcoding.
+ * Transcoder for mpeg 1 layer 3 audio.
*/
internal class Rygel.MP3Transcoder : Rygel.Transcoder {
public const int BITRATE = 256;
- private const string[] AUDIO_ENCODER = {null, "twolame", "lame"};
- private const string AUDIO_PARSER = "mp3parse";
+ private const string DECODE_BIN = "decodebin2";
+ private const string ENCODE_BIN = "encodebin";
- private const string CONVERT_SINK_PAD = "convert-sink-pad";
-
- private MP3Layer layer;
-
- public MP3Transcoder (MP3Layer layer) {
+ public MP3Transcoder () {
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);
+ dynamic Element decoder = GstUtils.create_element (DECODE_BIN,
+ DECODE_BIN);
+ dynamic Element encoder = GstUtils.create_element (ENCODE_BIN,
+ ENCODE_BIN);
+
+ encoder.profile = this.get_encoding_profile ();
+
+ var bin = new Bin ("mp3-transcoder-bin");
+ bin.add_many (src, decoder, encoder);
+
+ src.link (decoder);
+
+ decoder.pad_added.connect (this.on_decoder_pad_added);
+
+ var pad = encoder.get_static_pad ("src");
+ var ghost = new GhostPad (null, pad);
+ bin.add_pad (ghost);
+
+ return bin;
}
public override DIDLLiteResource? add_resource (DIDLLiteItem didl_item,
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
- (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;
- }
+ private void on_decoder_pad_added (Element decodebin, Pad new_pad) {
+ var bin = decodebin.get_parent () as Bin;
+ assert (bin != null);
- encoder.bitrate = BITRATE;
+ var encoder = bin.get_by_name (ENCODE_BIN);
+ assert (encoder != null);
- var bin = new Bin ("mp3-encoder-bin");
- bin.add_many (convert, encoder, parser);
+ var encoder_pad = encoder.get_compatible_pad (new_pad, null);
+ if (encoder_pad == null) {
+ debug ("No compatible encodebin pad found for pad '%s', ignoring..",
+ new_pad.name);
- convert.link_many (encoder, parser);
+ return;
+ } else {
+ debug ("pad '%s' with caps '%s' is compatible with '%s'",
+ new_pad.name,
+ new_pad.get_caps ().to_string (),
+ encoder_pad.name);
+ }
- var pad = convert.get_static_pad (CONVERT_SINK_PAD);
- var ghost = new GhostPad (sink_pad_name, pad);
- bin.add_pad (ghost);
+ if (new_pad.link (encoder_pad) != PadLinkReturn.OK) {
+ var error = new GstError.LINK (_("Failed to link pad %s to %s"),
+ new_pad.name,
+ encoder_pad.name);
+ GstUtils.post_error (bin, error);
+ }
+ }
- pad = parser.get_static_pad ("src");
- ghost = new GhostPad (src_pad_name, pad);
- bin.add_pad (ghost);
+ private 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);
- return bin;
+ return encoding_profile;
}
}