switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_QOS:
{
+ GstQOSType type;
gdouble proportion;
GstClockTimeDiff diff;
GstClockTime timestamp;
- gst_event_parse_qos (event, &proportion, &diff, ×tamp);
+ gst_event_parse_qos (event, &type, &proportion, &diff, ×tamp);
/* update our QoS values */
gst_ffmpegdec_update_qos (ffmpegdec, proportion, timestamp + diff);
* fsize contains the size of the palette, so the overall size
* is bigger than ffmpegcolorspace's unit size, which will
* prompt GstBaseTransform to complain endlessly ... */
- *outbuf = new_aligned_buffer (fsize, GST_PAD_CAPS (ffmpegdec->srcpad));
+ *outbuf = new_aligned_buffer (fsize);
ret = GST_FLOW_OK;
}
- /* set caps, we do this here because the buffer is still writable here and we
- * are sure to be negotiated */
- gst_buffer_set_caps (*outbuf, GST_PAD_CAPS (ffmpegdec->srcpad));
return ret;
GstClockTime in_dur)
{
gboolean res = TRUE;
- gint64 cstart, cstop;
+ guint64 cstart, cstop;
GstClockTime stop;
GST_LOG_OBJECT (dec,
GstClockTime in_dur)
{
GstClockTime stop;
- gint64 diff, ctime, cstop;
+ gint64 diff;
+ guint64 ctime, cstop;
gboolean res = TRUE;
gsize size, offset;
dec_info->offset, GST_TIME_ARGS (dec_info->timestamp),
GST_TIME_ARGS (dec_info->duration), GST_TIME_ARGS (ffmpegdec->next_out));
- *outbuf =
- new_aligned_buffer (AVCODEC_MAX_AUDIO_FRAME_SIZE,
- GST_PAD_CAPS (ffmpegdec->srcpad));
+ *outbuf = new_aligned_buffer (AVCODEC_MAX_AUDIO_FRAME_SIZE);
odata = gst_buffer_map (*outbuf, NULL, NULL, GST_MAP_WRITE);
GST_BUFFER_TIMESTAMP (*outbuf) = out_timestamp;
GST_BUFFER_DURATION (*outbuf) = out_duration;
GST_BUFFER_OFFSET (*outbuf) = out_offset;
- gst_buffer_set_caps (*outbuf, GST_PAD_CAPS (ffmpegdec->srcpad));
/* the next timestamp we'll use when interpolating */
ffmpegdec->next_out = out_timestamp + out_duration;
clear_queued (ffmpegdec);
break;
}
- case GST_EVENT_NEWSEGMENT:
+ case GST_EVENT_SEGMENT:
{
- gboolean update;
- GstFormat fmt;
- gint64 start, stop, time;
- gdouble rate, arate;
+ GstSegment segment;
- gst_event_parse_new_segment_full (event, &update, &rate, &arate, &fmt,
- &start, &stop, &time);
+ gst_event_copy_segment (event, &segment);
- switch (fmt) {
+ switch (segment.format) {
case GST_FORMAT_TIME:
/* fine, our native segment format */
break;
GST_DEBUG_OBJECT (ffmpegdec, "bitrate: %d", bit_rate);
/* convert values to TIME */
- if (start != -1)
- start = gst_util_uint64_scale_int (start, GST_SECOND, bit_rate);
- if (stop != -1)
- stop = gst_util_uint64_scale_int (stop, GST_SECOND, bit_rate);
- if (time != -1)
- time = gst_util_uint64_scale_int (time, GST_SECOND, bit_rate);
+ if (segment.start != -1)
+ segment.start =
+ gst_util_uint64_scale_int (segment.start, GST_SECOND, bit_rate);
+ if (segment.stop != -1)
+ segment.stop =
+ gst_util_uint64_scale_int (segment.stop, GST_SECOND, bit_rate);
+ if (segment.time != -1)
+ segment.time =
+ gst_util_uint64_scale_int (segment.time, GST_SECOND, bit_rate);
/* unref old event */
gst_event_unref (event);
/* create new converted time segment */
- fmt = GST_FORMAT_TIME;
+ segment.format = GST_FORMAT_TIME;
/* FIXME, bitrate is not good enough too find a good stop, let's
* hope start and time were 0... meh. */
- stop = -1;
- event = gst_event_new_new_segment (update, rate, fmt,
- start, stop, time);
+ segment.stop = -1;
+ event = gst_event_new_segment (&segment);
break;
}
default:
if (ffmpegdec->context->codec)
gst_ffmpegdec_drain (ffmpegdec);
- GST_DEBUG_OBJECT (ffmpegdec,
- "NEWSEGMENT in time start %" GST_TIME_FORMAT " -- stop %"
- GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
+ GST_DEBUG_OBJECT (ffmpegdec, "SEGMENT in time %" GST_SEGMENT_FORMAT,
+ &segment);
/* and store the values */
- gst_segment_set_newsegment_full (&ffmpegdec->segment, update,
- rate, arate, fmt, start, stop, time);
+ gst_segment_copy_into (&segment, &ffmpegdec->segment);
break;
}
default:
gsize from_size, to_size;
outbuf = gst_buffer_new_and_alloc (deinterlace->to_size);
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (deinterlace->srcpad));
from_data = gst_buffer_map (inbuf, &from_size, NULL, GST_MAP_READ);
gst_ffmpeg_avpicture_fill (&deinterlace->from_frame, from_data,
/* segment stuff */
GstSegment segment;
- gboolean running;
/* cached seek in READY */
GstEvent *seek_event;
/* get the stream for seeking */
stream = demux->context->streams[index];
/* initial seek position */
- target = segment->last_stop;
+ target = segment->position;
/* convert target to ffmpeg time */
fftarget = gst_ffmpeg_time_gst_to_ff (target, stream->time_base);
GST_DEBUG_OBJECT (demux, "seek success, returned %d", seekret);
- segment->last_stop = target;
+ segment->position = target;
segment->time = target;
segment->start = target;
/* now configure the seek segment */
if (event) {
- gst_segment_set_seek (&seeksegment, rate, format, flags,
+ gst_segment_do_seek (&seeksegment, rate, format, flags,
cur_type, cur, stop_type, stop, &update);
}
GST_DEBUG_OBJECT (demux, "segment configured from %" G_GINT64_FORMAT
" to %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT,
- seeksegment.start, seeksegment.stop, seeksegment.last_stop);
+ seeksegment.start, seeksegment.stop, seeksegment.position);
/* make the sinkpad available for data passing since we might need
* it when doing the seek */
gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop ());
}
- /* do the seek, segment.last_stop contains new position. */
+ /* do the seek, segment.position contains new position. */
res = gst_ffmpegdemux_do_seek (demux, &seeksegment);
/* and prepare to continue streaming */
if (demux->streams[n])
demux->streams[n]->last_flow = GST_FLOW_OK;
}
- } else if (res && demux->running) {
- /* we are running the current segment and doing a non-flushing seek,
- * close the segment first based on the last_stop. */
- GST_DEBUG_OBJECT (demux, "closing running segment %" G_GINT64_FORMAT
- " to %" G_GINT64_FORMAT, demux->segment.start,
- demux->segment.last_stop);
-
- gst_ffmpegdemux_push_event (demux,
- gst_event_new_new_segment (TRUE,
- demux->segment.rate, demux->segment.format,
- demux->segment.start, demux->segment.last_stop,
- demux->segment.time));
}
/* if successfull seek, we update our real segment and push
* out the new segment. */
if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
gst_element_post_message (GST_ELEMENT (demux),
gst_message_new_segment_start (GST_OBJECT (demux),
- demux->segment.format, demux->segment.last_stop));
+ demux->segment.format, demux->segment.position));
}
- /* now send the newsegment */
+ /* now send the newsegment, FIXME, do this from the streaming thread */
GST_DEBUG_OBJECT (demux, "Sending newsegment from %" G_GINT64_FORMAT
- " to %" G_GINT64_FORMAT, demux->segment.last_stop, demux->segment.stop);
+ " to %" G_GINT64_FORMAT, demux->segment.position, demux->segment.stop);
- gst_ffmpegdemux_push_event (demux,
- gst_event_new_new_segment (FALSE,
- demux->segment.rate, demux->segment.format,
- demux->segment.last_stop, demux->segment.stop,
- demux->segment.time));
+ gst_ffmpegdemux_push_event (demux, gst_event_new_segment (&demux->segment));
}
/* Mark discont on all srcpads and remove eos */
/* and restart the task in case it got paused explicitely or by
* the FLUSH_START event we pushed out. */
- demux->running = TRUE;
gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_ffmpegdemux_loop,
demux->sinkpad);
GST_TIME_ARGS (demux->duration));
/* store duration in the segment as well */
- gst_segment_set_duration (&demux->segment, GST_FORMAT_TIME, demux->duration);
+ demux->segment.duration = demux->duration;
GST_OBJECT_LOCK (demux);
demux->opened = TRUE;
gst_ffmpegdemux_perform_seek (demux, event);
gst_event_unref (event);
} else {
- gst_ffmpegdemux_push_event (demux,
- gst_event_new_new_segment (FALSE,
- demux->segment.rate, demux->segment.format,
- demux->segment.start, demux->segment.stop, demux->segment.time));
+ gst_ffmpegdemux_push_event (demux, gst_event_new_segment (&demux->segment));
}
while (cached_events) {
event = cached_events->data;
- GST_INFO_OBJECT (demux, "pushing cached %s event: %" GST_PTR_FORMAT,
- GST_EVENT_TYPE_NAME (event), event->structure);
+ GST_INFO_OBJECT (demux, "pushing cached event: %" GST_PTR_FORMAT, event);
gst_ffmpegdemux_push_event (demux, event);
cached_events = g_list_delete_link (cached_events, cached_events);
}
outsize = pkt.size;
outbuf = gst_buffer_new_and_alloc (outsize);
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (srcpad));
if ((ret = gst_ffmpegdemux_aggregated_flow (demux)) != GST_FLOW_OK)
goto no_buffer;
{
GST_LOG_OBJECT (demux, "pausing task, reason %d (%s)", ret,
gst_flow_get_name (ret));
- demux->running = FALSE;
if (demux->seekable)
gst_pad_pause_task (demux->sinkpad);
else {
demux = (GstFFMpegDemux *) (GST_PAD_PARENT (sinkpad));
ffpipe = &(demux->ffpipe);
- GST_LOG_OBJECT (demux, "%s event: %" GST_PTR_FORMAT,
- GST_EVENT_TYPE_NAME (event), event->structure);
+ GST_LOG_OBJECT (demux, "event: %" GST_PTR_FORMAT, event);
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START:
ffpipe->srcresult = GST_FLOW_OK;
/* loop may have decided to end itself as a result of flush WRONG_STATE */
gst_task_start (demux->task);
- demux->running = TRUE;
demux->flushing = FALSE;
GST_LOG_OBJECT (demux, "loop started");
GST_FFMPEG_PIPE_MUTEX_UNLOCK (ffpipe);
static gboolean
gst_ffmpegdemux_sink_activate (GstPad * sinkpad)
{
- GstFFMpegDemux *demux;
- gboolean res;
+ GstQuery *query;
+ gboolean pull_mode;
- demux = (GstFFMpegDemux *) (gst_pad_get_parent (sinkpad));
+ query = gst_query_new_scheduling ();
+
+ if (!gst_pad_peer_query (sinkpad, query)) {
+ gst_query_unref (query);
+ goto activate_push;
+ }
- res = FALSE;
+ gst_query_parse_scheduling (query, &pull_mode, NULL, NULL, NULL, NULL, NULL);
- if (gst_pad_check_pull_range (sinkpad))
- res = gst_pad_activate_pull (sinkpad, TRUE);
- else {
- res = gst_pad_activate_push (sinkpad, TRUE);
+ if (!pull_mode)
+ goto activate_push;
+
+ GST_DEBUG_OBJECT (sinkpad, "activating pull");
+ return gst_pad_activate_pull (sinkpad, TRUE);
+
+activate_push:
+ {
+ GST_DEBUG_OBJECT (sinkpad, "activating push");
+ return gst_pad_activate_push (sinkpad, TRUE);
}
- gst_object_unref (demux);
- return res;
}
/* push mode:
demux->ffpipe.eos = FALSE;
demux->ffpipe.srcresult = GST_FLOW_OK;
demux->ffpipe.needed = 0;
- demux->running = TRUE;
demux->seekable = FALSE;
res = gst_task_start (demux->task);
} else {
g_static_rec_mutex_lock (demux->task_lock);
g_static_rec_mutex_unlock (demux->task_lock);
res = gst_task_join (demux->task);
- demux->running = FALSE;
demux->seekable = FALSE;
}
demux = (GstFFMpegDemux *) (gst_pad_get_parent (sinkpad));
if (active) {
- demux->running = TRUE;
demux->seekable = TRUE;
res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_ffmpegdemux_loop,
demux);
} else {
- demux->running = FALSE;
res = gst_pad_stop_task (sinkpad);
demux->seekable = FALSE;
}
static void gst_ffmpegenc_finalize (GObject * object);
static gboolean gst_ffmpegenc_setcaps (GstPad * pad, GstCaps * caps);
-static GstCaps *gst_ffmpegenc_getcaps (GstPad * pad);
+static GstCaps *gst_ffmpegenc_getcaps (GstPad * pad, GstCaps * filter);
static GstFlowReturn gst_ffmpegenc_chain_video (GstPad * pad,
GstBuffer * buffer);
static GstFlowReturn gst_ffmpegenc_chain_audio (GstPad * pad,
GstCaps *intersect = NULL;
guint i;
- othercaps = gst_pad_peer_get_caps (ffmpegenc->srcpad);
+ othercaps = gst_pad_peer_get_caps (ffmpegenc->srcpad, NULL);
if (!othercaps)
return gst_caps_copy (caps);
static GstCaps *
-gst_ffmpegenc_getcaps (GstPad * pad)
+gst_ffmpegenc_getcaps (GstPad * pad, GstCaps * filter)
{
GstFFMpegEnc *ffmpegenc = (GstFFMpegEnc *) GST_PAD_PARENT (pad);
GstFFMpegEncClass *oclass =
if (ffmpegenc->opened) {
gst_ffmpeg_avcodec_close (ffmpegenc->context);
ffmpegenc->opened = FALSE;
- /* fixed src caps;
- * so clear src caps for proper (re-)negotiation */
- gst_pad_set_caps (ffmpegenc->srcpad, NULL);
}
/* set defaults */
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
} else
GST_WARNING_OBJECT (ffmpegenc, "codec did not provide keyframe info");
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (ffmpegenc->srcpad));
gst_buffer_unref (inbuf);
GST_BUFFER_DURATION (outbuf) = duration;
if (discont)
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (ffmpegenc->srcpad));
GST_LOG_OBJECT (ffmpegenc, "pushing size %d, timestamp %" GST_TIME_FORMAT,
res, GST_TIME_ARGS (timestamp));
if (!ffmpegenc->context->coded_frame->key_frame)
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (ffmpegenc->srcpad));
gst_buffer_unref (inbuf);
static gboolean gst_ffmpegmux_setcaps (GstPad * pad, GstCaps * caps);
static GstPad *gst_ffmpegmux_request_new_pad (GstElement * element,
- GstPadTemplate * templ, const gchar * name);
+ GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
static GstFlowReturn gst_ffmpegmux_collected (GstCollectPads * pads,
gpointer user_data);
static GstPad *
gst_ffmpegmux_request_new_pad (GstElement * element,
- GstPadTemplate * templ, const gchar * name)
+ GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
{
GstFFMpegMux *ffmpegmux = (GstFFMpegMux *) element;
GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
/* create buffer and push data further */
outbuf = gst_buffer_new_and_alloc (size);
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (info->pad));
gst_buffer_fill (outbuf, 0, buf, size);
gst_ffmpegdata_seek (URLContext * h, int64_t pos, int whence)
{
GstProtocolInfo *info;
- guint64 newpos = 0;
+ guint64 newpos = 0, oldpos;
GST_DEBUG ("Seeking to %" G_GINT64_FORMAT ", whence=%d",
(gint64) pos, whence);
break;
case URL_WRONLY:
{
+ GstSegment segment;
+
+ oldpos = info->offset;
+
/* srcpad */
switch (whence) {
case SEEK_SET:
+ {
info->offset = (guint64) pos;
- gst_pad_push_event (info->pad, gst_event_new_new_segment
- (TRUE, 1.0, GST_FORMAT_BYTES, info->offset,
- GST_CLOCK_TIME_NONE, info->offset));
break;
+ }
case SEEK_CUR:
info->offset += pos;
- gst_pad_push_event (info->pad, gst_event_new_new_segment
- (TRUE, 1.0, GST_FORMAT_BYTES, info->offset,
- GST_CLOCK_TIME_NONE, info->offset));
break;
default:
break;
}
newpos = info->offset;
- }
+
+ if (newpos != oldpos) {
+ gst_segment_init (&segment, GST_FORMAT_BYTES);
+ segment.start = newpos;
+ segment.time = newpos;
+ gst_pad_push_event (info->pad, gst_event_new_segment (&segment));
+ }
break;
+ }
default:
g_assert (0);
break;
* for any processing. */
GstBuffer *
-new_aligned_buffer (gint size, GstCaps * caps)
+new_aligned_buffer (gint size)
{
GstBuffer *buf;
buf = gst_buffer_new ();
gst_buffer_take_memory (buf,
gst_memory_new_wrapped (0, av_malloc (size), av_free, size, 0, size));
- if (caps)
- gst_buffer_set_caps (buf, caps);
return buf;
}
av_smp_format_depth(enum SampleFormat smp_fmt);
GstBuffer *
-new_aligned_buffer (gint size, GstCaps * caps);
+new_aligned_buffer (gint size);
#endif /* __GST_FFMPEG_UTILS_H__ */
static gboolean gst_ffmpegscale_stop (GstBaseTransform * trans);
static GstCaps *gst_ffmpegscale_transform_caps (GstBaseTransform * trans,
- GstPadDirection direction, GstCaps * caps);
+ GstPadDirection direction, GstCaps * caps, GstCaps * filter);
static void gst_ffmpegscale_fixate_caps (GstBaseTransform * trans,
GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
static gboolean gst_ffmpegscale_get_unit_size (GstBaseTransform * trans,
static GstCaps *
gst_ffmpegscale_transform_caps (GstBaseTransform * trans,
- GstPadDirection direction, GstCaps * caps)
+ GstPadDirection direction, GstCaps * caps, GstCaps * filter)
{
GstCaps *ret;
GstStructure *structure;