c7e181dc77cb8d2e38ca5e9df68f992c4ea7bf19
[platform/upstream/gstreamer.git] / src / rtsp-media.c
1 /* GStreamer
2  * Copyright (C) 2008 Wim Taymans <wim.taymans at gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "rtsp-media.h"
21
22 G_DEFINE_TYPE (GstRTSPMedia, gst_rtsp_media, G_TYPE_OBJECT);
23
24 static void gst_rtsp_media_finalize (GObject * obj);
25
26 static void
27 gst_rtsp_media_class_init (GstRTSPMediaClass * klass)
28 {
29   GObjectClass *gobject_class;
30
31   gobject_class = G_OBJECT_CLASS (klass);
32
33   gobject_class->finalize = gst_rtsp_media_finalize;
34 }
35
36 static void
37 gst_rtsp_media_init (GstRTSPMedia * media)
38 {
39   media->streams = g_array_new (FALSE, TRUE, sizeof (GstRTSPMediaStream *));
40 }
41
42 static void
43 gst_rtsp_media_stream_free (GstRTSPMediaStream *stream)
44 {
45 }
46
47 static void
48 gst_rtsp_media_finalize (GObject * obj)
49 {
50   GstRTSPMedia *media;
51   guint i;
52
53   media = GST_RTSP_MEDIA (obj);
54
55   g_free (media->location);
56   gst_rtsp_url_free (media->url);
57
58   for (i = 0; i < media->streams->len; i++) {
59     GstRTSPMediaStream *stream;
60
61     stream = g_array_index (media->streams, GstRTSPMediaStream *, i);
62
63     gst_rtsp_media_stream_free (stream);
64   }
65   g_array_free (media->streams, TRUE);
66
67   G_OBJECT_CLASS (gst_rtsp_media_parent_class)->finalize (obj);
68 }
69
70 /**
71  * gst_rtsp_media_new:
72  * @location: the URL of the media
73  *
74  * Create a new #GstRTSPMedia instance.
75  *
76  * Returns: a new #GstRTSPMedia object or %NULL when location did not contain a
77  * valid or understood URL.
78  */
79 GstRTSPMedia *
80 gst_rtsp_media_new (const gchar *location)
81 {
82   GstRTSPMedia *result;
83   GstRTSPUrl *url;
84
85   url = NULL;
86
87   if (gst_rtsp_url_parse (location, &url) != GST_RTSP_OK)
88     goto invalid_url;
89
90   result = g_object_new (GST_TYPE_RTSP_MEDIA, NULL);
91   result->location = g_strdup (location);
92   result->url = url;
93
94   return result;
95
96   /* ERRORS */
97 invalid_url:
98   {
99     return NULL;
100   }
101 }
102
103 static void
104 caps_notify (GstPad * pad, GParamSpec * unused, GstRTSPMediaStream * stream)
105 {
106   if (stream->caps)
107     gst_caps_unref (stream->caps);
108   if ((stream->caps = GST_PAD_CAPS (pad)))
109     gst_caps_ref (stream->caps);
110 }
111
112 /**
113  *
114  * STREAMING CONFIGURATION
115  *
116  * gst_rtsp_media_prepare:
117  * @media: a #GstRTSPMedia
118  * @bin: the parent bin to create the elements in.
119  *
120  * Prepare the media object so that it creates its streams. Implementations
121  * should crate the needed gstreamer elements and add them to @bin. No state
122  * changes should be performed on them yet.
123  *
124  * One or more GstRTSPMediaStream objects should be added to @media with the
125  * srcpad member set to a source pad that produces buffer of type 
126  * application/x-rtp.
127  *
128  * Returns: %TRUE if the media could be prepared.
129  */
130 gboolean
131 gst_rtsp_media_prepare (GstRTSPMedia *media, GstBin *bin)
132 {
133   GstRTSPMediaStream *stream;
134   GstElement *pay, *element;
135   GstPad * pad;
136   gint i;
137
138   /* if we're already prepared we must exit */
139   g_return_val_if_fail (media->prepared == FALSE, FALSE);
140
141   g_print ("%s\n", media->url->abspath);
142
143   if (g_str_has_prefix (media->url->abspath, "/camera")) {
144     /* live */
145     element = gst_parse_launch ("( "
146         "v4l2src ! video/x-raw-yuv,width=352,height=288,framerate=15/1 ! "
147         "queue ! videorate ! ffmpegcolorspace ! "
148         "x264enc bitrate=300 ! rtph264pay name=pay0 "
149         "alsasrc ! audio/x-raw-int,rate=8000 ! queue ! "
150         "amrnbenc ! rtpamrpay name=pay1 "
151         ")", NULL);
152   }
153   else if (g_str_has_prefix (media->url->abspath, "/h264")) {
154     /* transcode h264 */
155     element = gst_parse_launch ("( uridecodebin "
156         "uri=file:///home/cschalle/Videos/mi2.avi ! "
157         "x264enc bitrate=300 ! rtph264pay name=pay0 )", NULL);
158   }
159   else if (g_str_has_prefix (media->url->abspath, "/theora")) {
160     /* transcode theora */
161     element = gst_parse_launch ("( uridecodebin "
162         "uri=file:///home/wim/data/mi2.avi ! "
163         "theoraenc ! rtptheorapay name=pay0 )", NULL);
164   }
165   else if (g_str_has_prefix (media->url->abspath, "/macpclinux")) {
166     /* theora/vorbis */
167     element = gst_parse_launch ("( filesrc "
168         "location=/home/cschalle/Videos/mac_pc_linux_2.ogg ! oggdemux name=d ! "
169         "queue ! theoraparse ! rtptheorapay name=pay0 "
170         "d. ! queue ! vorbisparse ! rtpvorbispay name=pay1 )", NULL);
171   }
172   else if (g_str_has_prefix (media->url->abspath, "/rtspproxy")) {
173     /* proxy RTSP transcode */
174     element = gst_parse_launch ("( uridecodebin "
175         "uri=rtsp://ia300135.us.archive.org:554/0/items/uncovered_interviews/uncovered_interviews_3_256kb.mp4 ! "
176         "x264enc bitrate=1800 ! rtph264pay name=pay0 )", NULL);
177   }
178   else if (g_str_has_prefix (media->url->abspath, "/httpproxy")) {
179     /* proxy HTTP transcode */
180     element = gst_parse_launch ("( uridecodebin "
181         "uri=http://movies.apple.com/movies/fox/maxpayne/maxpayne-tlre_h480.mov name=d "
182         "d. ! queue ! x264enc bitrate=1800 ! rtph264pay name=pay0 "
183         "d. ! queue ! faac ! rtpmp4gpay name=pay1 )", NULL);
184   }
185   else
186     return FALSE;
187
188   gst_bin_add (bin, element);
189
190   for (i = 0; ; i++) {
191     gchar *name;
192
193     name = g_strdup_printf ("pay%d", i);
194
195     if (!(pay = gst_bin_get_by_name (GST_BIN (element), name))) {
196       g_free (name);
197       break;
198     }
199     
200     /* create the stream */
201     stream = g_new0 (GstRTSPMediaStream, 1);
202     stream->media = media;
203     stream->element = element;
204     stream->payloader = pay;
205     stream->idx = media->streams->len;
206
207     pad = gst_element_get_static_pad (pay, "src");
208
209     stream->srcpad = gst_ghost_pad_new (name, pad);
210     gst_element_add_pad (stream->element, stream->srcpad);
211
212     stream->caps_sig = g_signal_connect (pad, "notify::caps", (GCallback) caps_notify, stream);
213     gst_object_unref (pad);
214
215     /* add stream now */
216     g_array_append_val (media->streams, stream);
217     gst_object_unref (pay);
218
219     g_free (name);
220   }
221
222   media->prepared = TRUE;
223
224   return TRUE;
225 }
226
227 /**
228  * gst_rtsp_media_n_streams:
229  * @media: a #GstRTSPMedia
230  *
231  * Get the number of streams in this media.
232  *
233  * Returns: The number of streams.
234  */
235 guint
236 gst_rtsp_media_n_streams (GstRTSPMedia *media)
237 {
238   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), 0);
239   g_return_val_if_fail (media->prepared, 0);
240
241   return media->streams->len;
242 }
243
244 /**
245  * gst_rtsp_media_get_stream:
246  * @media: a #GstRTSPMedia
247  * @idx: the stream index
248  *
249  * Retrieve the stream with index @idx from @media.
250  *
251  * Returns: the #GstRTSPMediaStream at index @idx.
252  */
253 GstRTSPMediaStream *
254 gst_rtsp_media_get_stream (GstRTSPMedia *media, guint idx)
255 {
256   GstRTSPMediaStream *res;
257   
258   g_return_val_if_fail (GST_IS_RTSP_MEDIA (media), NULL);
259   g_return_val_if_fail (media->prepared, 0);
260   g_return_val_if_fail (idx < media->streams->len, NULL);
261
262   res = g_array_index (media->streams, GstRTSPMediaStream *, idx);
263
264   return res;
265 }
266