1.1 --- a/gst-gpac/src/gpacmux.c Thu Feb 21 17:54:48 2008 +0000
1.2 +++ b/gst-gpac/src/gpacmux.c Thu Feb 21 22:49:45 2008 +0000
1.3 @@ -35,9 +35,14 @@
1.4 gint track_number;
1.5 guint32 di; /* outDescriptionIndex */
1.6
1.7 + GstBuffer *buffer;
1.8 + GstBuffer *next_buffer;
1.9 +
1.10 guint32 frame_count;
1.11 gboolean is_video;
1.12
1.13 + gboolean eos;
1.14 +
1.15 } GstGpacPad;
1.16
1.17 struct _GstGpacMux
1.18 @@ -46,6 +51,7 @@
1.19
1.20 GstPad *srcpad;
1.21 GstCollectPads *collect;
1.22 + gint active_pads;
1.23
1.24 GF_ISOFile *file;
1.25
1.26 @@ -109,6 +115,13 @@
1.27 static GstStateChangeReturn gst_gpac_mux_change_state (GstElement * element,
1.28 GstStateChange transition);
1.29
1.30 +static GstGpacPad* gst_gpac_mux_queue_pads (GstGpacMux * gpac_mux);
1.31 +static GstFlowReturn gst_gpac_mux_process_pad (GstGpacMux * gpac_mux, GstGpacPad *pad);
1.32 +static gboolean gst_gpac_mux_all_pads_eos (GstCollectPads * pads);
1.33 +static gint gst_gpac_mux_compare_pads (GstGpacMux * ogg_mux, GstGpacPad *first,
1.34 + GstGpacPad *second);
1.35 +
1.36 +
1.37 static GstElementClass *parent_class = NULL;
1.38
1.39 GType
1.40 @@ -216,13 +229,6 @@
1.41 GstGpacPad *gpacpad = (GstGpacPad *) data;
1.42 GstBuffer *buf;
1.43
1.44 -/* if (gpacpad->pagebuffers) {
1.45 - while ((buf = g_queue_pop_head (gpacpad->pagebuffers)) != NULL) {
1.46 - gst_buffer_unref (buf);
1.47 - }
1.48 - g_queue_free (gpacpad->pagebuffers);
1.49 - gpacpad->pagebuffers = NULL;
1.50 - }*/
1.51 }
1.52
1.53 static GstPadLinkReturn
1.54 @@ -282,7 +288,7 @@
1.55
1.56 /* create new pad with the name */
1.57 GST_DEBUG_OBJECT (gpac_mux, "Creating new pad for serial %d", serial);
1.58 - printf ("XXXX new pad from template\n");
1.59 +
1.60 newpad = gst_pad_new_from_template (templ, padname);
1.61 g_free (padname);
1.62
1.63 @@ -294,6 +300,7 @@
1.64 gpacpad = (GstGpacPad *)
1.65 gst_collect_pads_add_pad_full (gpac_mux->collect, newpad,
1.66 sizeof (GstGpacPad), gst_gpac_mux_gpac_pad_destroy_notify);
1.67 + gpac_mux->active_pads++;
1.68
1.69 /* gpac new track */
1.70 gpacpad->is_video = is_video;
1.71 @@ -411,92 +418,128 @@
1.72 return gst_pad_push (mux->srcpad, buffer);
1.73 }
1.74
1.75 +static GstFlowReturn
1.76 +gst_gpac_mux_collected (GstCollectPads * pads, GstGpacMux * gpac_mux)
1.77 +{
1.78 + GstFlowReturn ret = GST_FLOW_OK;
1.79 + GstGpacPad *pad;
1.80 + gint active_before;
1.81 +
1.82 + GST_LOG_OBJECT (gpac_mux, "collected");
1.83 +
1.84 + active_before = gpac_mux->active_pads;
1.85 +
1.86 + pad = gst_gpac_mux_queue_pads (gpac_mux);
1.87 + if (!pad) {
1.88 + return GST_FLOW_WRONG_STATE;
1.89 + }
1.90 +
1.91 + if (pad->buffer) {
1.92 + ret = gst_gpac_mux_process_pad (gpac_mux, pad);
1.93 + }
1.94 +
1.95 + if (gpac_mux->active_pads < active_before) {
1.96 + /* If the active pad count went down, this mean at least one pad has gone
1.97 + * EOS. Since CollectPads only calls _collected() once when all pads are
1.98 + * EOS, and our code doesn't _pop() from all pads we need to check that by
1.99 + * peeking on all pads, else we won't be called again and the muxing will
1.100 + * not terminate (push out EOS). */
1.101 + printf ("XXXX um pad foi desativado %" GST_PTR_FORMAT "\n", pad);
1.102 +
1.103 + /* if all the pads have been removed, flush all pending data */
1.104 + if ((ret == GST_FLOW_OK) && gst_gpac_mux_all_pads_eos (pads)) {
1.105 + GST_LOG_OBJECT (gpac_mux, "no pads remaining, flushing data");
1.106 +
1.107 + do {
1.108 + pad = gst_gpac_mux_queue_pads (gpac_mux);
1.109 + if (pad)
1.110 + ret = gst_gpac_mux_process_pad (gpac_mux, pad);
1.111 + } while ((ret == GST_FLOW_OK) && (pad != NULL));
1.112 +
1.113 + /* gpac file close (eos) */
1.114 + // Fixme: this should flush all data to src pad
1.115 + // Fixme: where to release gpac_mux->file?
1.116 + printf ("CCCCCCCCCCCCCCCCcclosing the file\n");
1.117 + gf_isom_close (gpac_mux->file);
1.118 +
1.119 +
1.120 + GST_DEBUG_OBJECT (gpac_mux, "Pushing EOS");
1.121 + gst_pad_push_event (gpac_mux->srcpad, gst_event_new_eos ());
1.122 + }
1.123 + }
1.124 +
1.125 + return ret;
1.126 +
1.127 +}
1.128 +
1.129 static gboolean
1.130 -all_pads_eos (GstCollectPads * pads)
1.131 +gst_gpac_mux_all_pads_eos (GstCollectPads * pads)
1.132 {
1.133 - GSList *iter;
1.134 + GSList *walk;
1.135 gboolean alleos = TRUE;
1.136
1.137 - iter = pads->data;
1.138 - while (iter) {
1.139 + walk = pads->data;
1.140 + while (walk) {
1.141 GstBuffer *buf;
1.142 - GstCollectData *data = (GstCollectData *) iter->data;
1.143 + GstCollectData *data = (GstCollectData *) walk->data;
1.144
1.145 buf = gst_collect_pads_peek (pads, data);
1.146 if (buf) {
1.147 alleos = FALSE;
1.148 gst_buffer_unref (buf);
1.149 - goto beach;
1.150 + break;
1.151 }
1.152 - iter = iter->next;
1.153 + walk = walk->next;
1.154 }
1.155 -beach:
1.156 +
1.157 return alleos;
1.158 }
1.159 -
1.160 +
1.161 +
1.162 static GstFlowReturn
1.163 -gst_gpac_mux_collected (GstCollectPads * pads, GstGpacMux * gpac_mux)
1.164 +gst_gpac_mux_process_pad (GstGpacMux *gpac_mux, GstGpacPad *pad)
1.165 {
1.166 GstFlowReturn ret = GST_FLOW_OK;
1.167 - GSList *iter;
1.168 - GstBuffer *buf;
1.169 - gint i = 0;
1.170 + GF_ISOSample *sample;
1.171
1.172 - GST_LOG_OBJECT (gpac_mux, "collected");
1.173 -
1.174 - iter = gpac_mux->collect->data;
1.175 - while (iter) {
1.176 - GstCollectData *data = (GstCollectData *) iter->data;
1.177 - GstGpacPad *pad = (GstGpacPad *) data;
1.178 -
1.179 - buf = gst_collect_pads_pop (gpac_mux->collect, data);
1.180 - if (buf == NULL) {
1.181 - iter = g_slist_next (iter);
1.182 - continue;
1.183 - }
1.184 - GST_LOG_OBJECT (data->pad, "popped buffer %" GST_PTR_FORMAT, buf);
1.185 -
1.186 - /* gpac output */
1.187 - printf ("xxxxxx buffer size: %d\n", GST_BUFFER_SIZE(buf)); fflush (stdout);
1.188 - if (pad->frame_count < 300) {
1.189 - GF_ISOSample *sample = gf_isom_sample_new();
1.190 -
1.191 - sample->dataLength = GST_BUFFER_SIZE(buf);
1.192 - sample->data = GST_BUFFER_DATA(buf);
1.193 - sample->CTS_Offset = 0;
1.194 -
1.195 - if (pad->is_video) {
1.196 - sample->IsRAP = 0;
1.197 - sample->DTS += 1000*pad->frame_count;
1.198 - } else {
1.199 - sample->IsRAP = 0;
1.200 - sample->DTS = 2048*pad->frame_count;
1.201 - }
1.202 -
1.203 - gf_isom_add_sample(gpac_mux->file, pad->track_number,
1.204 - pad->di, sample);
1.205 - sample->data = NULL;
1.206 -
1.207 - gf_isom_sample_del(&sample);
1.208 -
1.209 - printf ("xxxx frames %d\n", pad->frame_count);
1.210 -
1.211 - } else if (pad->frame_count == 300) {
1.212 - printf ("XXX closing gpac output file\n"); fflush (stdout);
1.213 - gf_isom_close (gpac_mux->file);
1.214 - }
1.215 -
1.216 - /* gstreamer output (push) */
1.217 - if (gst_gpac_mux_push_buffer (gpac_mux, buf) != GST_FLOW_OK) {
1.218 - printf ("EEEEEEEE push failed\n");
1.219 - }
1.220 -
1.221 - iter = g_slist_next (iter);
1.222 - pad->frame_count++;
1.223 - i++;
1.224 + if (pad->buffer == NULL) {
1.225 + printf ("Buffer is null, wrong state\n");
1.226 + return GST_FLOW_WRONG_STATE;
1.227 }
1.228
1.229 - /* fixme */
1.230 + /* gpac output */
1.231 + printf ("xxxxxx buffer size: %d\n", GST_BUFFER_SIZE(pad->buffer)); fflush (stdout);
1.232 + printf ("xxxx frames %d\n", pad->frame_count);
1.233 +
1.234 + sample = gf_isom_sample_new();
1.235 + sample->dataLength = GST_BUFFER_SIZE(pad->buffer);
1.236 + sample->data = GST_BUFFER_DATA(pad->buffer);
1.237 + sample->CTS_Offset = 0;
1.238 +
1.239 + if (pad->is_video) {
1.240 + sample->IsRAP = 0;
1.241 + sample->DTS += 1000*pad->frame_count;
1.242 + } else {
1.243 + sample->IsRAP = 0;
1.244 + sample->DTS = 2048*pad->frame_count;
1.245 + }
1.246 +
1.247 + gf_isom_add_sample(gpac_mux->file, pad->track_number,
1.248 + pad->di, sample);
1.249 + sample->data = NULL;
1.250 +
1.251 + gf_isom_sample_del(&sample);
1.252 +
1.253 +
1.254 + /* gstreamer output (push) */
1.255 + ret = gst_gpac_mux_push_buffer (gpac_mux, pad->buffer);
1.256 + pad->buffer = NULL;
1.257 +
1.258 + if (ret != GST_FLOW_OK) {
1.259 + }
1.260 +
1.261 + pad->frame_count++;
1.262 +
1.263 return ret;
1.264 }
1.265
1.266 @@ -504,13 +547,13 @@
1.267 static void
1.268 gst_gpac_mux_init_collectpads (GstCollectPads * collect)
1.269 {
1.270 - GSList *walk;
1.271 + GSList *iter;
1.272
1.273 - walk = collect->data;
1.274 - while (walk) {
1.275 - GstGpacPad *gpacpad = (GstGpacPad *) walk->data;
1.276 + iter = collect->data;
1.277 + while (iter) {
1.278 + GstGpacPad *gpacpad = (GstGpacPad *) iter->data;
1.279
1.280 - //ogg_stream_init (&gpacpad->stream, gpacpad->serial);
1.281 + //gpac_stream_init (&gpacpad->stream, gpacpad->serial);
1.282 //gpacpad->packetno = 0;
1.283 //gpacpad->pageno = 0;
1.284 //gpacpad->eos = FALSE;
1.285 @@ -521,7 +564,7 @@
1.286 //gpacpad->prev_delta = FALSE;
1.287 //gpacpad->pagebuffers = g_queue_new ();
1.288
1.289 - walk = g_slist_next (walk);
1.290 + iter = g_slist_next (iter);
1.291 }
1.292 }
1.293
1.294 @@ -529,10 +572,10 @@
1.295 static void
1.296 gst_gpac_mux_clear_collectpads (GstCollectPads * collect)
1.297 {
1.298 - GSList *walk;
1.299 + GSList *iter;
1.300
1.301 - for (walk = collect->data; walk; walk = g_slist_next (walk)) {
1.302 - GstGpacPad *gpacpad = (GstGpacPad *) walk->data;
1.303 + for (iter = collect->data; iter; iter = g_slist_next (iter)) {
1.304 + GstGpacPad *gpacpad = (GstGpacPad *) iter->data;
1.305 GstBuffer *buf;
1.306
1.307 //gpac_stream_clear (&gpacpad->stream);
1.308 @@ -588,6 +631,97 @@
1.309
1.310 }
1.311
1.312 +static GstGpacPad *
1.313 +gst_gpac_mux_queue_pads (GstGpacMux * gpac_mux)
1.314 +{
1.315 + GstGpacPad *bestpad = NULL;//, *still_hungry = NULL;
1.316 + GSList *iter;
1.317 +
1.318 + /* try to make sure we have a buffer from each usable pad first */
1.319 + iter = gpac_mux->collect->data;
1.320 + while (iter) {
1.321 + GstGpacPad *pad;
1.322 + GstCollectData *data;
1.323 +
1.324 + data = (GstCollectData *) iter->data;
1.325 + pad = (GstGpacPad *) data;
1.326 +
1.327 + iter = g_slist_next (iter);
1.328 +
1.329 + GST_LOG_OBJECT (data->pad, "looking at pad for buffer");
1.330 +
1.331 + /* try to get a new buffer for this pad if needed and possible */
1.332 + if (pad->buffer == NULL) {
1.333 + GstBuffer *buf;
1.334 +
1.335 + buf = gst_collect_pads_pop (gpac_mux->collect, data);
1.336 + GST_LOG_OBJECT (data->pad, "popped buffer %" GST_PTR_FORMAT, buf);
1.337 +
1.338 + /* On EOS we get a NULL buffer */
1.339 + if (buf == NULL) {
1.340 + printf ("EENENENENENEND OF STREAM EOS\n");
1.341 + GST_DEBUG_OBJECT (data->pad, "EOS on pad");
1.342 + if (!pad->eos) {
1.343 + /* it's no longer active */
1.344 + gpac_mux->active_pads--;
1.345 + pad->eos = TRUE;
1.346 +
1.347 + }
1.348 + }
1.349 +
1.350 + pad->buffer = buf;
1.351 + }
1.352 +
1.353 + /* we should have a buffer now, see if it is the best pad to
1.354 + * pull on */
1.355 + if (gst_gpac_mux_compare_pads (gpac_mux, bestpad, pad) > 0) {
1.356 + GST_LOG_OBJECT (data->pad,
1.357 + "new best pad, with buffers %" GST_PTR_FORMAT, pad->buffer);
1.358 + bestpad = pad;
1.359 + }
1.360 + }
1.361 +
1.362 + return bestpad;
1.363 +}
1.364 +
1.365 +static gint
1.366 +gst_gpac_mux_compare_pads (GstGpacMux * ogg_mux, GstGpacPad *first,
1.367 + GstGpacPad *second)
1.368 +{
1.369 + guint64 firsttime, secondtime;
1.370 +
1.371 + /* if the first pad doesn't contain anything or is even NULL, return
1.372 + * the second pad as best candidate and vice versa */
1.373 + if (first == NULL || (first->buffer == NULL))
1.374 + return 1;
1.375 + if (second == NULL || (second->buffer == NULL))
1.376 + return -1;
1.377 +
1.378 + /* no timestamp on first buffer, it must go first */
1.379 + if (first->buffer)
1.380 + firsttime = GST_BUFFER_TIMESTAMP (first->buffer);
1.381 + if (firsttime == GST_CLOCK_TIME_NONE)
1.382 + return -1;
1.383 +
1.384 + /* no timestamp on second buffer, it must go first */
1.385 + if (second->buffer)
1.386 + secondtime = GST_BUFFER_TIMESTAMP (second->buffer);
1.387 + if (secondtime == GST_CLOCK_TIME_NONE)
1.388 + return 1;
1.389 +
1.390 + /* first buffer has higher timestamp, second one should go first */
1.391 + if (secondtime < firsttime)
1.392 + return 1;
1.393 + /* second buffer has higher timestamp, first one should go first */
1.394 + else if (secondtime > firsttime)
1.395 + return -1;
1.396 +
1.397 + /* same priority if all of the above failed */
1.398 + return 0;
1.399 +}
1.400 +
1.401 +
1.402 +
1.403 static gboolean
1.404 gst_gpac_mux_plugin_init (GstPlugin * plugin)
1.405 {