00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "gst-decode.h"
00026
00027 #ifdef MARSYAS_GSTREAMER
00028
00029 #include "gst-decode.h"
00030 #include <gst/gst.h>
00031 #include <glib.h>
00032 #include <string.h>
00033
00034 static void cb_newpad (GstElement *decodebin, GstPad *pad, gboolean last, GstElement *audio) {
00035 GstCaps *caps;
00036 GstStructure *str;
00037 GstPad *audiopad;
00038
00039
00040 audiopad = gst_element_get_pad (audio, "sink");
00041 if (GST_PAD_IS_LINKED (audiopad)) {
00042 g_object_unref (audiopad);
00043 return;
00044 }
00045
00046
00047 caps = gst_pad_get_caps (pad);
00048 str = gst_caps_get_structure (caps, 0);
00049 if (!g_strrstr (gst_structure_get_name (str), "audio")) {
00050 gst_caps_unref (caps);
00051 gst_object_unref (audiopad);
00052 return;
00053 }
00054 gst_caps_unref (caps);
00055
00056
00057 gst_pad_link (pad, audiopad);
00058 }
00059
00060 void handoff (GstElement* identity, GstBuffer* frame, gstreamerFrames* frameData) {
00061 if (GST_BUFFER_SIZE(frame) == 0) {
00062 return;
00063 }
00064
00065 frameData->frameCount += 1;
00066 frameData->totalSize += GST_BUFFER_SIZE(frame);
00067
00068 mrs_real* values = g_new(mrs_real,GST_BUFFER_SIZE(frame)/sizeof(mrs_real));
00069 memcpy((void*)values, (void*)GST_BUFFER_DATA(frame), GST_BUFFER_SIZE(frame));
00070 frameData->frameList = g_list_append(frameData->frameList, (gpointer)values);
00071
00072 int* fc = g_new(int,1);
00073 *fc = GST_BUFFER_SIZE(frame);
00074 frameData->frameSize = g_list_append(frameData->frameSize, (gpointer)fc);
00075 }
00076
00077 GstElement* gstreamer_init(const gchar *filename, gstreamerFrames* data) {
00078
00079 gst_init (NULL, NULL);
00080
00081
00082 GstElement *audio = gst_bin_new ("audiobin");
00083 GstElement *pipeline = gst_pipeline_new ("pipeline");
00084 GstElement *src = gst_element_factory_make ("filesrc", "source");
00085 GstElement *dec = gst_element_factory_make ("decodebin", "decoder");
00086 GstElement *conv = gst_element_factory_make ("audioconvert", "aconv");
00087 GstPad *audiopad = gst_element_get_pad(conv, "sink");
00088
00089 GstCaps *filter_float_caps = gst_caps_new_simple("audio/x-raw-float",
00090 "width", G_TYPE_INT, sizeof(mrs_real)*8,
00091 "rate", G_TYPE_INT, 44100,
00092 "channels", G_TYPE_INT, 2,
00093 NULL);
00094 GstElement *filt_float = gst_element_factory_make("capsfilter", "filt_float");
00095 GstElement *monitor = gst_element_factory_make ("identity", "idmonitor");
00096 GstElement *sink = gst_element_factory_make ("fakesink", "sink");
00097
00098
00099 g_object_set(G_OBJECT(src), "location", filename, NULL);
00100 g_object_set(G_OBJECT(filt_float), "caps", filter_float_caps, NULL);
00101 g_signal_connect(dec, "new-decoded-pad", G_CALLBACK(cb_newpad), audio);
00102 g_signal_connect(monitor, "handoff", G_CALLBACK(handoff), data);
00103
00104
00105 gst_bin_add_many (GST_BIN (pipeline), src, dec, NULL);
00106 gst_element_link (src, dec);
00107
00108
00109 gst_bin_add_many (GST_BIN (audio), conv, filt_float, monitor, sink, NULL);
00110 gst_element_link_many (conv, filt_float, monitor, sink, NULL);
00111 gst_element_add_pad (audio, gst_ghost_pad_new("sink", audiopad));
00112 gst_object_unref (audiopad);
00113 gst_bin_add (GST_BIN (pipeline), audio);
00114
00115 return pipeline;
00116 }
00117
00118 void gstreamer_cleanup(GstElement* pipeline) {
00119 gst_element_set_state (pipeline, GST_STATE_NULL);
00120 gst_object_unref (GST_OBJECT (pipeline));
00121 }
00122
00123 audioVector gst_decode_file(const gchar *filename) {
00124 gstreamerFrames* data = g_new0(gstreamerFrames,1);
00125 GstElement* pipeline = gstreamer_init(filename, data);
00126 gchar msg[100];
00127
00128
00129 gst_element_set_state(pipeline, GST_STATE_PLAYING);
00130 g_snprintf(msg, 100, "decoding %s\n", filename);
00131 MRSDEBUG(msg);
00132
00133 GstBus* bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
00134 GstMessage* message = 0;
00135 gboolean decoding = TRUE;
00136 while (decoding) {
00137 message = gst_bus_poll(bus, GST_MESSAGE_ANY, -1);
00138 if (message == 0)
00139 continue;
00140
00141 switch (GST_MESSAGE_TYPE(message)) {
00142 case GST_MESSAGE_ERROR: {
00143 GError *err;
00144 gchar *debug;
00145
00146 gst_message_parse_error(message, &err, &debug);
00147 g_snprintf(msg, 100, "GStreamer decode error: %s\n", err->message);
00148 MRSWARN(msg);
00149 g_error_free(err);
00150 g_free(debug);
00151 g_free(msg);
00152 decoding = FALSE;
00153
00154 break;
00155 }
00156 case GST_MESSAGE_EOS: {
00157 g_snprintf(msg, 100, "End of stream\n");
00158 MRSDEBUG(msg);
00159 decoding = FALSE;
00160 break;
00161 }
00162 default:
00163 break;
00164 }
00165 }
00166 g_snprintf(msg, 100, "got %d frames of audio\n", data->frameCount);
00167 MRSDEBUG(msg);
00168 g_snprintf(msg, 100, "%d bytes of audio data\n", data->totalSize);
00169 MRSDEBUG(msg);
00170
00171 gst_object_unref(bus);
00172 gstreamer_cleanup(pipeline);
00173
00174
00175 mrs_real* alldata = g_new0(mrs_real, data->totalSize/sizeof(mrs_real));
00176 mrs_real* copyLoc = alldata;
00177
00178 GList *dl, *sl;
00179 int fsize = 0;
00180 int frameN = 0;
00181 for (dl = data->frameList, sl = data->frameSize; (dl != 0) && (sl != 0); dl = g_list_next(dl), sl = g_list_next(sl)) {
00182 fsize = *((int*)sl->data);
00183 memcpy((void*)copyLoc, (void*)dl->data, fsize);
00184 copyLoc += fsize/sizeof(mrs_real);
00185 g_free(dl->data);
00186 g_free(sl->data);
00187 }
00188 g_snprintf(msg, 100, "finished condensing data\n");
00189 MRSDEBUG(msg);
00190 g_list_free(data->frameList);
00191 g_list_free(data->frameSize);
00192
00193 audioVector r = {alldata, data->totalSize/sizeof(mrs_real)};
00194 return r;
00195 }
00196
00197 #endif //MARSYAS_GSTREAMER