diff options
| author | Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> | 2009-10-09 16:21:03 +0200 | 
|---|---|---|
| committer | Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> | 2009-10-09 17:49:12 +0200 | 
| commit | 5ed2c3e5628f44775a76ae8937033180b43f99fb (patch) | |
| tree | 4c5f030d99f29bfd32999a9ab0a6ad552f6cb3a9 | |
| parent | 674b0c4289fcdab6fdf8d6a7ccf2921931e2524b (diff) | |
qtdemux: refactor buffer processing and sending
... so it can be used in both pull and push based mode.
| -rw-r--r-- | gst/qtdemux/qtdemux.c | 242 | ||||
| -rw-r--r-- | gst/qtdemux/qtdemux.h | 3 | 
2 files changed, 121 insertions, 124 deletions
diff --git a/gst/qtdemux/qtdemux.c b/gst/qtdemux/qtdemux.c index f41c71e8..7b58af54 100644 --- a/gst/qtdemux/qtdemux.c +++ b/gst/qtdemux/qtdemux.c @@ -399,8 +399,6 @@ gst_qtdemux_init (GstQTDemux * qtdemux)    gst_element_add_pad (GST_ELEMENT_CAST (qtdemux), qtdemux->sinkpad);    qtdemux->state = QTDEMUX_STATE_INITIAL; -  /* FIXME, use segment last_stop for this */ -  qtdemux->last_ts = GST_CLOCK_TIME_NONE;    qtdemux->pullbased = FALSE;    qtdemux->neededbytes = 16;    qtdemux->todrop = 0; @@ -1396,7 +1394,6 @@ gst_qtdemux_change_state (GstElement * element, GstStateChange transition)        gint n;        qtdemux->state = QTDEMUX_STATE_INITIAL; -      qtdemux->last_ts = GST_CLOCK_TIME_NONE;        qtdemux->neededbytes = 16;        qtdemux->todrop = 0;        qtdemux->pullbased = FALSE; @@ -1938,22 +1935,6 @@ gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,    GST_LOG_OBJECT (qtdemux, "segment active, index = %u of %u",        stream->sample_index, stream->n_samples); -  /* send out pending buffers */ -  while (stream->buffers) { -    GstBuffer *buffer = (GstBuffer *) stream->buffers->data; - -    if (G_UNLIKELY (stream->discont)) { -      GST_LOG_OBJECT (qtdemux, "marking discont buffer"); -      GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); -      stream->discont = FALSE; -    } -    gst_buffer_set_caps (buffer, stream->caps); - -    gst_pad_push (stream->pad, buffer); - -    stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers); -  } -    if (G_UNLIKELY (stream->sample_index >= stream->n_samples))      goto eos; @@ -1966,12 +1947,6 @@ gst_qtdemux_prepare_current_sample (GstQTDemux * qtdemux,    *duration = sample->duration;    *keyframe = stream->all_keyframe || sample->keyframe; -  /* add padding */ -  if (stream->padding) { -    *offset += stream->padding; -    *size -= stream->padding; -  } -    return TRUE;    /* special cases */ @@ -2304,6 +2279,105 @@ gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,    return buf;  } +/* Sets a buffer's attributes properly and pushes it downstream. + * Also checks for additional actions and custom processing that may + * need to be done first. + */ +static gboolean +gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux, +    QtDemuxStream * stream, GstBuffer * buf, +    guint64 timestamp, guint64 duration, gboolean keyframe, guint64 position) +{ +  GstFlowReturn ret = GST_FLOW_OK; + +  if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) { +    GstMessage *m; +    gchar *url; + +    url = g_strndup ((gchar *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + +    /* we have RTSP redirect now */ +    m = gst_message_new_element (GST_OBJECT_CAST (qtdemux), +        gst_structure_new ("redirect", +            "new-location", G_TYPE_STRING, url, NULL)); +    g_free (url); + +    gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m); +  } + +  /* position reporting */ +  if (qtdemux->segment.rate >= 0) { +    gst_segment_set_last_stop (&qtdemux->segment, GST_FORMAT_TIME, position); +    gst_qtdemux_sync_streams (qtdemux); +  } + +  if (G_UNLIKELY (!stream->pad)) { +    GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring"); +    gst_buffer_unref (buf); +    goto exit; +  } + +  /* send out pending buffers */ +  while (stream->buffers) { +    GstBuffer *buffer = (GstBuffer *) stream->buffers->data; + +    if (G_UNLIKELY (stream->discont)) { +      GST_LOG_OBJECT (qtdemux, "marking discont buffer"); +      GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); +      stream->discont = FALSE; +    } +    gst_buffer_set_caps (buffer, stream->caps); + +    gst_pad_push (stream->pad, buffer); + +    stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers); +  } + +  /* we're going to modify the metadata */ +  buf = gst_buffer_make_metadata_writable (buf); + +  if (G_UNLIKELY (stream->need_process)) +    buf = gst_qtdemux_process_buffer (qtdemux, stream, buf); + +  GST_BUFFER_TIMESTAMP (buf) = timestamp; +  GST_BUFFER_DURATION (buf) = duration; +  GST_BUFFER_OFFSET (buf) = -1; +  GST_BUFFER_OFFSET_END (buf) = -1; + +  if (G_UNLIKELY (stream->padding)) { +    GST_BUFFER_DATA (buf) += stream->padding; +    GST_BUFFER_SIZE (buf) -= stream->padding; +  } + +  if (stream->need_clip) +    buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf); + +  if (G_UNLIKELY (buf == NULL)) +    goto exit; + +  if (G_UNLIKELY (stream->discont)) { +    GST_LOG_OBJECT (qtdemux, "marking discont buffer"); +    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); +    stream->discont = FALSE; +  } + +  if (!keyframe) +    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); + +  gst_buffer_set_caps (buf, stream->caps); + +  GST_LOG_OBJECT (qtdemux, +      "Pushing buffer with time %" GST_TIME_FORMAT ", duration %" +      GST_TIME_FORMAT " on pad %s", +      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), +      GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad)); + +  ret = gst_pad_push (stream->pad, buf); + +exit: +  return ret; +} +  static GstFlowReturn  gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)  { @@ -2377,67 +2451,8 @@ gst_qtdemux_loop_state_movie (GstQTDemux * qtdemux)    if (G_UNLIKELY (ret != GST_FLOW_OK))      goto beach; -  if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) { -    GstMessage *m; -    gchar *url; - -    url = g_strndup ((gchar *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); - -    /* we have RTSP redirect now */ -    m = gst_message_new_element (GST_OBJECT_CAST (qtdemux), -        gst_structure_new ("redirect", -            "new-location", G_TYPE_STRING, url, NULL)); -    g_free (url); - -    gst_element_post_message (GST_ELEMENT_CAST (qtdemux), m); -  } - -  qtdemux->last_ts = min_time; -  if (qtdemux->segment.rate >= 0) { -    gst_segment_set_last_stop (&qtdemux->segment, GST_FORMAT_TIME, min_time); -    gst_qtdemux_sync_streams (qtdemux); -  } -  if (G_LIKELY (stream->pad)) { -    /* we're going to modify the metadata */ -    buf = gst_buffer_make_metadata_writable (buf); - -    if (G_UNLIKELY (stream->need_process)) -      buf = gst_qtdemux_process_buffer (qtdemux, stream, buf); - -    GST_BUFFER_TIMESTAMP (buf) = timestamp; -    GST_BUFFER_DURATION (buf) = duration; -    GST_BUFFER_OFFSET (buf) = -1; -    GST_BUFFER_OFFSET_END (buf) = -1; - -    if (stream->need_clip) -      buf = gst_qtdemux_clip_buffer (qtdemux, stream, buf); - -    if (buf == NULL) -      goto next; - -    if (stream->discont) { -      GST_LOG_OBJECT (qtdemux, "marking discont buffer"); -      GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); -      stream->discont = FALSE; -    } - -    if (!keyframe) -      GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); - -    gst_buffer_set_caps (buf, stream->caps); - -    GST_LOG_OBJECT (qtdemux, -        "Pushing buffer with time %" GST_TIME_FORMAT ", duration %" -        GST_TIME_FORMAT " on pad %s", -        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), -        GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_PAD_NAME (stream->pad)); - -    ret = gst_pad_push (stream->pad, buf); -  } else { -    GST_DEBUG_OBJECT (qtdemux, "No output pad for stream, ignoring"); -    gst_buffer_unref (buf); -    ret = GST_FLOW_OK; -  } +  ret = gst_qtdemux_decorate_and_push_buffer (qtdemux, stream, buf, +      timestamp, duration, keyframe, min_time);    /* combine flows */    ret = gst_qtdemux_combine_flows (qtdemux, stream, ret); @@ -2676,6 +2691,13 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)          guint32 fourcc;          guint64 size; +        /* prepare newsegment to send when streaming actually starts */ +        if (!demux->pending_newsegment) { +          demux->pending_newsegment = +              gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, +              0, GST_CLOCK_TIME_NONE, 0); +        } +          data = gst_adapter_peek (demux->adapter, demux->neededbytes);          /* get fourcc/length, set neededbytes */ @@ -2809,6 +2831,8 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)          GstBuffer *outbuf;          QtDemuxStream *stream = NULL;          int i = -1; +        guint64 timestamp, duration, position; +        gboolean keyframe;          GST_DEBUG_OBJECT (demux,              "BEGIN // in MOVIE for offset %" G_GUINT64_FORMAT, demux->offset); @@ -2823,10 +2847,9 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)          /* first buffer? */          /* initial newsegment sent here after having added pads,           * possible others in sink_event */ -        if (G_UNLIKELY (demux->last_ts == GST_CLOCK_TIME_NONE)) { -          gst_qtdemux_push_event (demux, -              gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, -                  0, GST_CLOCK_TIME_NONE, 0)); +        if (G_UNLIKELY (demux->pending_newsegment)) { +          gst_qtdemux_push_event (demux, demux->pending_newsegment); +          demux->pending_newsegment = NULL;            /* clear to send tags on all streams */            for (i = 0; i < demux->n_streams; i++) {              gst_qtdemux_push_tags (demux, demux->streams[i]); @@ -2858,37 +2881,14 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)          g_return_val_if_fail (outbuf != NULL, GST_FLOW_ERROR); -        if (stream->samples[stream->sample_index].pts_offset) { -          demux->last_ts = stream->samples[stream->sample_index].timestamp; -          GST_BUFFER_TIMESTAMP (outbuf) = demux->last_ts + -              stream->samples[stream->sample_index].pts_offset; -        } else { -          GST_BUFFER_TIMESTAMP (outbuf) = -              stream->samples[stream->sample_index].timestamp; -          demux->last_ts = GST_BUFFER_TIMESTAMP (outbuf); -        } -        GST_BUFFER_DURATION (outbuf) = -            stream->samples[stream->sample_index].duration; -        if (!stream->all_keyframe && -            !stream->samples[stream->sample_index].keyframe) -          GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT); - -        /* position reporting */ -        gst_segment_set_last_stop (&demux->segment, GST_FORMAT_TIME, -            demux->last_ts); -        gst_qtdemux_sync_streams (demux); - -        /* send buffer */ -        if (stream->pad) { -          GST_LOG_OBJECT (demux, -              "Pushing buffer with time %" GST_TIME_FORMAT " on pad %p", -              GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)), stream->pad); -          gst_buffer_set_caps (outbuf, stream->caps); -          ret = gst_pad_push (stream->pad, outbuf); -        } else { -          gst_buffer_unref (outbuf); -          ret = GST_FLOW_OK; -        } +        position = stream->samples[stream->sample_index].timestamp; +        timestamp = position + stream->samples[stream->sample_index].pts_offset; +        duration = stream->samples[stream->sample_index].duration; +        keyframe = stream->all_keyframe || +            stream->samples[stream->sample_index].keyframe; + +        ret = gst_qtdemux_decorate_and_push_buffer (demux, stream, outbuf, +            timestamp, duration, keyframe, position);          /* combine flows */          ret = gst_qtdemux_combine_flows (demux, stream, ret); diff --git a/gst/qtdemux/qtdemux.h b/gst/qtdemux/qtdemux.h index 23d0c4dd..6521dd21 100644 --- a/gst/qtdemux/qtdemux.h +++ b/gst/qtdemux/qtdemux.h @@ -89,9 +89,6 @@ struct _GstQTDemux {    GstTagList *tag_list; -  /* track stuff */ -  guint64 last_ts; -    /* configured playback region */    GstSegment segment;    gboolean segment_running;  | 
