static VALUE segment_done_initialize(VALUE self, VALUE src, VALUE format, VALUE position) { G_INITIALIZE(self, gst_message_new_segment_done(RVAL2GST_OBJ(src), RVAL2GST_FORMAT(format), NUM2LL(position))); return Qnil; }
static void gst_nuv_demux_send_eos (GstNuvDemux * nuv) { gst_element_post_message (GST_ELEMENT (nuv), gst_message_new_segment_done (GST_OBJECT (nuv), GST_FORMAT_TIME, -1)); if (nuv->src_video_pad) gst_pad_push_event (nuv->src_video_pad, gst_event_new_eos ()); if (nuv->src_audio_pad) gst_pad_push_event (nuv->src_audio_pad, gst_event_new_eos ()); }
static void gst_aiff_parse_loop (GstPad * pad) { GstFlowReturn ret; GstAiffParse *aiff = GST_AIFF_PARSE (GST_PAD_PARENT (pad)); GST_LOG_OBJECT (aiff, "process data"); switch (aiff->state) { case AIFF_PARSE_START: GST_INFO_OBJECT (aiff, "AIFF_PARSE_START"); if ((ret = gst_aiff_parse_stream_init (aiff)) != GST_FLOW_OK) goto pause; aiff->state = AIFF_PARSE_HEADER; /* fall-through */ case AIFF_PARSE_HEADER: GST_INFO_OBJECT (aiff, "AIFF_PARSE_HEADER"); if ((ret = gst_aiff_parse_stream_headers (aiff)) != GST_FLOW_OK) goto pause; aiff->state = AIFF_PARSE_DATA; GST_INFO_OBJECT (aiff, "AIFF_PARSE_DATA"); /* fall-through */ case AIFF_PARSE_DATA: if ((ret = gst_aiff_parse_stream_data (aiff)) != GST_FLOW_OK) goto pause; break; default: g_assert_not_reached (); } return; /* ERRORS */ pause: { const gchar *reason = gst_flow_get_name (ret); GST_DEBUG_OBJECT (aiff, "pausing task, reason %s", reason); aiff->segment_running = FALSE; gst_pad_pause_task (pad); if (ret == GST_FLOW_UNEXPECTED) { /* perform EOS logic */ if (aiff->segment.flags & GST_SEEK_FLAG_SEGMENT) { GstClockTime stop; if ((stop = aiff->segment.stop) == -1) stop = aiff->segment.duration; gst_element_post_message (GST_ELEMENT_CAST (aiff), gst_message_new_segment_done (GST_OBJECT_CAST (aiff), aiff->segment.format, stop)); } else { gst_pad_push_event (aiff->srcpad, gst_event_new_eos ()); } } else if (ret < GST_FLOW_UNEXPECTED || ret == GST_FLOW_NOT_LINKED) { /* for fatal errors we post an error message, post the error * first so the app knows about the error first. */ GST_ELEMENT_ERROR (aiff, STREAM, FAILED, (_("Internal data flow error.")), ("streaming task paused, reason %s (%d)", reason, ret)); gst_pad_push_event (aiff->srcpad, gst_event_new_eos ()); } return; } }
static void gst_musepackdec_loop (GstPad * sinkpad) { GstMusepackDec *musepackdec; GstFlowReturn flow; GstBuffer *out; GstMapInfo info; mpc_frame_info frame; mpc_status err; gint num_samples, samplerate, bitspersample; musepackdec = GST_MUSEPACK_DEC (GST_PAD_PARENT (sinkpad)); samplerate = g_atomic_int_get (&musepackdec->rate); if (samplerate == 0) { if (!gst_musepack_stream_init (musepackdec)) goto pause_task; gst_musepackdec_send_newsegment (musepackdec); samplerate = g_atomic_int_get (&musepackdec->rate); } bitspersample = g_atomic_int_get (&musepackdec->bps); out = gst_buffer_new_allocate (NULL, MPC_DECODER_BUFFER_LENGTH * 4, NULL); gst_buffer_map (out, &info, GST_MAP_READWRITE); frame.buffer = (MPC_SAMPLE_FORMAT *) info.data; err = mpc_demux_decode (musepackdec->d, &frame); gst_buffer_unmap (out, &info); if (err != MPC_STATUS_OK) { GST_ERROR_OBJECT (musepackdec, "Failed to decode sample"); GST_ELEMENT_ERROR (musepackdec, STREAM, DECODE, (NULL), (NULL)); goto pause_task; } else if (frame.bits == -1) { goto eos_and_pause; } num_samples = frame.samples; gst_buffer_set_size (out, num_samples * bitspersample); GST_BUFFER_OFFSET (out) = musepackdec->segment.position; GST_BUFFER_PTS (out) = gst_util_uint64_scale_int (musepackdec->segment.position, GST_SECOND, samplerate); GST_BUFFER_DURATION (out) = gst_util_uint64_scale_int (num_samples, GST_SECOND, samplerate); musepackdec->segment.position += num_samples; GST_LOG_OBJECT (musepackdec, "Pushing buffer, timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out))); flow = gst_pad_push (musepackdec->srcpad, out); if (flow != GST_FLOW_OK) { GST_DEBUG_OBJECT (musepackdec, "Flow: %s", gst_flow_get_name (flow)); goto pause_task; } /* check if we're at the end of a configured segment */ if (musepackdec->segment.stop != -1 && musepackdec->segment.position >= musepackdec->segment.stop) { gint64 stop_time; GST_DEBUG_OBJECT (musepackdec, "Reached end of configured segment"); if ((musepackdec->segment.flags & GST_SEEK_FLAG_SEGMENT) == 0) goto eos_and_pause; GST_DEBUG_OBJECT (musepackdec, "Posting SEGMENT_DONE message"); stop_time = gst_util_uint64_scale_int (musepackdec->segment.stop, GST_SECOND, samplerate); gst_element_post_message (GST_ELEMENT (musepackdec), gst_message_new_segment_done (GST_OBJECT (musepackdec), GST_FORMAT_TIME, stop_time)); gst_pad_push_event (musepackdec->srcpad, gst_event_new_segment_done (GST_FORMAT_TIME, stop_time)); goto pause_task; } return; eos_and_pause: { GST_DEBUG_OBJECT (musepackdec, "sending EOS event"); gst_pad_push_event (musepackdec->srcpad, gst_event_new_eos ()); /* fall through to pause */ } pause_task: { GST_DEBUG_OBJECT (musepackdec, "Pausing task"); gst_pad_pause_task (sinkpad); return; } }
static void gst_type_find_element_loop (GstPad * pad) { GstTypeFindElement *typefind; GstFlowReturn ret = GST_FLOW_OK; typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); if (typefind->need_stream_start) { gchar *stream_id; GstEvent *event; stream_id = gst_pad_create_stream_id (typefind->src, GST_ELEMENT_CAST (typefind), NULL); GST_DEBUG_OBJECT (typefind, "Pushing STREAM_START"); event = gst_event_new_stream_start (stream_id); gst_event_set_group_id (event, gst_util_group_id_next ()); gst_pad_push_event (typefind->src, event); typefind->need_stream_start = FALSE; g_free (stream_id); } if (typefind->mode == MODE_TYPEFIND) { GstPad *peer = NULL; GstCaps *found_caps = NULL; GstTypeFindProbability probability = GST_TYPE_FIND_NONE; GST_DEBUG_OBJECT (typefind, "find type in pull mode"); GST_OBJECT_LOCK (typefind); if (typefind->force_caps) { found_caps = gst_caps_ref (typefind->force_caps); probability = GST_TYPE_FIND_MAXIMUM; } GST_OBJECT_UNLOCK (typefind); if (!found_caps) { peer = gst_pad_get_peer (pad); if (peer) { gint64 size; gchar *ext; if (!gst_pad_query_duration (peer, GST_FORMAT_BYTES, &size)) { GST_WARNING_OBJECT (typefind, "Could not query upstream length!"); gst_object_unref (peer); ret = GST_FLOW_ERROR; goto pause; } /* the size if 0, we cannot continue */ if (size == 0) { /* keep message in sync with message in sink event handler */ GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (_("Stream contains no data.")), ("Can't typefind empty stream")); gst_object_unref (peer); ret = GST_FLOW_ERROR; goto pause; } ext = gst_type_find_get_extension (typefind, pad); found_caps = gst_type_find_helper_get_range (GST_OBJECT_CAST (peer), GST_OBJECT_PARENT (peer), (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)), (guint64) size, ext, &probability); g_free (ext); GST_DEBUG ("Found caps %" GST_PTR_FORMAT, found_caps); gst_object_unref (peer); } } if (!found_caps || probability < typefind->min_probability) { GST_DEBUG ("Trying to guess using extension"); gst_caps_replace (&found_caps, NULL); found_caps = gst_type_find_guess_by_extension (typefind, pad, &probability); } if (!found_caps || probability < typefind->min_probability) { GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL)); gst_caps_replace (&found_caps, NULL); ret = GST_FLOW_ERROR; goto pause; } GST_DEBUG ("Emiting found caps %" GST_PTR_FORMAT, found_caps); gst_type_find_element_emit_have_type (typefind, probability, found_caps); typefind->mode = MODE_NORMAL; gst_caps_unref (found_caps); } else if (typefind->mode == MODE_NORMAL) { GstBuffer *outbuf = NULL; if (typefind->need_segment) { typefind->need_segment = FALSE; gst_pad_push_event (typefind->src, gst_event_new_segment (&typefind->segment)); } /* Pull 4k blocks and send downstream */ ret = gst_pad_pull_range (typefind->sink, typefind->offset, 4096, &outbuf); if (ret != GST_FLOW_OK) goto pause; typefind->offset += gst_buffer_get_size (outbuf); ret = gst_pad_push (typefind->src, outbuf); if (ret != GST_FLOW_OK) goto pause; } else { /* Error out */ ret = GST_FLOW_ERROR; goto pause; } return; pause: { const gchar *reason = gst_flow_get_name (ret); gboolean push_eos = FALSE; GST_LOG_OBJECT (typefind, "pausing task, reason %s", reason); gst_pad_pause_task (typefind->sink); if (ret == GST_FLOW_EOS) { /* perform EOS logic */ if (typefind->segment.flags & GST_SEGMENT_FLAG_SEGMENT) { gint64 stop; /* for segment playback we need to post when (in stream time) * we stopped, this is either stop (when set) or the duration. */ if ((stop = typefind->segment.stop) == -1) stop = typefind->offset; GST_LOG_OBJECT (typefind, "Sending segment done, at end of segment"); gst_element_post_message (GST_ELEMENT (typefind), gst_message_new_segment_done (GST_OBJECT (typefind), GST_FORMAT_BYTES, stop)); gst_pad_push_event (typefind->src, gst_event_new_segment_done (GST_FORMAT_BYTES, stop)); } else { push_eos = TRUE; } } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) { /* for fatal errors we post an error message */ GST_ELEMENT_ERROR (typefind, STREAM, FAILED, (NULL), ("stream stopped, reason %s", reason)); push_eos = TRUE; } if (push_eos) { /* send EOS, and prevent hanging if no streams yet */ GST_LOG_OBJECT (typefind, "Sending EOS, at end of stream"); gst_pad_push_event (typefind->src, gst_event_new_eos ()); } return; } }
static void gst_raw_parse_loop (GstElement * element) { GstRawParse *rp = GST_RAW_PARSE (element); GstRawParseClass *rp_class = GST_RAW_PARSE_GET_CLASS (rp); GstFlowReturn ret; GstBuffer *buffer; gint size; if (!gst_raw_parse_set_src_caps (rp)) goto no_caps; if (rp->start_segment) { GST_DEBUG_OBJECT (rp, "sending start segment"); gst_pad_push_event (rp->srcpad, rp->start_segment); rp->start_segment = NULL; } if (rp_class->multiple_frames_per_buffer && rp->framesize < 4096) size = 4096 - (4096 % rp->framesize); else size = rp->framesize; if (rp->segment.rate >= 0) { if (rp->offset + size > rp->upstream_length) { GstFormat fmt = GST_FORMAT_BYTES; if (!gst_pad_peer_query_duration (rp->sinkpad, fmt, &rp->upstream_length)) { GST_WARNING_OBJECT (rp, "Could not get upstream duration, trying to pull frame by frame"); size = rp->framesize; } else if (rp->upstream_length < rp->offset + rp->framesize) { ret = GST_FLOW_EOS; goto pause; } else if (rp->offset + size > rp->upstream_length) { size = rp->upstream_length - rp->offset; size -= size % rp->framesize; } } } else { if (rp->offset == 0) { ret = GST_FLOW_EOS; goto pause; } else if (rp->offset < size) { size -= rp->offset; } rp->offset -= size; } buffer = NULL; ret = gst_pad_pull_range (rp->sinkpad, rp->offset, size, &buffer); if (ret != GST_FLOW_OK) { GST_DEBUG_OBJECT (rp, "pull_range (%" G_GINT64_FORMAT ", %u) " "failed, flow: %s", rp->offset, size, gst_flow_get_name (ret)); buffer = NULL; goto pause; } if (gst_buffer_get_size (buffer) < size) { GST_DEBUG_OBJECT (rp, "Short read at offset %" G_GINT64_FORMAT ", got only %" G_GSIZE_FORMAT " of %u bytes", rp->offset, gst_buffer_get_size (buffer), size); if (size > rp->framesize) { gst_buffer_set_size (buffer, gst_buffer_get_size (buffer) - gst_buffer_get_size (buffer) % rp->framesize); } else { gst_buffer_unref (buffer); buffer = NULL; ret = GST_FLOW_EOS; goto pause; } } ret = gst_raw_parse_push_buffer (rp, buffer); if (ret != GST_FLOW_OK) goto pause; return; /* ERRORS */ no_caps: { GST_ERROR_OBJECT (rp, "could not negotiate caps"); ret = GST_FLOW_NOT_NEGOTIATED; goto pause; } pause: { const gchar *reason = gst_flow_get_name (ret); GST_LOG_OBJECT (rp, "pausing task, reason %s", reason); gst_pad_pause_task (rp->sinkpad); if (ret == GST_FLOW_EOS) { if (rp->segment.flags & GST_SEEK_FLAG_SEGMENT) { GstClockTime stop; GST_LOG_OBJECT (rp, "Sending segment done"); if ((stop = rp->segment.stop) == -1) stop = rp->segment.duration; gst_element_post_message (GST_ELEMENT_CAST (rp), gst_message_new_segment_done (GST_OBJECT_CAST (rp), rp->segment.format, stop)); gst_pad_push_event (rp->srcpad, gst_event_new_segment_done (rp->segment.format, stop)); } else { GST_LOG_OBJECT (rp, "Sending EOS, at end of stream"); gst_pad_push_event (rp->srcpad, gst_event_new_eos ()); } } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) { GST_ELEMENT_ERROR (rp, STREAM, FAILED, ("Internal data stream error."), ("stream stopped, reason %s", reason)); gst_pad_push_event (rp->srcpad, gst_event_new_eos ()); } return; } }
static void gst_musepackdec_loop (GstPad * sinkpad) { GstMusepackDec *musepackdec; GstFlowReturn flow; GstBuffer *out; #ifdef MPC_IS_OLD_API guint32 update_acc, update_bits; #else mpc_frame_info frame; mpc_status err; #endif gint num_samples, samplerate, bitspersample; musepackdec = GST_MUSEPACK_DEC (GST_PAD_PARENT (sinkpad)); samplerate = g_atomic_int_get (&musepackdec->rate); if (samplerate == 0) { if (!gst_musepack_stream_init (musepackdec)) goto pause_task; gst_musepackdec_send_newsegment (musepackdec); samplerate = g_atomic_int_get (&musepackdec->rate); } bitspersample = g_atomic_int_get (&musepackdec->bps); flow = gst_pad_alloc_buffer_and_set_caps (musepackdec->srcpad, -1, MPC_DECODER_BUFFER_LENGTH * 4, GST_PAD_CAPS (musepackdec->srcpad), &out); if (flow != GST_FLOW_OK) { GST_DEBUG_OBJECT (musepackdec, "Flow: %s", gst_flow_get_name (flow)); goto pause_task; } #ifdef MPC_IS_OLD_API num_samples = mpc_decoder_decode (musepackdec->d, (MPC_SAMPLE_FORMAT *) GST_BUFFER_DATA (out), &update_acc, &update_bits); if (num_samples < 0) { GST_ERROR_OBJECT (musepackdec, "Failed to decode sample"); GST_ELEMENT_ERROR (musepackdec, STREAM, DECODE, (NULL), (NULL)); goto pause_task; } else if (num_samples == 0) { goto eos_and_pause; } #else frame.buffer = (MPC_SAMPLE_FORMAT *) GST_BUFFER_DATA (out); err = mpc_demux_decode (musepackdec->d, &frame); if (err != MPC_STATUS_OK) { GST_ERROR_OBJECT (musepackdec, "Failed to decode sample"); GST_ELEMENT_ERROR (musepackdec, STREAM, DECODE, (NULL), (NULL)); goto pause_task; } else if (frame.bits == -1) { goto eos_and_pause; } num_samples = frame.samples; #endif GST_BUFFER_SIZE (out) = num_samples * bitspersample; GST_BUFFER_OFFSET (out) = musepackdec->segment.last_stop; GST_BUFFER_TIMESTAMP (out) = gst_util_uint64_scale_int (musepackdec->segment.last_stop, GST_SECOND, samplerate); GST_BUFFER_DURATION (out) = gst_util_uint64_scale_int (num_samples, GST_SECOND, samplerate); musepackdec->segment.last_stop += num_samples; GST_LOG_OBJECT (musepackdec, "Pushing buffer, timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out))); flow = gst_pad_push (musepackdec->srcpad, out); if (flow != GST_FLOW_OK) { GST_DEBUG_OBJECT (musepackdec, "Flow: %s", gst_flow_get_name (flow)); goto pause_task; } /* check if we're at the end of a configured segment */ if (musepackdec->segment.stop != -1 && musepackdec->segment.last_stop >= musepackdec->segment.stop) { gint64 stop_time; GST_DEBUG_OBJECT (musepackdec, "Reached end of configured segment"); if ((musepackdec->segment.flags & GST_SEEK_FLAG_SEGMENT) == 0) goto eos_and_pause; GST_DEBUG_OBJECT (musepackdec, "Posting SEGMENT_DONE message"); stop_time = gst_util_uint64_scale_int (musepackdec->segment.stop, GST_SECOND, samplerate); gst_element_post_message (GST_ELEMENT (musepackdec), gst_message_new_segment_done (GST_OBJECT (musepackdec), GST_FORMAT_TIME, stop_time)); goto pause_task; } return; eos_and_pause: { GST_DEBUG_OBJECT (musepackdec, "sending EOS event"); gst_pad_push_event (musepackdec->srcpad, gst_event_new_eos ()); /* fall through to pause */ } pause_task: { GST_DEBUG_OBJECT (musepackdec, "Pausing task"); gst_pad_pause_task (sinkpad); return; } }
SegmentDoneMessagePtr SegmentDoneMessage::create(const ObjectPtr & source, Format format, qint64 position) { GstMessage *m = gst_message_new_segment_done(source, static_cast<GstFormat>(format), position); return SegmentDoneMessagePtr::wrap(m, false); }
static void gst_real_audio_demux_loop (GstRealAudioDemux * demux) { GstFlowReturn ret; GstBuffer *buf; guint bytes_needed; /* check how much data we need */ switch (demux->state) { case REAL_AUDIO_DEMUX_STATE_MARKER: bytes_needed = 6 + 16; /* 16 are beginning of header */ break; case REAL_AUDIO_DEMUX_STATE_HEADER: if (!gst_real_audio_demux_get_data_offset_from_header (demux)) goto parse_header_error; bytes_needed = demux->data_offset - (6 + 16); break; case REAL_AUDIO_DEMUX_STATE_DATA: if (demux->packet_size > 0) { /* TODO: should probably take into account width/height as well? */ bytes_needed = demux->packet_size; } else { bytes_needed = 1024; } break; default: g_return_if_reached (); } /* now get the data */ GST_LOG_OBJECT (demux, "getting data: %5u bytes @ %8" G_GINT64_MODIFIER "u", bytes_needed, demux->offset); if (demux->upstream_size > 0 && demux->offset >= demux->upstream_size) goto eos; ret = gst_pad_pull_range (demux->sinkpad, demux->offset, bytes_needed, &buf); if (ret != GST_FLOW_OK) goto pull_range_error; if (GST_BUFFER_SIZE (buf) != bytes_needed) goto pull_range_short_read; ret = gst_real_audio_demux_handle_buffer (demux, buf); if (ret != GST_FLOW_OK) goto handle_flow_error; /* TODO: increase this in chain function too (for timestamps)? */ demux->offset += bytes_needed; /* check for the end of the segment */ if (demux->segment.stop != -1 && demux->segment.last_stop != -1 && demux->segment.last_stop > demux->segment.stop) { GST_DEBUG_OBJECT (demux, "reached end of segment"); goto eos; } return; /* ERRORS */ parse_header_error: { GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL), (NULL)); goto pause_task; } handle_flow_error: { GST_WARNING_OBJECT (demux, "handle_buf flow: %s", gst_flow_get_name (ret)); goto pause_task; } pull_range_error: { GST_WARNING_OBJECT (demux, "pull range flow: %s", gst_flow_get_name (ret)); goto pause_task; } pull_range_short_read: { GST_WARNING_OBJECT (demux, "pull range short read: wanted %u bytes, but " "got only %u bytes", bytes_needed, GST_BUFFER_SIZE (buf)); gst_buffer_unref (buf); goto eos; } eos: { if (demux->state != REAL_AUDIO_DEMUX_STATE_DATA) { GST_WARNING_OBJECT (demux, "reached EOS before finished parsing header"); goto parse_header_error; } GST_INFO_OBJECT (demux, "EOS"); if ((demux->segment.flags & GST_SEEK_FLAG_SEGMENT) != 0) { gint64 stop; /* for segment playback we need to post when (in stream time) * we stopped, this is either stop (when set) or the duration. */ if ((stop = demux->segment.stop) == -1) stop = demux->segment.duration; GST_DEBUG_OBJECT (demux, "sending segment done, at end of segment"); gst_element_post_message (GST_ELEMENT (demux), gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME, stop)); } else { /* normal playback, send EOS event downstream */ GST_DEBUG_OBJECT (demux, "sending EOS event, at end of stream"); gst_pad_push_event (demux->srcpad, gst_event_new_eos ()); } goto pause_task; } pause_task: { demux->segment_running = FALSE; gst_pad_pause_task (demux->sinkpad); GST_DEBUG_OBJECT (demux, "pausing task"); return; } }
static void gst_wavpack_parse_loop (GstElement * element) { GstWavpackParse *parse = GST_WAVPACK_PARSE (element); GstFlowReturn flow_ret; WavpackHeader header = { {0,}, 0, }; GstBuffer *buf = NULL; flow_ret = gst_wavpack_parse_resync_loop (parse, &header); if (flow_ret != GST_FLOW_OK) goto pause; GST_LOG_OBJECT (parse, "Read header at offset %" G_GINT64_FORMAT ": chunk size = %u+8", parse->current_offset, header.ckSize); buf = gst_wavpack_parse_pull_buffer (parse, parse->current_offset, header.ckSize + 8, &flow_ret); if (flow_ret != GST_FLOW_OK) goto pause; if (parse->srcpad == NULL) { if (!gst_wavpack_parse_create_src_pad (parse, buf, &header)) { GST_ERROR_OBJECT (parse, "Failed to create src pad"); flow_ret = GST_FLOW_ERROR; goto pause; } } if (header.flags & INITIAL_BLOCK) gst_wavpack_parse_index_append_entry (parse, parse->current_offset, header.block_index, header.block_samples); flow_ret = gst_wavpack_parse_push_buffer (parse, buf, &header); if (flow_ret != GST_FLOW_OK) goto pause; return; pause: { const gchar *reason = gst_flow_get_name (flow_ret); GST_LOG_OBJECT (parse, "pausing task, reason %s", reason); gst_pad_pause_task (parse->sinkpad); if (GST_FLOW_IS_FATAL (flow_ret) || flow_ret == GST_FLOW_NOT_LINKED) { if (flow_ret == GST_FLOW_UNEXPECTED && parse->srcpad) { if (parse->segment.flags & GST_SEEK_FLAG_SEGMENT) { GstClockTime stop; GST_LOG_OBJECT (parse, "Sending segment done"); if ((stop = parse->segment.stop) == -1) stop = parse->segment.duration; gst_element_post_message (GST_ELEMENT_CAST (parse), gst_message_new_segment_done (GST_OBJECT_CAST (parse), parse->segment.format, stop)); } else { GST_LOG_OBJECT (parse, "Sending EOS, at end of stream"); gst_pad_push_event (parse->srcpad, gst_event_new_eos ()); } } else { GST_ELEMENT_ERROR (parse, STREAM, FAILED, (_("Internal data stream error.")), ("stream stopped, reason %s", reason)); if (parse->srcpad) gst_pad_push_event (parse->srcpad, gst_event_new_eos ()); } } return; } }
static void gst_image_freeze_src_loop (GstPad * pad) { GstImageFreeze *self = GST_IMAGE_FREEZE (GST_PAD_PARENT (pad)); GstBuffer *buffer; guint64 offset; GstClockTime timestamp, timestamp_end; guint64 cstart, cstop; gboolean in_seg, eos; GstFlowReturn flow_ret = GST_FLOW_OK; g_mutex_lock (&self->lock); if (!gst_pad_has_current_caps (self->srcpad)) { GST_ERROR_OBJECT (pad, "Not negotiated yet"); flow_ret = GST_FLOW_NOT_NEGOTIATED; g_mutex_unlock (&self->lock); goto pause_task; } if (!self->buffer) { GST_ERROR_OBJECT (pad, "Have no buffer yet"); flow_ret = GST_FLOW_ERROR; g_mutex_unlock (&self->lock); goto pause_task; } buffer = gst_buffer_ref (self->buffer); buffer = gst_buffer_make_writable (buffer); g_mutex_unlock (&self->lock); if (self->need_segment) { GstEvent *e; GST_DEBUG_OBJECT (pad, "Pushing SEGMENT event: %" GST_SEGMENT_FORMAT, &self->segment); e = gst_event_new_segment (&self->segment); g_mutex_lock (&self->lock); if (self->segment.rate >= 0) { self->offset = gst_util_uint64_scale (self->segment.start, self->fps_n, self->fps_d * GST_SECOND); } else { self->offset = gst_util_uint64_scale (self->segment.stop, self->fps_n, self->fps_d * GST_SECOND); } g_mutex_unlock (&self->lock); self->need_segment = FALSE; gst_pad_push_event (self->srcpad, e); } g_mutex_lock (&self->lock); offset = self->offset; if (self->fps_n != 0) { timestamp = gst_util_uint64_scale (offset, self->fps_d * GST_SECOND, self->fps_n); timestamp_end = gst_util_uint64_scale (offset + 1, self->fps_d * GST_SECOND, self->fps_n); } else { timestamp = self->segment.start; timestamp_end = GST_CLOCK_TIME_NONE; } eos = (self->fps_n == 0 && offset > 0) || (self->segment.rate >= 0 && self->segment.stop != -1 && timestamp > self->segment.stop) || (self->segment.rate < 0 && offset == 0) || (self->segment.rate < 0 && self->segment.start != -1 && timestamp_end < self->segment.start); if (self->fps_n == 0 && offset > 0) in_seg = FALSE; else in_seg = gst_segment_clip (&self->segment, GST_FORMAT_TIME, timestamp, timestamp_end, &cstart, &cstop); if (in_seg) { self->segment.position = cstart; if (self->segment.rate >= 0) self->segment.position = cstop; } if (self->segment.rate >= 0) self->offset++; else self->offset--; g_mutex_unlock (&self->lock); GST_DEBUG_OBJECT (pad, "Handling buffer with timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp)); if (in_seg) { GST_BUFFER_DTS (buffer) = GST_CLOCK_TIME_NONE; GST_BUFFER_PTS (buffer) = cstart; GST_BUFFER_DURATION (buffer) = cstop - cstart; GST_BUFFER_OFFSET (buffer) = offset; GST_BUFFER_OFFSET_END (buffer) = offset + 1; flow_ret = gst_pad_push (self->srcpad, buffer); GST_DEBUG_OBJECT (pad, "Pushing buffer resulted in %s", gst_flow_get_name (flow_ret)); if (flow_ret != GST_FLOW_OK) goto pause_task; } else { gst_buffer_unref (buffer); } if (eos) { flow_ret = GST_FLOW_EOS; goto pause_task; } return; pause_task: { const gchar *reason = gst_flow_get_name (flow_ret); GST_LOG_OBJECT (self, "pausing task, reason %s", reason); gst_pad_pause_task (pad); if (flow_ret == GST_FLOW_EOS) { if ((self->segment.flags & GST_SEEK_FLAG_SEGMENT)) { GstMessage *m; GstEvent *e; GST_DEBUG_OBJECT (pad, "Sending segment done at end of segment"); if (self->segment.rate >= 0) { m = gst_message_new_segment_done (GST_OBJECT_CAST (self), GST_FORMAT_TIME, self->segment.stop); e = gst_event_new_segment_done (GST_FORMAT_TIME, self->segment.stop); } else { m = gst_message_new_segment_done (GST_OBJECT_CAST (self), GST_FORMAT_TIME, self->segment.start); e = gst_event_new_segment_done (GST_FORMAT_TIME, self->segment.start); } gst_element_post_message (GST_ELEMENT_CAST (self), m); gst_pad_push_event (self->srcpad, e); } else { GST_DEBUG_OBJECT (pad, "Sending EOS at end of segment"); gst_pad_push_event (self->srcpad, gst_event_new_eos ()); } } else if (flow_ret == GST_FLOW_NOT_LINKED || flow_ret < GST_FLOW_EOS) { GST_ELEMENT_ERROR (self, STREAM, FAILED, ("Internal data stream error."), ("stream stopped, reason %s", reason)); gst_pad_push_event (self->srcpad, gst_event_new_eos ()); } return; } }