melunko@917
|
1 |
|
melunko@917
|
2 |
#ifdef HAVE_CONFIG_H
|
melunko@917
|
3 |
#include "config.h"
|
melunko@917
|
4 |
#endif
|
melunko@917
|
5 |
|
melunko@917
|
6 |
#include <gst/gst.h>
|
melunko@917
|
7 |
#include <gst/base/gstcollectpads.h>
|
melunko@917
|
8 |
|
melunko@917
|
9 |
#include <stdlib.h>
|
melunko@917
|
10 |
#include <string.h>
|
melunko@917
|
11 |
|
melunko@917
|
12 |
/* gpac includes */
|
melunko@917
|
13 |
#include <gpac/isomedia.h>
|
melunko@917
|
14 |
|
melunko@917
|
15 |
#define GST_TYPE_GPAC_MUX (gst_gpac_mux_get_type())
|
melunko@917
|
16 |
#define GST_GPAC_MUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GPAC_MUX, GstGpacMux))
|
melunko@917
|
17 |
#define GST_GPAC_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GPAC_MUX, GstGpacMux))
|
melunko@917
|
18 |
#define GST_IS_GPAC_MUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GPAC_MUX))
|
melunko@917
|
19 |
#define GST_IS_GPAC_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GPAC_MUX))
|
melunko@917
|
20 |
|
melunko@917
|
21 |
typedef struct _GstGpacMux GstGpacMux;
|
melunko@917
|
22 |
typedef struct _GstGpacMuxClass GstGpacMuxClass;
|
melunko@917
|
23 |
|
melunko@917
|
24 |
typedef enum
|
melunko@917
|
25 |
{
|
melunko@917
|
26 |
GST_GPAC_PAD_STATE_CONTROL = 0,
|
melunko@917
|
27 |
GST_GPAC_PAD_STATE_DATA = 1
|
melunko@917
|
28 |
}
|
melunko@917
|
29 |
GstGpacPadState;
|
melunko@917
|
30 |
|
melunko@917
|
31 |
typedef struct
|
melunko@917
|
32 |
{
|
melunko@917
|
33 |
GstCollectData collect; /* we extend the CollectData */
|
melunko@917
|
34 |
|
melunko@917
|
35 |
gint track_number;
|
melunko@917
|
36 |
guint32 di; /* outDescriptionIndex */
|
melunko@917
|
37 |
|
melunko@917
|
38 |
guint32 frame_count;
|
melunko@917
|
39 |
gboolean is_video;
|
melunko@917
|
40 |
|
melunko@917
|
41 |
} GstGpacPad;
|
melunko@917
|
42 |
|
melunko@917
|
43 |
struct _GstGpacMux
|
melunko@917
|
44 |
{
|
melunko@917
|
45 |
GstElement element;
|
melunko@917
|
46 |
|
melunko@917
|
47 |
GstPad *srcpad;
|
melunko@917
|
48 |
GstCollectPads *collect;
|
melunko@917
|
49 |
|
melunko@917
|
50 |
GF_ISOFile *file;
|
melunko@917
|
51 |
|
melunko@917
|
52 |
};
|
melunko@917
|
53 |
|
melunko@917
|
54 |
struct _GstGpacMuxClass
|
melunko@917
|
55 |
{
|
melunko@917
|
56 |
GstElementClass parent_class;
|
melunko@917
|
57 |
};
|
melunko@917
|
58 |
|
melunko@917
|
59 |
/* elementfactory information */
|
melunko@917
|
60 |
static const GstElementDetails gst_gpac_mux_details =
|
melunko@917
|
61 |
GST_ELEMENT_DETAILS ("Gpac muxer",
|
melunko@917
|
62 |
"Codec/Muxer",
|
melunko@917
|
63 |
"mux mp4 streams",
|
melunko@917
|
64 |
"Hallyson Melo <hallyson.melo@indt.org.br");
|
melunko@917
|
65 |
|
melunko@917
|
66 |
/* GpacMux signals and args */
|
melunko@917
|
67 |
enum
|
melunko@917
|
68 |
{
|
melunko@917
|
69 |
/* FILL ME */
|
melunko@917
|
70 |
LAST_SIGNAL
|
melunko@917
|
71 |
};
|
melunko@917
|
72 |
|
melunko@917
|
73 |
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
|
melunko@917
|
74 |
GST_PAD_SRC,
|
melunko@917
|
75 |
GST_PAD_ALWAYS,
|
melunko@917
|
76 |
GST_STATIC_CAPS ("video/quicktime")
|
melunko@917
|
77 |
);
|
melunko@917
|
78 |
|
melunko@917
|
79 |
static GstStaticPadTemplate audio_sink_factory = GST_STATIC_PAD_TEMPLATE ("audio_%d",
|
melunko@917
|
80 |
GST_PAD_SINK,
|
melunko@917
|
81 |
GST_PAD_REQUEST,
|
melunko@917
|
82 |
GST_STATIC_CAPS (
|
melunko@917
|
83 |
"audio/mpeg, "
|
melunko@917
|
84 |
"mpegversion = (int) 4, "
|
melunko@917
|
85 |
"channels = (int) { 1, 2 }, "
|
melunko@917
|
86 |
"rate = (int) [ 8000, 96000 ]")
|
melunko@917
|
87 |
);
|
melunko@917
|
88 |
//GST_STATIC_CAPS ("audio/mpeg, mpegversion = 1, layer = 3")
|
melunko@917
|
89 |
|
melunko@917
|
90 |
static GstStaticPadTemplate video_sink_factory = GST_STATIC_PAD_TEMPLATE ("video_%d",
|
melunko@917
|
91 |
GST_PAD_SINK,
|
melunko@917
|
92 |
GST_PAD_REQUEST,
|
melunko@917
|
93 |
GST_STATIC_CAPS ("video/mpeg, mpegversion = 4")
|
melunko@917
|
94 |
);
|
melunko@917
|
95 |
|
melunko@917
|
96 |
static void gst_gpac_mux_base_init (gpointer g_class);
|
melunko@917
|
97 |
static void gst_gpac_mux_class_init (GstGpacMuxClass * klass);
|
melunko@917
|
98 |
static void gst_gpac_mux_init (GstGpacMux * gpac_mux);
|
melunko@917
|
99 |
static void gst_gpac_mux_finalize (GObject * object);
|
melunko@917
|
100 |
|
melunko@917
|
101 |
static GstFlowReturn
|
melunko@917
|
102 |
gst_gpac_mux_collected (GstCollectPads * pads, GstGpacMux * gpac_mux);
|
melunko@917
|
103 |
|
melunko@917
|
104 |
static gboolean gst_gpac_mux_handle_src_event (GstPad * pad, GstEvent * event);
|
melunko@917
|
105 |
static GstPad *gst_gpac_mux_request_new_pad (GstElement * element,
|
melunko@917
|
106 |
GstPadTemplate * templ, const gchar * name);
|
melunko@917
|
107 |
static void gst_gpac_mux_release_pad (GstElement * element, GstPad * pad);
|
melunko@917
|
108 |
|
melunko@917
|
109 |
static GstStateChangeReturn gst_gpac_mux_change_state (GstElement * element,
|
melunko@917
|
110 |
GstStateChange transition);
|
melunko@917
|
111 |
|
melunko@917
|
112 |
static GstElementClass *parent_class = NULL;
|
melunko@917
|
113 |
|
melunko@917
|
114 |
GType
|
melunko@917
|
115 |
gst_gpac_mux_get_type (void)
|
melunko@917
|
116 |
{
|
melunko@917
|
117 |
static GType gpac_mux_type = 0;
|
melunko@917
|
118 |
|
melunko@917
|
119 |
if (G_UNLIKELY (gpac_mux_type == 0)) {
|
melunko@917
|
120 |
static const GTypeInfo gpac_mux_info = {
|
melunko@917
|
121 |
sizeof (GstGpacMuxClass),
|
melunko@917
|
122 |
gst_gpac_mux_base_init,
|
melunko@917
|
123 |
NULL,
|
melunko@917
|
124 |
(GClassInitFunc) gst_gpac_mux_class_init,
|
melunko@917
|
125 |
NULL,
|
melunko@917
|
126 |
NULL,
|
melunko@917
|
127 |
sizeof (GstGpacMux),
|
melunko@917
|
128 |
0,
|
melunko@917
|
129 |
(GInstanceInitFunc) gst_gpac_mux_init,
|
melunko@917
|
130 |
};
|
melunko@917
|
131 |
|
melunko@917
|
132 |
gpac_mux_type =
|
melunko@917
|
133 |
g_type_register_static (GST_TYPE_ELEMENT, "GstGpacMux", &gpac_mux_info,
|
melunko@917
|
134 |
0);
|
melunko@917
|
135 |
}
|
melunko@917
|
136 |
return gpac_mux_type;
|
melunko@917
|
137 |
}
|
melunko@917
|
138 |
|
melunko@917
|
139 |
static void
|
melunko@917
|
140 |
gst_gpac_mux_base_init (gpointer g_class)
|
melunko@917
|
141 |
{
|
melunko@917
|
142 |
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
melunko@917
|
143 |
|
melunko@917
|
144 |
gst_element_class_add_pad_template (element_class,
|
melunko@917
|
145 |
gst_static_pad_template_get (&src_factory));
|
melunko@917
|
146 |
gst_element_class_add_pad_template (element_class,
|
melunko@917
|
147 |
gst_static_pad_template_get (&audio_sink_factory));
|
melunko@917
|
148 |
gst_element_class_add_pad_template (element_class,
|
melunko@917
|
149 |
gst_static_pad_template_get (&video_sink_factory));
|
melunko@917
|
150 |
|
melunko@917
|
151 |
gst_element_class_set_details (element_class, &gst_gpac_mux_details);
|
melunko@917
|
152 |
}
|
melunko@917
|
153 |
|
melunko@917
|
154 |
static void
|
melunko@917
|
155 |
gst_gpac_mux_class_init (GstGpacMuxClass * klass)
|
melunko@917
|
156 |
{
|
melunko@917
|
157 |
GObjectClass *gobject_class;
|
melunko@917
|
158 |
GstElementClass *gstelement_class;
|
melunko@917
|
159 |
|
melunko@917
|
160 |
gobject_class = (GObjectClass *) klass;
|
melunko@917
|
161 |
gstelement_class = (GstElementClass *) klass;
|
melunko@917
|
162 |
|
melunko@917
|
163 |
parent_class = g_type_class_peek_parent (klass);
|
melunko@917
|
164 |
|
melunko@917
|
165 |
gobject_class->finalize = gst_gpac_mux_finalize;
|
melunko@917
|
166 |
|
melunko@917
|
167 |
gstelement_class->request_new_pad = gst_gpac_mux_request_new_pad;
|
melunko@917
|
168 |
gstelement_class->release_pad = gst_gpac_mux_release_pad;
|
melunko@917
|
169 |
|
melunko@917
|
170 |
gstelement_class->change_state = gst_gpac_mux_change_state;
|
melunko@917
|
171 |
|
melunko@917
|
172 |
}
|
melunko@917
|
173 |
|
melunko@917
|
174 |
static void
|
melunko@917
|
175 |
gst_gpac_mux_init (GstGpacMux * gpac_mux)
|
melunko@917
|
176 |
{
|
melunko@917
|
177 |
GstElementClass *klass = GST_ELEMENT_GET_CLASS (gpac_mux);
|
melunko@917
|
178 |
|
melunko@917
|
179 |
gpac_mux->srcpad =
|
melunko@917
|
180 |
gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
|
melunko@917
|
181 |
"src"), "src");
|
melunko@917
|
182 |
gst_pad_set_event_function (gpac_mux->srcpad, gst_gpac_mux_handle_src_event);
|
melunko@917
|
183 |
gst_element_add_pad (GST_ELEMENT (gpac_mux), gpac_mux->srcpad);
|
melunko@917
|
184 |
|
melunko@917
|
185 |
gpac_mux->collect = gst_collect_pads_new ();
|
melunko@917
|
186 |
gst_collect_pads_set_function (gpac_mux->collect,
|
melunko@917
|
187 |
(GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_gpac_mux_collected),
|
melunko@917
|
188 |
gpac_mux);
|
melunko@917
|
189 |
|
melunko@917
|
190 |
/* Opens gpac library */
|
melunko@917
|
191 |
/* FIXME */
|
melunko@917
|
192 |
gpac_mux->file = gf_isom_open("/tmp/gpac.mp4", GF_ISOM_OPEN_WRITE, NULL);
|
melunko@917
|
193 |
gf_isom_set_storage_mode(gpac_mux->file, GF_ISOM_STORE_FLAT /*STREAMABLE*/);
|
melunko@917
|
194 |
|
melunko@917
|
195 |
//gst_gpac_mux_clear (gpac_mux);
|
melunko@917
|
196 |
}
|
melunko@917
|
197 |
|
melunko@917
|
198 |
static void
|
melunko@917
|
199 |
gst_gpac_mux_finalize (GObject * object)
|
melunko@917
|
200 |
{
|
melunko@917
|
201 |
GstGpacMux *gpac_mux;
|
melunko@917
|
202 |
|
melunko@917
|
203 |
gpac_mux = GST_GPAC_MUX (object);
|
melunko@917
|
204 |
|
melunko@917
|
205 |
if (gpac_mux->collect) {
|
melunko@917
|
206 |
gst_object_unref (gpac_mux->collect);
|
melunko@917
|
207 |
gpac_mux->collect = NULL;
|
melunko@917
|
208 |
}
|
melunko@917
|
209 |
|
melunko@917
|
210 |
G_OBJECT_CLASS (parent_class)->finalize (object);
|
melunko@917
|
211 |
}
|
melunko@917
|
212 |
|
melunko@917
|
213 |
static void
|
melunko@917
|
214 |
gst_gpac_mux_gpac_pad_destroy_notify (GstCollectData * data)
|
melunko@917
|
215 |
{
|
melunko@917
|
216 |
GstGpacPad *gpacpad = (GstGpacPad *) data;
|
melunko@917
|
217 |
GstBuffer *buf;
|
melunko@917
|
218 |
|
melunko@917
|
219 |
/* if (gpacpad->pagebuffers) {
|
melunko@917
|
220 |
while ((buf = g_queue_pop_head (gpacpad->pagebuffers)) != NULL) {
|
melunko@917
|
221 |
gst_buffer_unref (buf);
|
melunko@917
|
222 |
}
|
melunko@917
|
223 |
g_queue_free (gpacpad->pagebuffers);
|
melunko@917
|
224 |
gpacpad->pagebuffers = NULL;
|
melunko@917
|
225 |
}*/
|
melunko@917
|
226 |
}
|
melunko@917
|
227 |
|
melunko@917
|
228 |
static GstPadLinkReturn
|
melunko@917
|
229 |
gst_gpac_mux_sinkconnect (GstPad * pad, GstPad * peer)
|
melunko@917
|
230 |
{
|
melunko@917
|
231 |
GstGpacMux *gpac_mux;
|
melunko@917
|
232 |
|
melunko@917
|
233 |
gpac_mux = GST_GPAC_MUX (gst_pad_get_parent (pad));
|
melunko@917
|
234 |
|
melunko@917
|
235 |
GST_DEBUG_OBJECT (gpac_mux, "sinkconnect triggered on %s", GST_PAD_NAME (pad));
|
melunko@917
|
236 |
|
melunko@917
|
237 |
gst_object_unref (gpac_mux);
|
melunko@917
|
238 |
|
melunko@917
|
239 |
return GST_PAD_LINK_OK;
|
melunko@917
|
240 |
}
|
melunko@917
|
241 |
|
melunko@917
|
242 |
static GstPad *
|
melunko@917
|
243 |
gst_gpac_mux_request_new_pad (GstElement * element,
|
melunko@917
|
244 |
GstPadTemplate * templ, const gchar * req_name)
|
melunko@917
|
245 |
{
|
melunko@917
|
246 |
GstGpacMux *gpac_mux;
|
melunko@917
|
247 |
GstPad *newpad;
|
melunko@917
|
248 |
GstElementClass *klass;
|
melunko@917
|
249 |
gchar *padname = NULL;
|
melunko@917
|
250 |
gint serial;
|
melunko@917
|
251 |
gboolean is_video = FALSE;
|
melunko@917
|
252 |
|
melunko@917
|
253 |
g_return_val_if_fail (templ != NULL, NULL);
|
melunko@917
|
254 |
|
melunko@917
|
255 |
if (templ->direction != GST_PAD_SINK)
|
melunko@917
|
256 |
goto wrong_direction;
|
melunko@917
|
257 |
|
melunko@917
|
258 |
g_return_val_if_fail (GST_IS_GPAC_MUX (element), NULL);
|
melunko@917
|
259 |
gpac_mux = GST_GPAC_MUX (element);
|
melunko@917
|
260 |
|
melunko@917
|
261 |
klass = GST_ELEMENT_GET_CLASS (element);
|
melunko@917
|
262 |
|
melunko@917
|
263 |
if (req_name == NULL || strlen (req_name) < 6) {
|
melunko@917
|
264 |
/* no name given when requesting the pad, use random serial number */
|
melunko@917
|
265 |
serial = rand ();
|
melunko@917
|
266 |
} else {
|
melunko@917
|
267 |
/* parse serial number from requested padname */
|
melunko@917
|
268 |
serial = atoi (&req_name[5]);
|
melunko@917
|
269 |
}
|
melunko@917
|
270 |
|
melunko@917
|
271 |
if (templ == gst_element_class_get_pad_template (klass, "video_%d")) {
|
melunko@917
|
272 |
is_video = TRUE;
|
melunko@917
|
273 |
padname = g_strdup_printf ("video_%d", serial);
|
melunko@917
|
274 |
} else if (templ != gst_element_class_get_pad_template (klass, "audio_%d")) {
|
melunko@917
|
275 |
goto wrong_template;
|
melunko@917
|
276 |
} else {
|
melunko@917
|
277 |
padname = g_strdup_printf ("audio_%d", serial);
|
melunko@917
|
278 |
}
|
melunko@917
|
279 |
|
melunko@917
|
280 |
|
melunko@917
|
281 |
{
|
melunko@917
|
282 |
|
melunko@917
|
283 |
/* create new pad with the name */
|
melunko@917
|
284 |
GST_DEBUG_OBJECT (gpac_mux, "Creating new pad for serial %d", serial);
|
melunko@917
|
285 |
printf ("XXXX new pad from template\n");
|
melunko@917
|
286 |
newpad = gst_pad_new_from_template (templ, padname);
|
melunko@917
|
287 |
g_free (padname);
|
melunko@917
|
288 |
|
melunko@917
|
289 |
/* construct our own wrapper data structure for the pad to
|
melunko@917
|
290 |
* keep track of its status */
|
melunko@917
|
291 |
{
|
melunko@917
|
292 |
GstGpacPad *gpacpad;
|
melunko@917
|
293 |
|
melunko@917
|
294 |
gpacpad = (GstGpacPad *)
|
melunko@917
|
295 |
gst_collect_pads_add_pad_full (gpac_mux->collect, newpad,
|
melunko@917
|
296 |
sizeof (GstGpacPad), gst_gpac_mux_gpac_pad_destroy_notify);
|
melunko@917
|
297 |
|
melunko@917
|
298 |
/* gpac new track */
|
melunko@917
|
299 |
gpacpad->is_video = is_video;
|
melunko@917
|
300 |
if (gpacpad->is_video) {
|
melunko@917
|
301 |
gpacpad->track_number = gf_isom_new_track(gpac_mux->file, 0,
|
melunko@917
|
302 |
GF_ISOM_MEDIA_VISUAL, 10 * 1000 /* time scale */);
|
melunko@917
|
303 |
} else {
|
melunko@917
|
304 |
gpacpad->track_number = gf_isom_new_track(gpac_mux->file, 0,
|
melunko@917
|
305 |
GF_ISOM_MEDIA_AUDIO, 48000 /*time scale */);
|
melunko@917
|
306 |
|
melunko@917
|
307 |
}
|
melunko@917
|
308 |
if (gpacpad->track_number == 0) {
|
melunko@917
|
309 |
g_warning ("Error while adding the new gpac track");
|
melunko@917
|
310 |
} else {
|
melunko@917
|
311 |
gf_isom_set_track_enabled(gpac_mux->file, gpacpad->track_number, 1);
|
melunko@917
|
312 |
if (is_video) {
|
melunko@917
|
313 |
GF_ESD *esd = gf_odf_desc_esd_new (0);
|
melunko@917
|
314 |
esd->ESID = gf_isom_get_track_id(gpac_mux->file, gpacpad->track_number);
|
melunko@917
|
315 |
|
melunko@917
|
316 |
gf_isom_new_mpeg4_description( gpac_mux->file, gpacpad->track_number,
|
melunko@917
|
317 |
esd, NULL, NULL, &(gpacpad->di));
|
melunko@917
|
318 |
|
melunko@917
|
319 |
gf_isom_set_visual_info (gpac_mux->file, gpacpad->track_number, gpacpad->di, 320, 240);//fixme
|
melunko@917
|
320 |
//gf_isom_set_cts_packing (gpac_mux->file, gpacpad->track_number, 0);
|
melunko@917
|
321 |
} else {
|
melunko@917
|
322 |
GF_ESD *esd = gf_odf_desc_esd_new (2);
|
melunko@917
|
323 |
esd->ESID = gf_isom_get_track_id(gpac_mux->file, gpacpad->track_number);
|
melunko@917
|
324 |
|
melunko@917
|
325 |
gf_isom_new_mpeg4_description(gpac_mux->file, gpacpad->track_number,
|
melunko@917
|
326 |
esd, NULL, NULL, &(gpacpad->di));
|
melunko@917
|
327 |
|
melunko@917
|
328 |
gf_isom_set_audio_info(gpac_mux->file, gpacpad->track_number,
|
melunko@917
|
329 |
gpacpad->di, 48000, 2 /*num channels */, 16);
|
melunko@917
|
330 |
}
|
melunko@917
|
331 |
}
|
melunko@917
|
332 |
}
|
melunko@917
|
333 |
}
|
melunko@917
|
334 |
|
melunko@917
|
335 |
/* setup some pad functions */
|
melunko@917
|
336 |
gst_pad_set_link_function (newpad, gst_gpac_mux_sinkconnect);
|
melunko@917
|
337 |
/* dd the pad to the element */
|
melunko@917
|
338 |
gst_element_add_pad (element, newpad);
|
melunko@917
|
339 |
|
melunko@917
|
340 |
return newpad;
|
melunko@917
|
341 |
|
melunko@917
|
342 |
/* ERRORS */
|
melunko@917
|
343 |
wrong_direction:
|
melunko@917
|
344 |
{
|
melunko@917
|
345 |
g_warning ("gpac_mux: request pad that is not a SINK pad\n");
|
melunko@917
|
346 |
return NULL;
|
melunko@917
|
347 |
}
|
melunko@917
|
348 |
wrong_template:
|
melunko@917
|
349 |
{
|
melunko@917
|
350 |
g_warning ("gpac_mux: this is not our template!\n");
|
melunko@917
|
351 |
return NULL;
|
melunko@917
|
352 |
}
|
melunko@917
|
353 |
}
|
melunko@917
|
354 |
|
melunko@917
|
355 |
static void
|
melunko@917
|
356 |
gst_gpac_mux_release_pad (GstElement * element, GstPad * pad)
|
melunko@917
|
357 |
{
|
melunko@917
|
358 |
GstGpacMux *gpac_mux;
|
melunko@917
|
359 |
|
melunko@917
|
360 |
gpac_mux = GST_GPAC_MUX (gst_pad_get_parent (pad));
|
melunko@917
|
361 |
|
melunko@917
|
362 |
gst_collect_pads_remove_pad (gpac_mux->collect, pad);
|
melunko@917
|
363 |
gst_element_remove_pad (element, pad);
|
melunko@917
|
364 |
}
|
melunko@917
|
365 |
|
melunko@917
|
366 |
/* handle events */
|
melunko@917
|
367 |
static gboolean
|
melunko@917
|
368 |
gst_gpac_mux_handle_src_event (GstPad * pad, GstEvent * event)
|
melunko@917
|
369 |
{
|
melunko@917
|
370 |
GstEventType type;
|
melunko@917
|
371 |
|
melunko@917
|
372 |
type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
|
melunko@917
|
373 |
|
melunko@917
|
374 |
switch (type) {
|
melunko@917
|
375 |
case GST_EVENT_SEEK:
|
melunko@917
|
376 |
/* disable seeking for now */
|
melunko@917
|
377 |
return FALSE;
|
melunko@917
|
378 |
default:
|
melunko@917
|
379 |
break;
|
melunko@917
|
380 |
}
|
melunko@917
|
381 |
|
melunko@917
|
382 |
return gst_pad_event_default (pad, event);
|
melunko@917
|
383 |
}
|
melunko@917
|
384 |
|
melunko@917
|
385 |
static GstFlowReturn
|
melunko@917
|
386 |
gst_gpac_mux_push_buffer (GstGpacMux * mux, GstBuffer * buffer)
|
melunko@917
|
387 |
{
|
melunko@917
|
388 |
GstCaps *caps;
|
melunko@917
|
389 |
#if 0
|
melunko@917
|
390 |
/* fix up OFFSET and OFFSET_END again */
|
melunko@917
|
391 |
GST_BUFFER_OFFSET (buffer) = mux->offset;
|
melunko@917
|
392 |
mux->offset += GST_BUFFER_SIZE (buffer);
|
melunko@917
|
393 |
GST_BUFFER_OFFSET_END (buffer) = mux->offset;
|
melunko@917
|
394 |
|
melunko@917
|
395 |
/* Ensure we have monotonically increasing timestamps in the output. */
|
melunko@917
|
396 |
if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) {
|
melunko@917
|
397 |
if (mux->last_ts != GST_CLOCK_TIME_NONE &&
|
melunko@917
|
398 |
GST_BUFFER_TIMESTAMP (buffer) < mux->last_ts)
|
melunko@917
|
399 |
GST_BUFFER_TIMESTAMP (buffer) = mux->last_ts;
|
melunko@917
|
400 |
else
|
melunko@917
|
401 |
mux->last_ts = GST_BUFFER_TIMESTAMP (buffer);
|
melunko@917
|
402 |
}
|
melunko@917
|
403 |
#endif
|
melunko@917
|
404 |
|
melunko@917
|
405 |
caps = gst_pad_get_negotiated_caps (mux->srcpad);
|
melunko@917
|
406 |
gst_buffer_set_caps (buffer, caps);
|
melunko@917
|
407 |
if (caps != NULL) {
|
melunko@917
|
408 |
gst_caps_unref (caps);
|
melunko@917
|
409 |
}
|
melunko@917
|
410 |
|
melunko@917
|
411 |
return gst_pad_push (mux->srcpad, buffer);
|
melunko@917
|
412 |
}
|
melunko@917
|
413 |
|
melunko@917
|
414 |
static gboolean
|
melunko@917
|
415 |
all_pads_eos (GstCollectPads * pads)
|
melunko@917
|
416 |
{
|
melunko@917
|
417 |
GSList *iter;
|
melunko@917
|
418 |
gboolean alleos = TRUE;
|
melunko@917
|
419 |
|
melunko@917
|
420 |
iter = pads->data;
|
melunko@917
|
421 |
while (iter) {
|
melunko@917
|
422 |
GstBuffer *buf;
|
melunko@917
|
423 |
GstCollectData *data = (GstCollectData *) iter->data;
|
melunko@917
|
424 |
|
melunko@917
|
425 |
buf = gst_collect_pads_peek (pads, data);
|
melunko@917
|
426 |
if (buf) {
|
melunko@917
|
427 |
alleos = FALSE;
|
melunko@917
|
428 |
gst_buffer_unref (buf);
|
melunko@917
|
429 |
goto beach;
|
melunko@917
|
430 |
}
|
melunko@917
|
431 |
iter = iter->next;
|
melunko@917
|
432 |
}
|
melunko@917
|
433 |
beach:
|
melunko@917
|
434 |
return alleos;
|
melunko@917
|
435 |
}
|
melunko@917
|
436 |
|
melunko@917
|
437 |
static GstFlowReturn
|
melunko@917
|
438 |
gst_gpac_mux_collected (GstCollectPads * pads, GstGpacMux * gpac_mux)
|
melunko@917
|
439 |
{
|
melunko@917
|
440 |
GstFlowReturn ret = GST_FLOW_OK;
|
melunko@917
|
441 |
GSList *iter;
|
melunko@917
|
442 |
GstBuffer *buf;
|
melunko@917
|
443 |
gint i = 0;
|
melunko@917
|
444 |
|
melunko@917
|
445 |
GST_LOG_OBJECT (gpac_mux, "collected");
|
melunko@917
|
446 |
|
melunko@917
|
447 |
iter = gpac_mux->collect->data;
|
melunko@917
|
448 |
while (iter) {
|
melunko@917
|
449 |
GstCollectData *data = (GstCollectData *) iter->data;
|
melunko@917
|
450 |
GstGpacPad *pad = (GstGpacPad *) data;
|
melunko@917
|
451 |
|
melunko@917
|
452 |
buf = gst_collect_pads_pop (gpac_mux->collect, data);
|
melunko@917
|
453 |
if (buf == NULL) {
|
melunko@917
|
454 |
iter = g_slist_next (iter);
|
melunko@917
|
455 |
continue;
|
melunko@917
|
456 |
}
|
melunko@917
|
457 |
GST_LOG_OBJECT (data->pad, "popped buffer %" GST_PTR_FORMAT, buf);
|
melunko@917
|
458 |
|
melunko@917
|
459 |
/* gpac output */
|
melunko@917
|
460 |
printf ("xxxxxx buffer size: %d\n", GST_BUFFER_SIZE(buf)); fflush (stdout);
|
melunko@917
|
461 |
if (pad->frame_count < 300) {
|
melunko@917
|
462 |
GF_ISOSample *sample = gf_isom_sample_new();
|
melunko@917
|
463 |
|
melunko@917
|
464 |
sample->dataLength = GST_BUFFER_SIZE(buf);
|
melunko@917
|
465 |
sample->data = GST_BUFFER_DATA(buf);
|
melunko@917
|
466 |
sample->CTS_Offset = 0;
|
melunko@917
|
467 |
|
melunko@917
|
468 |
if (pad->is_video) {
|
melunko@917
|
469 |
sample->IsRAP = 0;
|
melunko@917
|
470 |
sample->DTS += 1000*pad->frame_count;
|
melunko@917
|
471 |
} else {
|
melunko@917
|
472 |
sample->IsRAP = 0;
|
melunko@917
|
473 |
sample->DTS = 2048*pad->frame_count;
|
melunko@917
|
474 |
}
|
melunko@917
|
475 |
|
melunko@917
|
476 |
gf_isom_add_sample(gpac_mux->file, pad->track_number,
|
melunko@917
|
477 |
pad->di, sample);
|
melunko@917
|
478 |
sample->data = NULL;
|
melunko@917
|
479 |
|
melunko@917
|
480 |
gf_isom_sample_del(&sample);
|
melunko@917
|
481 |
|
melunko@917
|
482 |
printf ("xxxx frames %d\n", pad->frame_count);
|
melunko@917
|
483 |
|
melunko@917
|
484 |
} else if (pad->frame_count == 300) {
|
melunko@917
|
485 |
printf ("XXX closing gpac output file\n"); fflush (stdout);
|
melunko@917
|
486 |
gf_isom_close (gpac_mux->file);
|
melunko@917
|
487 |
}
|
melunko@917
|
488 |
|
melunko@917
|
489 |
/* gstreamer output (push) */
|
melunko@917
|
490 |
if (gst_gpac_mux_push_buffer (gpac_mux, buf) != GST_FLOW_OK) {
|
melunko@917
|
491 |
printf ("EEEEEEEE push failed\n");
|
melunko@917
|
492 |
}
|
melunko@917
|
493 |
|
melunko@917
|
494 |
iter = g_slist_next (iter);
|
melunko@917
|
495 |
pad->frame_count++;
|
melunko@917
|
496 |
i++;
|
melunko@917
|
497 |
}
|
melunko@917
|
498 |
|
melunko@917
|
499 |
/* fixme */
|
melunko@917
|
500 |
return ret;
|
melunko@917
|
501 |
}
|
melunko@917
|
502 |
|
melunko@917
|
503 |
/* reset all variables in the gpac pads. */
|
melunko@917
|
504 |
static void
|
melunko@917
|
505 |
gst_gpac_mux_init_collectpads (GstCollectPads * collect)
|
melunko@917
|
506 |
{
|
melunko@917
|
507 |
GSList *walk;
|
melunko@917
|
508 |
|
melunko@917
|
509 |
walk = collect->data;
|
melunko@917
|
510 |
while (walk) {
|
melunko@917
|
511 |
GstGpacPad *gpacpad = (GstGpacPad *) walk->data;
|
melunko@917
|
512 |
|
melunko@917
|
513 |
//ogg_stream_init (&gpacpad->stream, gpacpad->serial);
|
melunko@917
|
514 |
//gpacpad->packetno = 0;
|
melunko@917
|
515 |
//gpacpad->pageno = 0;
|
melunko@917
|
516 |
//gpacpad->eos = FALSE;
|
melunko@917
|
517 |
/* we assume there will be some control data first for this pad */
|
melunko@917
|
518 |
//gpacpad->state = GST_GPAC_PAD_STATE_CONTROL;
|
melunko@917
|
519 |
//gpacpad->new_page = TRUE;
|
melunko@917
|
520 |
//gpacpad->first_delta = FALSE;
|
melunko@917
|
521 |
//gpacpad->prev_delta = FALSE;
|
melunko@917
|
522 |
//gpacpad->pagebuffers = g_queue_new ();
|
melunko@917
|
523 |
|
melunko@917
|
524 |
walk = g_slist_next (walk);
|
melunko@917
|
525 |
}
|
melunko@917
|
526 |
}
|
melunko@917
|
527 |
|
melunko@917
|
528 |
/* Clear all buffers from the collectpads object */
|
melunko@917
|
529 |
static void
|
melunko@917
|
530 |
gst_gpac_mux_clear_collectpads (GstCollectPads * collect)
|
melunko@917
|
531 |
{
|
melunko@917
|
532 |
GSList *walk;
|
melunko@917
|
533 |
|
melunko@917
|
534 |
for (walk = collect->data; walk; walk = g_slist_next (walk)) {
|
melunko@917
|
535 |
GstGpacPad *gpacpad = (GstGpacPad *) walk->data;
|
melunko@917
|
536 |
GstBuffer *buf;
|
melunko@917
|
537 |
|
melunko@917
|
538 |
//gpac_stream_clear (&gpacpad->stream);
|
melunko@917
|
539 |
/*
|
melunko@917
|
540 |
while ((buf = g_queue_pop_head (gpacpad->pagebuffers)) != NULL) {
|
melunko@917
|
541 |
gst_buffer_unref (buf);
|
melunko@917
|
542 |
}
|
melunko@917
|
543 |
g_queue_free (gpacpad->pagebuffers);
|
melunko@917
|
544 |
gpacpad->pagebuffers = NULL;*/
|
melunko@917
|
545 |
}
|
melunko@917
|
546 |
}
|
melunko@917
|
547 |
|
melunko@917
|
548 |
static GstStateChangeReturn
|
melunko@917
|
549 |
gst_gpac_mux_change_state (GstElement * element, GstStateChange transition)
|
melunko@917
|
550 |
{
|
melunko@917
|
551 |
GstGpacMux *gpac_mux;
|
melunko@917
|
552 |
GstStateChangeReturn ret;
|
melunko@917
|
553 |
|
melunko@917
|
554 |
gpac_mux = GST_GPAC_MUX (element);
|
melunko@917
|
555 |
|
melunko@917
|
556 |
switch (transition) {
|
melunko@917
|
557 |
case GST_STATE_CHANGE_NULL_TO_READY:
|
melunko@917
|
558 |
break;
|
melunko@917
|
559 |
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
melunko@917
|
560 |
//gst_gpac_mux_clear (gpac_mux);
|
melunko@917
|
561 |
//gst_gpac_mux_init_collectpads (gpac_mux->collect);
|
melunko@917
|
562 |
gst_collect_pads_start (gpac_mux->collect);
|
melunko@917
|
563 |
break;
|
melunko@917
|
564 |
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
melunko@917
|
565 |
break;
|
melunko@917
|
566 |
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
melunko@917
|
567 |
gst_collect_pads_stop (gpac_mux->collect);
|
melunko@917
|
568 |
break;
|
melunko@917
|
569 |
default:
|
melunko@917
|
570 |
break;
|
melunko@917
|
571 |
}
|
melunko@917
|
572 |
|
melunko@917
|
573 |
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
melunko@917
|
574 |
|
melunko@917
|
575 |
switch (transition) {
|
melunko@917
|
576 |
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
melunko@917
|
577 |
break;
|
melunko@917
|
578 |
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
melunko@917
|
579 |
gst_gpac_mux_clear_collectpads (gpac_mux->collect);
|
melunko@917
|
580 |
break;
|
melunko@917
|
581 |
case GST_STATE_CHANGE_READY_TO_NULL:
|
melunko@917
|
582 |
break;
|
melunko@917
|
583 |
default:
|
melunko@917
|
584 |
break;
|
melunko@917
|
585 |
}
|
melunko@917
|
586 |
|
melunko@917
|
587 |
return ret;
|
melunko@917
|
588 |
|
melunko@917
|
589 |
}
|
melunko@917
|
590 |
|
melunko@917
|
591 |
static gboolean
|
melunko@917
|
592 |
gst_gpac_mux_plugin_init (GstPlugin * plugin)
|
melunko@917
|
593 |
{
|
melunko@917
|
594 |
return gst_element_register (plugin, "gpacmux", GST_RANK_NONE,
|
melunko@917
|
595 |
GST_TYPE_GPAC_MUX);
|
melunko@917
|
596 |
}
|
melunko@917
|
597 |
|
melunko@917
|
598 |
GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
|
melunko@917
|
599 |
GST_VERSION_MINOR,
|
melunko@917
|
600 |
"gpacmux",
|
melunko@917
|
601 |
"Muxes audio and video",
|
melunko@917
|
602 |
gst_gpac_mux_plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME,
|
melunko@917
|
603 |
GST_PACKAGE_ORIGIN)
|
melunko@917
|
604 |
|