diff options
Diffstat (limited to 'gst')
-rw-r--r-- | gst/aacparse/gstbaseparse.c | 89 | ||||
-rw-r--r-- | gst/aacparse/gstbaseparse.h | 3 | ||||
-rw-r--r-- | gst/amrparse/gstbaseparse.c | 89 | ||||
-rw-r--r-- | gst/amrparse/gstbaseparse.h | 3 | ||||
-rw-r--r-- | gst/camerabin/TODO | 31 | ||||
-rw-r--r-- | gst/camerabin/camerabinimage.c | 8 | ||||
-rw-r--r-- | gst/camerabin/camerabinpreview.c | 5 | ||||
-rw-r--r-- | gst/camerabin/camerabinvideo.c | 9 | ||||
-rw-r--r-- | gst/camerabin/gstcamerabin.c | 20 | ||||
-rw-r--r-- | gst/debugutils/fpsdisplaysink.c | 5 | ||||
-rw-r--r-- | gst/mpegdemux/gstmpegdemux.c | 73 | ||||
-rw-r--r-- | gst/mpegdemux/gstmpegtsdemux.c | 48 | ||||
-rw-r--r-- | gst/mpegdemux/gstpesfilter.c | 49 | ||||
-rw-r--r-- | gst/mpegdemux/mpegtspacketizer.c | 10 | ||||
-rw-r--r-- | gst/mpegdemux/mpegtsparse.c | 55 | ||||
-rw-r--r-- | gst/mxf/mxfdemux.c | 55 | ||||
-rw-r--r-- | gst/pcapparse/gstpcapparse.h | 7 | ||||
-rw-r--r-- | gst/real/gstrealaudiodec.c | 14 | ||||
-rw-r--r-- | gst/real/gstrealvideodec.c | 20 |
19 files changed, 466 insertions, 127 deletions
diff --git a/gst/aacparse/gstbaseparse.c b/gst/aacparse/gstbaseparse.c index 026b1341..b59319a5 100644 --- a/gst/aacparse/gstbaseparse.c +++ b/gst/aacparse/gstbaseparse.c @@ -735,7 +735,6 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, GstBaseParseClass * klass, GstBuffer * buffer) { GstFlowReturn ret; - GstClockTime last_stop = GST_CLOCK_TIME_NONE; if (parse->priv->discont) { GST_DEBUG_OBJECT (parse, "marking DISCONT"); @@ -749,6 +748,46 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, * keep track of timestamp and calculate everything possible * if not set already */ + /* First buffers are dropped, this means that the subclass needs more + * frames to decide on the format and queues them internally */ + if (ret == GST_BASE_PARSE_FLOW_DROPPED && !GST_PAD_CAPS (parse->srcpad)) { + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } + + /* convert internal flow to OK and mark discont for the next buffer. */ + if (ret == GST_BASE_PARSE_FLOW_DROPPED) { + parse->priv->discont = TRUE; + ret = GST_FLOW_OK; + + gst_buffer_unref (buffer); + + return ret; + } else if (ret != GST_FLOW_OK) { + return ret; + } + + return gst_base_parse_push_buffer (parse, buffer); +} + +/** + * gst_base_parse_push_buffer: + * @parse: #GstBaseParse. + * @buffer: #GstBuffer. + * + * Pushes the buffer downstream, sends any pending events and + * does some timestamp and segment handling. + * + * This must be called with srcpad STREAM_LOCK held. + * + * Returns: #GstFlowReturn + */ +GstFlowReturn +gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstClockTime last_stop = GST_CLOCK_TIME_NONE; + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) last_stop = GST_BUFFER_TIMESTAMP (buffer); if (last_stop != GST_CLOCK_TIME_NONE && GST_BUFFER_DURATION_IS_VALID (buffer)) @@ -792,39 +831,30 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, /* TODO: Add to seek table */ - if (ret == GST_FLOW_OK) { - if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && - GST_CLOCK_TIME_IS_VALID (parse->segment.stop) && - GST_BUFFER_TIMESTAMP (buffer) > parse->segment.stop) { - GST_LOG_OBJECT (parse, "Dropped frame, after segment"); - gst_buffer_unref (buffer); - } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && - GST_BUFFER_DURATION_IS_VALID (buffer) && - GST_CLOCK_TIME_IS_VALID (parse->segment.start) && - GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) - < parse->segment.start) { - /* FIXME: subclass needs way to override the start as downstream might - * need frames before for proper decoding */ - GST_LOG_OBJECT (parse, "Dropped frame, before segment"); - gst_buffer_unref (buffer); - } else { - ret = gst_pad_push (parse->srcpad, buffer); - GST_LOG_OBJECT (parse, "frame (%d bytes) pushed: %d", - GST_BUFFER_SIZE (buffer), ret); - } - } else { + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && + GST_CLOCK_TIME_IS_VALID (parse->segment.stop) && + GST_BUFFER_TIMESTAMP (buffer) > parse->segment.stop) { + GST_LOG_OBJECT (parse, "Dropped frame, after segment"); gst_buffer_unref (buffer); + } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && + GST_BUFFER_DURATION_IS_VALID (buffer) && + GST_CLOCK_TIME_IS_VALID (parse->segment.start) && + GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) + < parse->segment.start) { + /* FIXME: subclass needs way to override the start as downstream might + * need frames before for proper decoding */ + GST_LOG_OBJECT (parse, "Dropped frame, before segment"); + gst_buffer_unref (buffer); + } else { + ret = gst_pad_push (parse->srcpad, buffer); + GST_LOG_OBJECT (parse, "frame (%d bytes) pushed: %d", + GST_BUFFER_SIZE (buffer), ret); } /* Update current running segment position */ if (ret == GST_FLOW_OK && last_stop != GST_CLOCK_TIME_NONE) gst_segment_set_last_stop (&parse->segment, GST_FORMAT_TIME, last_stop); - /* convert internal flow to OK and mark discont for the next buffer. */ - if (ret == GST_BASE_PARSE_FLOW_DROPPED) { - parse->priv->discont = TRUE; - ret = GST_FLOW_OK; - } return ret; } @@ -1575,12 +1605,13 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event) * it directly or fail. For TIME, try upstream, but do it ourselves if * it fails upstream */ if (format != GST_FORMAT_TIME) { - gst_event_ref (event); return gst_pad_push_event (parse->sinkpad, event); } else { gst_event_ref (event); - if (gst_pad_push_event (parse->sinkpad, event)) + if (gst_pad_push_event (parse->sinkpad, event)) { + gst_event_unref (event); return TRUE; + } } /* get flush flag */ diff --git a/gst/aacparse/gstbaseparse.h b/gst/aacparse/gstbaseparse.h index a2856cc7..9d53f07b 100644 --- a/gst/aacparse/gstbaseparse.h +++ b/gst/aacparse/gstbaseparse.h @@ -225,6 +225,9 @@ struct _GstBaseParseClass { GType gst_base_parse_get_type (void); +GstFlowReturn gst_base_parse_push_buffer (GstBaseParse *parse, + GstBuffer *buffer); + void gst_base_parse_set_duration (GstBaseParse *parse, GstFormat fmt, gint64 duration); diff --git a/gst/amrparse/gstbaseparse.c b/gst/amrparse/gstbaseparse.c index ad963785..870492a8 100644 --- a/gst/amrparse/gstbaseparse.c +++ b/gst/amrparse/gstbaseparse.c @@ -735,7 +735,6 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, GstBaseParseClass * klass, GstBuffer * buffer) { GstFlowReturn ret; - GstClockTime last_stop = GST_CLOCK_TIME_NONE; if (parse->priv->discont) { GST_DEBUG_OBJECT (parse, "marking DISCONT"); @@ -749,6 +748,46 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, * keep track of timestamp and calculate everything possible * if not set already */ + /* First buffers are dropped, this means that the subclass needs more + * frames to decide on the format and queues them internally */ + if (ret == GST_BASE_PARSE_FLOW_DROPPED && !GST_PAD_CAPS (parse->srcpad)) { + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } + + /* convert internal flow to OK and mark discont for the next buffer. */ + if (ret == GST_BASE_PARSE_FLOW_DROPPED) { + parse->priv->discont = TRUE; + ret = GST_FLOW_OK; + + gst_buffer_unref (buffer); + + return ret; + } else if (ret != GST_FLOW_OK) { + return ret; + } + + return gst_base_parse_push_buffer (parse, buffer); +} + +/** + * gst_base_parse_push_buffer: + * @parse: #GstBaseParse. + * @buffer: #GstBuffer. + * + * Pushes the buffer downstream, sends any pending events and + * does some timestamp and segment handling. + * + * This must be called with srcpad STREAM_LOCK held. + * + * Returns: #GstFlowReturn + */ +GstFlowReturn +gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstClockTime last_stop = GST_CLOCK_TIME_NONE; + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) last_stop = GST_BUFFER_TIMESTAMP (buffer); if (last_stop != GST_CLOCK_TIME_NONE && GST_BUFFER_DURATION_IS_VALID (buffer)) @@ -792,39 +831,30 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, /* TODO: Add to seek table */ - if (ret == GST_FLOW_OK) { - if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && - GST_CLOCK_TIME_IS_VALID (parse->segment.stop) && - GST_BUFFER_TIMESTAMP (buffer) > parse->segment.stop) { - GST_LOG_OBJECT (parse, "Dropped frame, after segment"); - gst_buffer_unref (buffer); - } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && - GST_BUFFER_DURATION_IS_VALID (buffer) && - GST_CLOCK_TIME_IS_VALID (parse->segment.start) && - GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) - < parse->segment.start) { - /* FIXME: subclass needs way to override the start as downstream might - * need frames before for proper decoding */ - GST_LOG_OBJECT (parse, "Dropped frame, before segment"); - gst_buffer_unref (buffer); - } else { - ret = gst_pad_push (parse->srcpad, buffer); - GST_LOG_OBJECT (parse, "frame (%d bytes) pushed: %d", - GST_BUFFER_SIZE (buffer), ret); - } - } else { + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && + GST_CLOCK_TIME_IS_VALID (parse->segment.stop) && + GST_BUFFER_TIMESTAMP (buffer) > parse->segment.stop) { + GST_LOG_OBJECT (parse, "Dropped frame, after segment"); gst_buffer_unref (buffer); + } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && + GST_BUFFER_DURATION_IS_VALID (buffer) && + GST_CLOCK_TIME_IS_VALID (parse->segment.start) && + GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) + < parse->segment.start) { + /* FIXME: subclass needs way to override the start as downstream might + * need frames before for proper decoding */ + GST_LOG_OBJECT (parse, "Dropped frame, before segment"); + gst_buffer_unref (buffer); + } else { + ret = gst_pad_push (parse->srcpad, buffer); + GST_LOG_OBJECT (parse, "frame (%d bytes) pushed: %d", + GST_BUFFER_SIZE (buffer), ret); } /* Update current running segment position */ if (ret == GST_FLOW_OK && last_stop != GST_CLOCK_TIME_NONE) gst_segment_set_last_stop (&parse->segment, GST_FORMAT_TIME, last_stop); - /* convert internal flow to OK and mark discont for the next buffer. */ - if (ret == GST_BASE_PARSE_FLOW_DROPPED) { - parse->priv->discont = TRUE; - ret = GST_FLOW_OK; - } return ret; } @@ -1575,12 +1605,13 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event) * it directly or fail. For TIME, try upstream, but do it ourselves if * it fails upstream */ if (format != GST_FORMAT_TIME) { - gst_event_ref (event); return gst_pad_push_event (parse->sinkpad, event); } else { gst_event_ref (event); - if (gst_pad_push_event (parse->sinkpad, event)) + if (gst_pad_push_event (parse->sinkpad, event)) { + gst_event_unref (event); return TRUE; + } } /* get flush flag */ diff --git a/gst/amrparse/gstbaseparse.h b/gst/amrparse/gstbaseparse.h index a2856cc7..9d53f07b 100644 --- a/gst/amrparse/gstbaseparse.h +++ b/gst/amrparse/gstbaseparse.h @@ -225,6 +225,9 @@ struct _GstBaseParseClass { GType gst_base_parse_get_type (void); +GstFlowReturn gst_base_parse_push_buffer (GstBaseParse *parse, + GstBuffer *buffer); + void gst_base_parse_set_duration (GstBaseParse *parse, GstFormat fmt, gint64 duration); diff --git a/gst/camerabin/TODO b/gst/camerabin/TODO new file mode 100644 index 00000000..423c0628 --- /dev/null +++ b/gst/camerabin/TODO @@ -0,0 +1,31 @@ += Cleanups = +* often two g_object_set for same object one after the other +* use GST_*_OBJECT () more often +* there are two gst_element_set_state() one after each other + += Renaming = +* internal use of img->image, vid->video + += Refactorisation = +* gstcamerabin:gst_camerabin_rewrite_tags + - sounds fishy, should use normal tagsetter method + - gst_camerabin_rewrite_tags_to_bin(9 why don't we just send a tag-event? + +* file-name property + - supplying an already opened filedeskriptor would be more safe + - need to check what filesink does if the file exists and cannot be overwritten + +* imagbin + - we want async operation here (especialy for burst mode capture) + - right now, its a bit fragile as we muck with locked_state + - main problem is that the location for filesink can only be set in NULL/READY + and we need to do that sync'ed with the dataflow. we can't use multifilesink + as it does a file per pad_push + - one problem of the current approach is that we can't have an image in e.g, + postprocessing while anotherone is beeing saved + - we could use a pool of imagebins: + - configure one (set filename) + - push_buffer + - on eos, put it back to the pool + - for this we need to check that we can have multiple instances of e.g. + dsp jpeg encoders diff --git a/gst/camerabin/camerabinimage.c b/gst/camerabin/camerabinimage.c index 8eea8d91..25730ccd 100644 --- a/gst/camerabin/camerabinimage.c +++ b/gst/camerabin/camerabinimage.c @@ -463,15 +463,13 @@ gst_camerabin_image_create_elements (GstCameraBinImage * img) g_object_set (G_OBJECT (img->meta_mux), "exif-byte-order", 1, NULL); } - /* Create file sink element */ + /* Add sink element for storing the image */ if (!(img->sink = gst_camerabin_create_and_add_element (imgbin, DEFAULT_SINK))) { goto done; } - - /* Set properties */ - g_object_set (G_OBJECT (img->sink), "location", img->filename->str, NULL); - g_object_set (G_OBJECT (img->sink), "async", FALSE, NULL); + g_object_set (G_OBJECT (img->sink), "location", img->filename->str, "async", FALSE, "buffer-mode", 2, /* non buffered io */ + NULL); ret = TRUE; diff --git a/gst/camerabin/camerabinpreview.c b/gst/camerabin/camerabinpreview.c index 9b12bbac..b8e53389 100644 --- a/gst/camerabin/camerabinpreview.c +++ b/gst/camerabin/camerabinpreview.c @@ -95,6 +95,8 @@ gst_camerabin_preview_create_pipeline (GstCameraBin * camera) gst_bin_add_many (GST_BIN (camera->preview_pipeline), src, csp, filter, vscale, sink, NULL); + GST_DEBUG ("preview format is: %" GST_PTR_FORMAT, camera->preview_caps); + g_object_set (filter, "caps", camera->preview_caps, NULL); g_object_set (sink, "preroll-queue-len", 1, "signal-handoffs", TRUE, NULL); g_object_set (vscale, "method", 0, NULL); @@ -195,7 +197,8 @@ gst_camerabin_preview_convert (GstCameraBin * camera, GstBuffer * buf) bflags = GST_BUFFER_FLAGS (buf); GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY); - GST_DEBUG ("running conversion pipeline"); + GST_DEBUG ("running conversion pipeline, source is: %" GST_PTR_FORMAT, + GST_BUFFER_CAPS (buf)); gst_element_set_state (camera->preview_pipeline, GST_STATE_PLAYING); g_signal_emit_by_name (src, "push-buffer", buf, &fret); diff --git a/gst/camerabin/camerabinvideo.c b/gst/camerabin/camerabinvideo.c index 4bbc5057..bc915243 100644 --- a/gst/camerabin/camerabinvideo.c +++ b/gst/camerabin/camerabinvideo.c @@ -553,7 +553,6 @@ gst_camerabin_video_create_elements (GstCameraBinVideo * vid) gst_ghost_pad_set_target (GST_GHOST_PAD (vid->sinkpad), vid_sinkpad); gst_object_unref (vid_sinkpad); - /* Add queue element for video */ vid->tee_video_srcpad = gst_element_get_request_pad (vid->tee, "src%d"); if (!(vid->video_queue = @@ -565,7 +564,6 @@ gst_camerabin_video_create_elements (GstCameraBinVideo * vid) gst_pad_add_buffer_probe (vid->tee_video_srcpad, G_CALLBACK (camerabin_video_pad_tee_src0_have_buffer), vid); - #ifdef USE_TIMEOVERLAY /* Add timeoverlay element to visualize elapsed time for debugging */ if (!(gst_camerabin_create_and_add_element (vidbin, "timeoverlay"))) { @@ -600,8 +598,8 @@ gst_camerabin_video_create_elements (GstCameraBinVideo * vid) gst_camerabin_create_and_add_element (vidbin, DEFAULT_SINK))) { goto error; } - g_object_set (G_OBJECT (vid->sink), "location", vid->filename->str, NULL); - + g_object_set (G_OBJECT (vid->sink), "location", vid->filename->str, "buffer-mode", 2, /* non buffered io */ + NULL); /* Add user set or default audio source element */ if (vid->user_aud_src) { @@ -615,10 +613,9 @@ gst_camerabin_video_create_elements (GstCameraBinVideo * vid) } /* Add queue element for audio */ - if (!(queue = gst_camerabin_create_and_add_element (vidbin, "queue"))) { + if (!(gst_camerabin_create_and_add_element (vidbin, "queue"))) { goto error; } - queue = NULL; /* Add optional audio conversion and volume elements and raise no errors if adding them fails */ diff --git a/gst/camerabin/gstcamerabin.c b/gst/camerabin/gstcamerabin.c index 9d8a14cc..22a33477 100644 --- a/gst/camerabin/gstcamerabin.c +++ b/gst/camerabin/gstcamerabin.c @@ -954,7 +954,7 @@ gst_camerabin_change_mode (GstCameraBin * camera, gint mode) camera->mode = mode; if (camera->active_bin) { GST_DEBUG_OBJECT (camera, "stopping active bin"); - gst_element_set_state (camera->active_bin, GST_STATE_NULL); + gst_element_set_state (camera->active_bin, GST_STATE_READY); } if (camera->mode == MODE_IMAGE) { GstStateChangeReturn state_ret; @@ -1031,6 +1031,10 @@ gst_camerabin_set_element_zoom (GstCameraBin * camera, gint zoom) if (zoom != ZOOM_1X) { w2_crop = (camera->width - (camera->width * ZOOM_1X / zoom)) / 2; h2_crop = (camera->height - (camera->height * ZOOM_1X / zoom)) / 2; + + /* force number of pixels cropped from left to be even, to avoid slow code + * path on videoscale */ + w2_crop &= 0xFFFE; } pad_zoom_sink = gst_element_get_static_pad (camera->src_zoom_crop, "sink"); @@ -2862,12 +2866,8 @@ gst_camerabin_set_property (GObject * object, guint prop_id, break; case ARG_FILTER_CAPS: GST_OBJECT_LOCK (camera); - if (camera->view_finder_caps) { - gst_caps_unref (camera->view_finder_caps); - } - /* just ref, we don't modify it inplace */ - camera->view_finder_caps = - gst_caps_ref ((GstCaps *) gst_value_get_caps (value)); + gst_caps_replace (&camera->view_finder_caps, + (GstCaps *) gst_value_get_caps (value)); GST_OBJECT_UNLOCK (camera); if (GST_STATE (camera) != GST_STATE_NULL) { gst_camerabin_set_capsfilter_caps (camera, camera->view_finder_caps); @@ -2875,10 +2875,8 @@ gst_camerabin_set_property (GObject * object, guint prop_id, break; case ARG_PREVIEW_CAPS: GST_OBJECT_LOCK (camera); - if (camera->preview_caps) { - gst_caps_unref (camera->preview_caps); - } - camera->preview_caps = gst_caps_copy (gst_value_get_caps (value)); + gst_caps_replace (&camera->preview_caps, + (GstCaps *) gst_value_get_caps (value)); GST_OBJECT_UNLOCK (camera); gst_camerabin_preview_create_pipeline (camera); break; diff --git a/gst/debugutils/fpsdisplaysink.c b/gst/debugutils/fpsdisplaysink.c index 54f5cc54..ff3e0dfd 100644 --- a/gst/debugutils/fpsdisplaysink.c +++ b/gst/debugutils/fpsdisplaysink.c @@ -206,7 +206,10 @@ display_current_fps (gpointer data) GstFPSDisplaySink *self = GST_FPS_DISPLAY_SINK (data); gint64 current_ts; - gst_element_query (self->video_sink, self->query); + /* if query failed try again on next timer tick */ + if (!gst_element_query (self->video_sink, self->query)) + return TRUE; + gst_query_parse_position (self->query, NULL, ¤t_ts); if (GST_CLOCK_TIME_IS_VALID (self->last_ts)) { diff --git a/gst/mpegdemux/gstmpegdemux.c b/gst/mpegdemux/gstmpegdemux.c index ce1d0978..75d5960f 100644 --- a/gst/mpegdemux/gstmpegdemux.c +++ b/gst/mpegdemux/gstmpegdemux.c @@ -845,6 +845,7 @@ gst_flups_demux_close_segment (GstFluPSDemux * demux) { gint id; GstEvent *event = NULL; + guint64 base_time; #if POST_10_10 GST_INFO_OBJECT (demux, "closing running segment %" GST_SEGMENT_FORMAT, @@ -855,14 +856,17 @@ gst_flups_demux_close_segment (GstFluPSDemux * demux) * last_seg_start != clock_time_none, as that indicates a sparse-stream * event was sent there */ + if ((base_time = demux->base_time) == (guint64) - 1) + base_time = 0; + + /* Close the current segment for a linear playback */ if (demux->src_segment.rate >= 0) { /* for forward playback, we played from start to last_stop */ event = gst_event_new_new_segment (TRUE, demux->src_segment.rate, demux->src_segment.format, - demux->src_segment.start + demux->base_time, - demux->src_segment.last_stop + demux->base_time, - demux->src_segment.time); + demux->src_segment.start + base_time, + demux->src_segment.last_stop + base_time, demux->src_segment.time); } else { gint64 stop; @@ -872,8 +876,8 @@ gst_flups_demux_close_segment (GstFluPSDemux * demux) /* for reverse playback, we played from stop to last_stop. */ event = gst_event_new_new_segment (TRUE, demux->src_segment.rate, demux->src_segment.format, - demux->src_segment.last_stop + demux->base_time, - stop + demux->base_time, demux->src_segment.last_stop); + demux->src_segment.last_stop + base_time, + stop + base_time, demux->src_segment.last_stop); } if (event) { @@ -1383,11 +1387,66 @@ gst_flups_demux_src_query (GstPad * pad, GstQuery * query) res = TRUE; break; } + case GST_QUERY_SEEKING:{ + GstFormat fmt; + + gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); + + res = TRUE; + if (demux->random_access) { + /* In pull mode we can seek in TIME format if we have the SCR */ + if (fmt != GST_FORMAT_TIME || demux->scr_rate_n == G_MAXUINT64 + || demux->scr_rate_d == G_MAXUINT64) + gst_query_set_seeking (query, fmt, FALSE, -1, -1); + else + gst_query_set_seeking (query, fmt, TRUE, 0, -1); + } else { + if (fmt == GST_FORMAT_BYTES) { + /* Seeking in BYTES format not supported at all */ + gst_query_set_seeking (query, fmt, FALSE, -1, -1); + } else { + GstQuery *peerquery; + gboolean seekable; + + /* Then ask upstream */ + res = gst_pad_peer_query (demux->sinkpad, query); + if (res) { + /* If upstream can handle seeks we're done, if it + * can't we still have our TIME->BYTES conversion seek + */ + gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL); + if (seekable || fmt != GST_FORMAT_TIME) + goto beach; + } + + /* We can seek if upstream supports BYTES seeks and we + * have the SCR + */ + peerquery = gst_query_new_seeking (GST_FORMAT_BYTES); + res = gst_pad_peer_query (demux->sinkpad, query); + if (!res || demux->scr_rate_n == G_MAXUINT64 + || demux->scr_rate_d == G_MAXUINT64) { + gst_query_set_seeking (query, fmt, FALSE, -1, -1); + } else { + gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL); + if (seekable) + gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0, -1); + else + gst_query_set_seeking (query, fmt, FALSE, -1, -1); + } + + gst_query_unref (peerquery); + res = TRUE; + } + } + break; + } default: res = gst_pad_query_default (pad, query); break; } +beach: gst_object_unref (demux); return res; @@ -2540,7 +2599,7 @@ gst_flups_demux_loop (GstPad * pad) { GstFluPSDemux *demux; GstFlowReturn ret = GST_FLOW_OK; - guint offset = 0; + guint64 offset = 0; demux = GST_FLUPS_DEMUX (gst_pad_get_parent (pad)); @@ -2579,7 +2638,7 @@ gst_flups_demux_loop (GstPad * pad) goto pause; } } else { /* Reverse playback */ - guint size = MIN (offset, BLOCK_SZ); + guint64 size = MIN (offset, BLOCK_SZ); /* pull in data */ ret = gst_flups_demux_pull_block (pad, demux, offset - size, size); diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index cb082a2b..8de7cc75 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -1697,7 +1697,8 @@ gst_mpegts_demux_parse_adaptation_field (GstMpegTSStream * stream, memset (pmts_checked, 0, sizeof (gboolean) * (MPEGTS_MAX_PID + 1)); for (j = 0; j < MPEGTS_MAX_PID + 1; j++) { - if (demux->streams[j] && demux->streams[j]->PMT_pid) { + if (demux->streams[j] + && demux->streams[j]->PMT_pid <= MPEGTS_MAX_PID) { if (!pmts_checked[demux->streams[j]->PMT_pid]) { /* check if this is correct pcr for pmt */ if (demux->streams[demux->streams[j]->PMT_pid] && @@ -2777,9 +2778,54 @@ gst_mpegts_demux_src_pad_query (GstPad * pad, GstQuery * query) } break; } + case GST_QUERY_SEEKING:{ + GstFormat fmt; + + gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); + if (fmt == GST_FORMAT_BYTES) { + /* Seeking in BYTES format not supported at all */ + gst_query_set_seeking (query, fmt, FALSE, -1, -1); + } else { + GstQuery *peerquery; + gboolean seekable; + + /* Then ask upstream */ + res = gst_pad_peer_query (demux->sinkpad, query); + if (res) { + /* If upstream can handle seeks we're done, if it + * can't we still have our TIME->BYTES conversion seek + */ + gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL); + if (seekable || fmt != GST_FORMAT_TIME) + goto beach; + } + + /* We can seek if upstream supports BYTES seeks and we + * have a bitrate + */ + peerquery = gst_query_new_seeking (GST_FORMAT_BYTES); + res = gst_pad_peer_query (demux->sinkpad, query); + if (!res || demux->bitrate == -1) { + gst_query_set_seeking (query, fmt, FALSE, -1, -1); + } else { + gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL); + if (seekable) + gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0, -1); + else + gst_query_set_seeking (query, fmt, FALSE, -1, -1); + } + + gst_query_unref (peerquery); + res = TRUE; + } + break; + } default: res = gst_pad_query_default (pad, query); + break; } + +beach: gst_object_unref (demux); return res; diff --git a/gst/mpegdemux/gstpesfilter.c b/gst/mpegdemux/gstpesfilter.c index b520c766..736d4960 100644 --- a/gst/mpegdemux/gstpesfilter.c +++ b/gst/mpegdemux/gstpesfilter.c @@ -151,6 +151,7 @@ gst_pes_filter_parse (GstPESFilter * filter) * to set the allow_unbounded flag if they want */ if (filter->length == 0 && ((filter->start_code & 0xFFFFFFF0) == PACKET_VIDEO_START_CODE || + filter->start_code == ID_EXTENDED_STREAM_ID || filter->allow_unbounded)) { GST_DEBUG ("id 0x%02x, unbounded length", filter->id); filter->unbounded_packet = TRUE; @@ -389,9 +390,53 @@ gst_pes_filter_parse (GstPESFilter * filter) } /* PES_extension_flag */ if ((flags & 0x01)) { - GST_DEBUG ("%x PES_extension", filter->id); + flags = *data++; + header_data_length -= 1; + datalen -= 1; + GST_DEBUG ("%x PES_extension, flags 0x%02x", filter->id, flags); + /* PES_private_data_flag */ + if ((flags & 0x80)) { + GST_DEBUG ("%x PES_private_data_flag", filter->id); + data += 16; + header_data_length -= 16; + datalen -= 16; + } + /* pack_header_field_flag */ + if ((flags & 0x40)) { + guint8 pack_field_length = *data; + GST_DEBUG ("%x pack_header_field_flag, pack_field_length %d", + filter->id, pack_field_length); + data += pack_field_length + 1; + header_data_length -= pack_field_length + 1; + datalen -= pack_field_length + 1; + } + /* program_packet_sequence_counter_flag */ + if ((flags & 0x20)) { + GST_DEBUG ("%x program_packet_sequence_counter_flag", filter->id); + data += 2; + header_data_length -= 2; + datalen -= 2; + } + /* P-STD_buffer_flag */ + if ((flags & 0x10)) { + GST_DEBUG ("%x P-STD_buffer_flag", filter->id); + data += 2; + header_data_length -= 2; + datalen -= 2; + } + /* PES_extension_flag_2 */ + if ((flags & 0x01)) { + guint8 PES_extension_field_length = *data++; + GST_DEBUG ("%x PES_extension_flag_2, len %d", + filter->id, PES_extension_field_length & 0x7f); + if (PES_extension_field_length == 0x81) { + GST_DEBUG ("%x substream id 0x%02x", filter->id, *data); + } + data += PES_extension_field_length & 0x7f; + header_data_length -= (PES_extension_field_length & 0x7f) + 1; + datalen -= (PES_extension_field_length & 0x7f) + 1; + } } - /* calculate the amount of real data in this PES packet */ data += header_data_length; datalen -= header_data_length; diff --git a/gst/mpegdemux/mpegtspacketizer.c b/gst/mpegdemux/mpegtspacketizer.c index 5ed71f0c..da53a926 100644 --- a/gst/mpegdemux/mpegtspacketizer.c +++ b/gst/mpegdemux/mpegtspacketizer.c @@ -1749,7 +1749,9 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer * packetizer, break; } component = gst_structure_new ("video", "high-definition", - G_TYPE_BOOLEAN, TRUE, "frequency", G_TYPE_INT, freq, NULL); + G_TYPE_BOOLEAN, TRUE, "frequency", G_TYPE_INT, freq, + "tag", G_TYPE_INT, DESC_DVB_COMPONENT_tag (comp_descriptor), + NULL); if (widescreen == 0) { gst_structure_set (component, "aspect-ratio", G_TYPE_STRING, "4:3", NULL); @@ -1787,7 +1789,8 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer * packetizer, break; } component = gst_structure_new ("audio", "type", G_TYPE_STRING, - comptype, NULL); + comptype, "tag", G_TYPE_INT, + DESC_DVB_COMPONENT_tag (comp_descriptor), NULL); break; case 0x03: /* subtitles/teletext/vbi */ comptype = "reserved"; @@ -1827,7 +1830,8 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer * packetizer, break; } component = gst_structure_new ("teletext", "type", G_TYPE_STRING, - comptype, NULL); + comptype, "tag", G_TYPE_INT, + DESC_DVB_COMPONENT_tag (comp_descriptor), NULL); break; } if (component) { diff --git a/gst/mpegdemux/mpegtsparse.c b/gst/mpegdemux/mpegtsparse.c index 976935f2..90a8ea3b 100644 --- a/gst/mpegdemux/mpegtsparse.c +++ b/gst/mpegdemux/mpegtsparse.c @@ -553,6 +553,35 @@ mpegts_parse_program_remove_stream (MpegTSParse * parse, g_hash_table_remove (program->streams, GINT_TO_POINTER ((gint) pid)); } +static void +mpegts_parse_deactivate_pmt (MpegTSParse * parse, MpegTSParseProgram * program) +{ + gint i; + guint pid; + guint stream_type; + GstStructure *stream; + const GValue *streams; + const GValue *value; + + if (program->pmt_info) { + streams = gst_structure_get_value (program->pmt_info, "streams"); + + for (i = 0; i < gst_value_list_get_size (streams); ++i) { + value = gst_value_list_get_value (streams, i); + stream = g_value_get_boxed (value); + gst_structure_get_uint (stream, "pid", &pid); + gst_structure_get_uint (stream, "stream-type", &stream_type); + mpegts_parse_program_remove_stream (parse, program, (guint16) pid); + g_hash_table_remove (parse->pes_pids, GINT_TO_POINTER ((gint) pid)); + } + + /* remove pcr stream */ + mpegts_parse_program_remove_stream (parse, program, program->pcr_pid); + g_hash_table_remove (parse->pes_pids, + GINT_TO_POINTER ((gint) program->pcr_pid)); + } +} + static MpegTSParsePad * mpegts_parse_create_tspad (MpegTSParse * parse, const gchar * pad_name) { @@ -940,6 +969,7 @@ mpegts_parse_apply_pat (MpegTSParse * parse, GstStructure * pat_info) parse->pads_to_remove = g_list_append (parse->pads_to_remove, mpegts_parse_deactivate_program (parse, program)); + mpegts_parse_deactivate_pmt (parse, program); mpegts_parse_remove_program (parse, program_number); g_hash_table_remove (parse->psi_pids, GINT_TO_POINTER ((gint) pid)); mpegts_packetizer_remove_stream (parse->packetizer, pid); @@ -964,7 +994,6 @@ mpegts_parse_apply_pmt (MpegTSParse * parse, guint stream_type; GstStructure *stream; gint i; - const GValue *old_streams; const GValue *new_streams; const GValue *value; @@ -975,27 +1004,11 @@ mpegts_parse_apply_pmt (MpegTSParse * parse, GST_OBJECT_LOCK (parse); program = mpegts_parse_get_program (parse, program_number); if (program) { - if (program->pmt_info) { - /* deactivate old pmt */ - old_streams = gst_structure_get_value (program->pmt_info, "streams"); - - for (i = 0; i < gst_value_list_get_size (old_streams); ++i) { - value = gst_value_list_get_value (old_streams, i); - stream = g_value_get_boxed (value); - gst_structure_get_uint (stream, "pid", &pid); - gst_structure_get_uint (stream, "stream-type", &stream_type); - mpegts_parse_program_remove_stream (parse, program, (guint16) pid); - g_hash_table_remove (parse->pes_pids, GINT_TO_POINTER ((gint) pid)); - } - - /* remove pcr stream */ - mpegts_parse_program_remove_stream (parse, program, program->pcr_pid); - g_hash_table_remove (parse->pes_pids, - GINT_TO_POINTER ((gint) program->pcr_pid)); - + /* deactivate old pmt */ + mpegts_parse_deactivate_pmt (parse, program); + if (program->pmt_info) gst_structure_free (program->pmt_info); - program->pmt_info = NULL; - } + program->pmt_info = NULL; } else { /* no PAT?? */ g_hash_table_insert (parse->psi_pids, diff --git a/gst/mxf/mxfdemux.c b/gst/mxf/mxfdemux.c index 5abd37ff..e646be8c 100644 --- a/gst/mxf/mxfdemux.c +++ b/gst/mxf/mxfdemux.c @@ -3453,6 +3453,7 @@ gst_mxf_demux_src_query_type (GstPad * pad) static const GstQueryType types[] = { GST_QUERY_POSITION, GST_QUERY_DURATION, + GST_QUERY_SEEKING, 0 }; @@ -3545,6 +3546,33 @@ gst_mxf_demux_src_query (GstPad * pad, GstQuery * query) ret = TRUE; break; } + case GST_QUERY_SEEKING:{ + GstFormat fmt; + + ret = TRUE; + gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); + if (fmt != GST_FORMAT_TIME) { + gst_query_set_seeking (query, fmt, FALSE, -1, -1); + goto done; + } + + if (demux->random_access) { + gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0, -1); + } else { + GstQuery *peerquery = gst_query_new_seeking (GST_FORMAT_BYTES); + gboolean seekable; + + seekable = gst_pad_peer_query (demux->sinkpad, peerquery); + if (seekable) + gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL); + if (seekable) + gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0, -1); + else + gst_query_set_seeking (query, GST_FORMAT_TIME, FALSE, -1, -1); + } + + break; + } default: /* else forward upstream */ ret = gst_pad_peer_query (demux->sinkpad, query); @@ -3806,6 +3834,33 @@ gst_mxf_demux_query (GstElement * element, GstQuery * query) ret = TRUE; break; } + case GST_QUERY_SEEKING:{ + GstFormat fmt; + + ret = TRUE; + gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); + if (fmt != GST_FORMAT_TIME) { + gst_query_set_seeking (query, fmt, FALSE, -1, -1); + goto done; + } + + if (demux->random_access) { + gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0, -1); + } else { + GstQuery *peerquery = gst_query_new_seeking (GST_FORMAT_BYTES); + gboolean seekable; + + seekable = gst_pad_peer_query (demux->sinkpad, peerquery); + if (seekable) + gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL); + if (seekable) + gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0, -1); + else + gst_query_set_seeking (query, GST_FORMAT_TIME, FALSE, -1, -1); + } + + break; + } default: /* else forward upstream */ ret = gst_pad_peer_query (demux->sinkpad, query); diff --git a/gst/pcapparse/gstpcapparse.h b/gst/pcapparse/gstpcapparse.h index 8e45f8b2..cc1b55f6 100644 --- a/gst/pcapparse/gstpcapparse.h +++ b/gst/pcapparse/gstpcapparse.h @@ -45,10 +45,17 @@ typedef enum PCAP_PARSE_STATE_PARSING, } GstPcapParseState; +/** + * GstPcapParse: + * + * GstPcapParse element. + */ + struct _GstPcapParse { GstElement element; + /*< private >*/ GstPad * sink_pad; GstPad * src_pad; diff --git a/gst/real/gstrealaudiodec.c b/gst/real/gstrealaudiodec.c index 1a94a77b..5f5b900d 100644 --- a/gst/real/gstrealaudiodec.c +++ b/gst/real/gstrealaudiodec.c @@ -262,12 +262,20 @@ open_library (GstRealAudioDec * dec, gint version, GstRADecLibrary * lib) GST_LOG_OBJECT (dec, "opening module %s", codec); - lib->module = g_module_open (codec, G_MODULE_BIND_LAZY); + /* This is racy, but it doesn't matter here; would be nice if GModule + * gave us a GError instead of an error string, but it doesn't, so.. */ + if (g_file_test (codec, G_FILE_TEST_EXISTS)) { + lib->module = g_module_open (codec, G_MODULE_BIND_LAZY); + if (lib->module == NULL) { + GST_ERROR_OBJECT (dec, "Could not open codec library '%s': %s", + codec, g_module_error ()); + } + } else { + GST_DEBUG_OBJECT (dec, "%s does not exist", codec); + } g_free (codec); if (lib->module) goto codec_search_done; - - GST_LOG_OBJECT (dec, "failure, try next one..."); } } diff --git a/gst/real/gstrealvideodec.c b/gst/real/gstrealvideodec.c index 74cb6f5a..313a99f2 100644 --- a/gst/real/gstrealvideodec.c +++ b/gst/real/gstrealvideodec.c @@ -480,7 +480,17 @@ open_library (GstRealVideoDec * dec, GstRealVideoDecVersion version, gchar *codec = g_strconcat (split_path[i], "/", split_names[j], NULL); GST_DEBUG_OBJECT (dec, "trying %s", codec); - module = g_module_open (codec, G_MODULE_BIND_LAZY); + /* This is racy, but it doesn't matter here; would be nice if GModule + * gave us a GError instead of an error string, but it doesn't, so.. */ + if (g_file_test (codec, G_FILE_TEST_EXISTS)) { + module = g_module_open (codec, G_MODULE_BIND_LAZY); + if (module == NULL) { + GST_ERROR_OBJECT (dec, "Could not open codec library '%s': %s", + codec, g_module_error ()); + } + } else { + GST_LOG_OBJECT (dec, "%s does not exist", codec); + } g_free (codec); if (module) goto codec_search_done; @@ -492,7 +502,7 @@ codec_search_done: g_strfreev (split_names); if (module == NULL) - goto could_not_open; + return FALSE; GST_DEBUG_OBJECT (dec, "module opened, finding symbols"); @@ -527,12 +537,6 @@ unknown_version: GST_ERROR_OBJECT (dec, "Cannot handle version %i.", version); return FALSE; } -could_not_open: - { - GST_ERROR_OBJECT (dec, "Could not open library '%s' in '%s': %s", names, - path, g_module_error ()); - return FALSE; - } could_not_load: { close_library (dec, lib); |