[libdmapsharing] Update transcoders and add (still broken) QuickTime transcoder
- From: W. Michael Petullo <wmpetullo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libdmapsharing] Update transcoders and add (still broken) QuickTime transcoder
- Date: Tue, 25 Jun 2013 01:10:56 +0000 (UTC)
commit 4caf1556bda4b3260263d90575040c64be3a717c
Author: W. Michael Petullo <mike flyn org>
Date: Mon Jun 24 20:10:32 2013 -0500
Update transcoders and add (still broken) QuickTime transcoder
Signed-off-by: W. Michael Petullo <mike flyn org>
libdmapsharing/Makefile.am | 2 +
libdmapsharing/daap-share.c | 8 +-
libdmapsharing/dmap-gst-input-stream.c | 3 +
libdmapsharing/dmap-gst-mp3-input-stream.c | 34 +++---
libdmapsharing/dmap-gst-qt-input-stream.c | 192 ++++++++++++++++++++++++++++
libdmapsharing/dmap-gst-qt-input-stream.h | 66 ++++++++++
libdmapsharing/dmap-gst-wav-input-stream.c | 41 +++---
7 files changed, 308 insertions(+), 38 deletions(-)
---
diff --git a/libdmapsharing/Makefile.am b/libdmapsharing/Makefile.am
index 5cc3fc2..f461991 100644
--- a/libdmapsharing/Makefile.am
+++ b/libdmapsharing/Makefile.am
@@ -44,6 +44,7 @@ if USE_GSTREAMERAPP
libdmapsharing_3_0_la_SOURCES += \
dmap-gst-input-stream.c \
dmap-gst-mp3-input-stream.c \
+ dmap-gst-qt-input-stream.c \
dmap-gst-wav-input-stream.c \
gst-util.c
endif
@@ -100,6 +101,7 @@ noinst_HEADERS = \
dmap-mdns-avahi.h \
dmap-utils.h \
dmap-gst-mp3-input-stream.h \
+ dmap-gst-qt-input-stream.h \
dmap-gst-wav-input-stream.h \
gst-util.h
diff --git a/libdmapsharing/daap-share.c b/libdmapsharing/daap-share.c
index d676afa..9e9a8c9 100644
--- a/libdmapsharing/daap-share.c
+++ b/libdmapsharing/daap-share.c
@@ -163,6 +163,8 @@ mime_to_format (const gchar * transcode_mimetype)
return g_strdup ("wav");
} else if (!strcmp (transcode_mimetype, "audio/mp3")) {
return g_strdup ("mp3");
+ } else if (!strcmp (transcode_mimetype, "video/quicktime")) {
+ return g_strdup ("mp4");
} else
return NULL;
}
@@ -418,8 +420,10 @@ send_chunked_file (SoupServer * server, SoupMessage * message,
g_object_get (record, "format", &format, NULL);
// Not presently transcoding videos (see also same comments elsewhere).
- if (has_video || transcode_mimetype == NULL
- || !strcmp (format, mime_to_format (transcode_mimetype))) {
+ char *format2 = NULL;
+ if (has_video
+ || transcode_mimetype == NULL
+ || (format2 = mime_to_format (transcode_mimetype)) && !strcmp (format, format2)) {
g_debug ("Not transcoding");
cd->stream = stream;
#ifdef HAVE_GSTREAMERAPP
diff --git a/libdmapsharing/dmap-gst-input-stream.c b/libdmapsharing/dmap-gst-input-stream.c
index 793d150..ecb07af 100644
--- a/libdmapsharing/dmap-gst-input-stream.c
+++ b/libdmapsharing/dmap-gst-input-stream.c
@@ -276,6 +276,9 @@ dmap_gst_input_stream_new (const gchar * transcode_mimetype,
} else if (!strcmp (transcode_mimetype, "audio/wav")) {
stream = G_INPUT_STREAM (dmap_gst_wav_input_stream_new
(src_stream));
+ } else if (!strcmp (transcode_mimetype, "video/quicktime")) {
+ stream = G_INPUT_STREAM (dmap_gst_qt_input_stream_new
+ (src_stream));
} else {
g_warning ("Transcode format %s not supported",
transcode_mimetype);
diff --git a/libdmapsharing/dmap-gst-mp3-input-stream.c b/libdmapsharing/dmap-gst-mp3-input-stream.c
index 0ca4dcf..dc60af2 100644
--- a/libdmapsharing/dmap-gst-mp3-input-stream.c
+++ b/libdmapsharing/dmap-gst-mp3-input-stream.c
@@ -34,7 +34,7 @@ struct DMAPGstMP3InputStreamPrivate
GstElement *src;
GstElement *decode;
GstElement *convert;
- GstElement *encode;
+ GstElement *audio_encode;
GstElement *sink;
};
@@ -59,13 +59,6 @@ pad_added_cb (GstElement * element,
(stream->priv->convert, "sink")));
gst_pad_link (pad, conv_pad);
-
- if (gst_element_link_many (stream->priv->convert,
- stream->priv->encode,
- stream->priv->sink,
- NULL) == FALSE) {
- g_warning ("Error linking convert and sink elements");
- }
} else {
g_warning ("Could not link GStreamer pipeline.");
}
@@ -95,8 +88,8 @@ dmap_gst_mp3_input_stream_new (GInputStream * src_stream)
gst_element_factory_make ("audioconvert", "convert");
g_assert (GST_IS_ELEMENT (stream->priv->convert));
- stream->priv->encode = gst_element_factory_make ("lamemp3enc", "encode");
- g_assert (GST_IS_ELEMENT (stream->priv->encode));
+ stream->priv->audio_encode = gst_element_factory_make ("lamemp3enc", "audioencode");
+ g_assert (GST_IS_ELEMENT (stream->priv->audio_encode));
stream->priv->sink = gst_element_factory_make ("appsink", "sink");
g_assert (GST_IS_ELEMENT (stream->priv->sink));
@@ -105,22 +98,31 @@ dmap_gst_mp3_input_stream_new (GInputStream * src_stream)
stream->priv->src,
stream->priv->decode,
stream->priv->convert,
- stream->priv->encode, stream->priv->sink, NULL);
+ stream->priv->audio_encode,
+ stream->priv->sink,
+ NULL);
- if (gst_element_link (stream->priv->src, stream->priv->decode) ==
- FALSE) {
+ if (gst_element_link (stream->priv->src,
+ stream->priv->decode) == FALSE) {
g_warning ("Error linking source and decode elements");
}
+ if (gst_element_link_many (stream->priv->convert,
+ stream->priv->audio_encode,
+ stream->priv->sink,
+ NULL) == FALSE) {
+ g_warning ("Error linking convert through sink elements");
+ }
+
g_assert (G_IS_INPUT_STREAM (src_stream));
g_object_set (G_OBJECT (stream->priv->src), "stream", src_stream,
NULL);
/* quality=9 is important for fast, realtime transcoding: */
// FIXME: Causes crash; why?
- // g_object_set (G_OBJECT (stream->priv->encode), "quality", 9, NULL);
- g_object_set (G_OBJECT (stream->priv->encode), "bitrate", 128, NULL);
- g_object_set (G_OBJECT (stream->priv->encode), "vbr", 0, NULL);
+ // g_object_set (G_OBJECT (stream->priv->audio_encode), "quality", 9, NULL);
+ g_object_set (G_OBJECT (stream->priv->audio_encode), "bitrate", 128, NULL);
+ g_object_set (G_OBJECT (stream->priv->audio_encode), "vbr", 0, NULL);
g_signal_connect (stream->priv->decode, "pad-added",
G_CALLBACK (pad_added_cb), stream);
diff --git a/libdmapsharing/dmap-gst-qt-input-stream.c b/libdmapsharing/dmap-gst-qt-input-stream.c
new file mode 100644
index 0000000..eff4253
--- /dev/null
+++ b/libdmapsharing/dmap-gst-qt-input-stream.c
@@ -0,0 +1,192 @@
+/*
+ * DMAPGstQtInputStream class: Open a URI using dmap_gst_qt_input_stream_new ().
+ * Data is decoded using GStreamer and is then reencoded as a QuickTime video
+ * stream by the class's read operations.
+ *
+ * Copyright (C) 2009 W. Michael Petullo <mike flyn org>
+ *
+ * This library 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.1 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <gst/gst.h>
+#include <gst/app/gstappsink.h>
+
+#include "dmap-gst-qt-input-stream.h"
+#include "gst-util.h"
+
+#define GST_APP_MAX_BUFFERS 1024
+
+struct DMAPGstQtInputStreamPrivate
+{
+ GstElement *pipeline;
+ GstElement *src;
+ GstElement *decode;
+ GstElement *convert;
+ GstElement *audio_encode;
+ GstElement *mux;
+ GstElement *sink;
+};
+
+/* FIXME: See note in dmap-gst-input-stream.h */
+void dmap_gst_input_stream_new_buffer_cb (GstElement * element,
+ DMAPGstInputStream * stream);
+
+static void
+pad_added_cb (GstElement * element,
+ GstPad * pad,
+ DMAPGstQtInputStream * stream)
+{
+ /* Link remaining pad after decodebin2 does its magic. */
+ GstPad *conv_pad;
+
+ conv_pad = gst_element_get_static_pad (stream->priv->convert, "sink");
+ g_assert (conv_pad != NULL);
+
+ if (pads_compatible (pad, conv_pad)) {
+ g_assert (!GST_PAD_IS_LINKED
+ (gst_element_get_static_pad
+ (stream->priv->convert, "sink")));
+
+ gst_pad_link (pad, conv_pad);
+ } else {
+ g_warning ("Could not link GStreamer pipeline.");
+ }
+}
+
+GInputStream *
+dmap_gst_qt_input_stream_new (GInputStream * src_stream)
+{
+ GstStateChangeReturn sret;
+ GstState state;
+ DMAPGstQtInputStream *stream;
+
+ stream = DMAP_GST_QT_INPUT_STREAM (g_object_new
+ (DMAP_TYPE_GST_QT_INPUT_STREAM,
+ NULL));
+
+ stream->priv->pipeline = gst_pipeline_new ("pipeline");
+
+ stream->priv->src = gst_element_factory_make ("giostreamsrc", "src");
+ g_assert (GST_IS_ELEMENT (stream->priv->src));
+
+ stream->priv->decode =
+ gst_element_factory_make ("decodebin", "decode");
+ g_assert (GST_IS_ELEMENT (stream->priv->decode));
+
+ stream->priv->convert =
+ gst_element_factory_make ("audioconvert", "convert");
+ g_assert (GST_IS_ELEMENT (stream->priv->convert));
+
+ stream->priv->audio_encode = gst_element_factory_make ("avenc_aac", "audioencode");
+ g_assert (GST_IS_ELEMENT (stream->priv->audio_encode));
+
+ stream->priv->mux = gst_element_factory_make ("qtmux", "mux");
+ g_assert (GST_IS_ELEMENT (stream->priv->mux));
+
+ stream->priv->sink = gst_element_factory_make ("appsink", "sink");
+ g_assert (GST_IS_ELEMENT (stream->priv->sink));
+
+ gst_bin_add_many (GST_BIN (stream->priv->pipeline),
+ stream->priv->src,
+ stream->priv->decode,
+ stream->priv->convert,
+ stream->priv->audio_encode,
+ stream->priv->mux,
+ stream->priv->sink,
+ NULL);
+
+ if (gst_element_link (stream->priv->src,
+ stream->priv->decode) == FALSE) {
+ g_warning ("Error linking source and decode elements");
+ }
+
+ if (gst_element_link_many (stream->priv->convert,
+ stream->priv->audio_encode,
+ stream->priv->mux,
+ stream->priv->sink,
+ NULL) == FALSE) {
+ g_warning ("Error linking convert through sink elements");
+ }
+
+ g_assert (G_IS_INPUT_STREAM (src_stream));
+ g_object_set (G_OBJECT (stream->priv->src), "stream", src_stream,
+ NULL);
+
+ g_signal_connect (stream->priv->decode, "pad-added",
+ G_CALLBACK (pad_added_cb), stream);
+
+ g_object_set (G_OBJECT (stream->priv->sink), "emit-signals", TRUE,
+ "sync", FALSE, NULL);
+ gst_app_sink_set_max_buffers (GST_APP_SINK (stream->priv->sink),
+ GST_APP_MAX_BUFFERS);
+ gst_app_sink_set_drop (GST_APP_SINK (stream->priv->sink), FALSE);
+
+ g_signal_connect (stream->priv->sink, "new-sample",
+ G_CALLBACK (dmap_gst_input_stream_new_buffer_cb),
+ stream);
+
+ /* FIXME: this technique is shared with dmapd-daap-share.c */
+ sret = gst_element_set_state (stream->priv->pipeline,
+ GST_STATE_PLAYING);
+ if (GST_STATE_CHANGE_ASYNC == sret) {
+ if (GST_STATE_CHANGE_SUCCESS !=
+ gst_element_get_state (GST_ELEMENT
+ (stream->priv->pipeline), &state,
+ NULL, 5 * GST_SECOND)) {
+ g_warning ("State change failed for stream.");
+ }
+ } else if (sret != GST_STATE_CHANGE_SUCCESS) {
+ g_warning ("Could not read stream.");
+ }
+
+ g_assert (G_IS_SEEKABLE (stream));
+ return G_INPUT_STREAM (stream);
+}
+
+static void
+dmap_gst_qt_input_stream_kill_pipeline (DMAPGstInputStream * stream)
+{
+ DMAPGstQtInputStream *qt_stream =
+ DMAP_GST_QT_INPUT_STREAM (stream);
+
+ // FIXME: It seems that I need to send an EOS, because QuickTime writes
+ // its headers after encoding the streams, but this does not yet work.
+ gst_element_send_event(qt_stream->priv->pipeline, gst_event_new_eos());
+
+ gst_element_set_state (qt_stream->priv->pipeline, GST_STATE_NULL);
+ gst_object_unref (GST_OBJECT (qt_stream->priv->pipeline));
+}
+
+G_DEFINE_TYPE (DMAPGstQtInputStream, dmap_gst_qt_input_stream,
+ DMAP_TYPE_GST_INPUT_STREAM);
+
+static void
+dmap_gst_qt_input_stream_class_init (DMAPGstQtInputStreamClass * klass)
+{
+ DMAPGstInputStreamClass *parent_class =
+ DMAP_GST_INPUT_STREAM_CLASS (klass);
+
+ g_type_class_add_private (klass,
+ sizeof (DMAPGstQtInputStreamPrivate));
+
+ parent_class->kill_pipeline = dmap_gst_qt_input_stream_kill_pipeline;
+}
+
+static void
+dmap_gst_qt_input_stream_init (DMAPGstQtInputStream * stream)
+{
+ stream->priv = DMAP_GST_QT_INPUT_STREAM_GET_PRIVATE (stream);
+
+}
diff --git a/libdmapsharing/dmap-gst-qt-input-stream.h b/libdmapsharing/dmap-gst-qt-input-stream.h
new file mode 100644
index 0000000..8e2bda6
--- /dev/null
+++ b/libdmapsharing/dmap-gst-qt-input-stream.h
@@ -0,0 +1,66 @@
+/*
+ * DMAPGstQtInputStream class: Open a URI using dmap_gst_qt_input_stream_new ().
+ * Data is decoded using GStreamer and is then reencoded as a QuickTime video
+ * stream by the class's read operations.
+ *
+ * Copyright (C) 2008 W. Michael Petullo <mike flyn org>
+ *
+ * This library 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.1 of the License, or (at your option) any later version.
+ *
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __DMAP_GST_QT_INPUT_STREAM
+#define __DMAP_GST_QT_INPUT_STREAM
+
+#include <gio/gio.h>
+
+#include "dmap-gst-input-stream.h"
+
+G_BEGIN_DECLS
+#define DMAP_TYPE_GST_QT_INPUT_STREAM (dmap_gst_qt_input_stream_get_type ())
+#define DMAP_GST_QT_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), \
+ DMAP_TYPE_GST_QT_INPUT_STREAM, \
+ DMAPGstQtInputStream))
+#define DMAP_GST_QT_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), \
+ DMAP_TYPE_GST_QT_INPUT_STREAM, \
+ DMAPGstQtInputStreamClass))
+#define IS_DMAP_GST_QT_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), \
+ DMAP_TYPE_GST_QT_INPUT_STREAM))
+#define IS_DMAP_GST_QT_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), \
+ DMAP_TYPE_GST_QT_INPUT_STREAM_CLASS))
+#define DMAP_GST_QT_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), \
+ DMAP_TYPE_GST_QT_INPUT_STREAM, \
+ DMAPGstQtInputStreamClass))
+#define DMAP_GST_QT_INPUT_STREAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+ DMAP_TYPE_GST_QT_INPUT_STREAM, \
+ DMAPGstQtInputStreamPrivate))
+typedef struct DMAPGstQtInputStreamPrivate DMAPGstQtInputStreamPrivate;
+
+typedef struct
+{
+ DMAPGstInputStream parent;
+ DMAPGstQtInputStreamPrivate *priv;
+} DMAPGstQtInputStream;
+
+typedef struct
+{
+ DMAPGstInputStreamClass parent;
+} DMAPGstQtInputStreamClass;
+
+GType dmap_gst_qt_input_stream_get_type (void);
+
+GInputStream *dmap_gst_qt_input_stream_new (GInputStream * stream);
+
+G_END_DECLS
+#endif /* __DMAP_GST_QT_INPUT_STREAM */
diff --git a/libdmapsharing/dmap-gst-wav-input-stream.c b/libdmapsharing/dmap-gst-wav-input-stream.c
index 8f8afd8..c7817ba 100644
--- a/libdmapsharing/dmap-gst-wav-input-stream.c
+++ b/libdmapsharing/dmap-gst-wav-input-stream.c
@@ -35,7 +35,7 @@ struct DMAPGstWAVInputStreamPrivate
GstElement *decode;
GstElement *convert;
GstCaps *filter;
- GstElement *encode;
+ GstElement *audio_encode;
GstElement *sink;
};
@@ -60,18 +60,6 @@ pad_added_cb (GstElement * element,
(stream->priv->convert, "sink")));
gst_pad_link (pad, conv_pad);
-
- if (gst_element_link_filtered (stream->priv->convert,
- stream->priv->encode,
- stream->priv->filter) ==
- FALSE) {
- g_warning
- ("Error linking convert and encode elements");
- }
- if (gst_element_link (stream->priv->encode,
- stream->priv->sink) == FALSE) {
- g_warning ("Error linking encode and sink elements");
- }
} else {
g_warning ("Could not link GStreamer pipeline.");
}
@@ -94,7 +82,7 @@ dmap_gst_wav_input_stream_new (GInputStream * src_stream)
g_assert (GST_IS_ELEMENT (stream->priv->src));
stream->priv->decode =
- gst_element_factory_make ("decodebin2", "decode");
+ gst_element_factory_make ("decodebin", "decode");
g_assert (GST_IS_ELEMENT (stream->priv->decode));
stream->priv->convert =
@@ -107,8 +95,8 @@ dmap_gst_wav_input_stream_new (GInputStream * src_stream)
"width", G_TYPE_INT, 16,
"depth", G_TYPE_INT, 16,
NULL);
- stream->priv->encode = gst_element_factory_make ("wavenc", "encode");
- g_assert (GST_IS_ELEMENT (stream->priv->encode));
+ stream->priv->audio_encode = gst_element_factory_make ("wavenc", "audioencode");
+ g_assert (GST_IS_ELEMENT (stream->priv->audio_encode));
stream->priv->sink = gst_element_factory_make ("appsink", "sink");
g_assert (GST_IS_ELEMENT (stream->priv->sink));
@@ -117,11 +105,24 @@ dmap_gst_wav_input_stream_new (GInputStream * src_stream)
stream->priv->src,
stream->priv->decode,
stream->priv->convert,
- stream->priv->encode, stream->priv->sink, NULL);
+ stream->priv->audio_encode,
+ stream->priv->sink,
+ NULL);
+
+ if (gst_element_link (stream->priv->src,
+ stream->priv->decode) == FALSE) {
+ g_warning ("Error linking source through decode elements");
+ }
+
+ if (gst_element_link_filtered (stream->priv->convert,
+ stream->priv->audio_encode,
+ stream->priv->filter) == FALSE) {
+ g_warning ("Error linking convert and audioencode elements");
+ }
- if (gst_element_link (stream->priv->src, stream->priv->decode) ==
- FALSE) {
- g_warning ("Error linking source and decode elements");
+ if (gst_element_link (stream->priv->audio_encode,
+ stream->priv->sink) == FALSE) {
+ g_warning ("Error linking audioencode and sink elements");
}
g_object_set (G_OBJECT (stream->priv->src), "stream", src_stream,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]