static void user_read_data (png_structp png_ptr, png_bytep data, png_size_t length) { GstPngDec *pngdec; GstBuffer *buffer; GstFlowReturn ret = GST_FLOW_OK; pngdec = GST_PNGDEC (png_ptr->io_ptr); GST_LOG ("reading %" G_GSIZE_FORMAT " bytes of data at offset %d", length, pngdec->offset); ret = gst_pad_pull_range (pngdec->sinkpad, pngdec->offset, length, &buffer); if ((ret != GST_FLOW_OK) || (GST_BUFFER_SIZE (buffer) != length)) goto pause; memcpy (data, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); gst_buffer_unref (buffer); pngdec->offset += length; return; pause: GST_INFO_OBJECT (pngdec, "pausing task, reason %s", gst_flow_get_name (ret)); gst_pad_pause_task (pngdec->sinkpad); if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) { gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ()); GST_ELEMENT_ERROR (pngdec, STREAM, FAILED, (_("Internal data stream error.")), ("stream stopped, reason %s", gst_flow_get_name (ret))); } }
static GstFlowReturn gst_cmml_enc_push_clip (GstCmmlEnc * enc, GstCmmlTagClip * clip, GstClockTime prev_clip_time) { GstFlowReturn res; GstBuffer *buffer; gchar *clip_string; gint64 granulepos; /* encode the clip */ clip_string = (gchar *) gst_cmml_parser_tag_clip_to_string (enc->parser, clip); res = gst_cmml_enc_new_buffer (enc, (guchar *) clip_string, strlen (clip_string), &buffer); g_free (clip_string); if (res != GST_FLOW_OK) goto done; GST_INFO_OBJECT (enc, "encoding clip" "(start-time: %" GST_TIME_FORMAT " end-time: %" GST_TIME_FORMAT, GST_TIME_ARGS (clip->start_time), GST_TIME_ARGS (clip->end_time)); /* set the granulepos */ granulepos = gst_cmml_clock_time_to_granule (prev_clip_time, clip->start_time, enc->granulerate_n, enc->granulerate_d, enc->granuleshift); if (granulepos == -1) { gst_buffer_unref (buffer); goto granule_overflow; } GST_BUFFER_OFFSET (buffer) = clip->start_time; GST_BUFFER_OFFSET_END (buffer) = granulepos; GST_BUFFER_TIMESTAMP (buffer) = clip->start_time; res = gst_cmml_enc_push (enc, buffer); if (GST_FLOW_IS_FATAL (res)) goto done; if (clip->end_time != GST_CLOCK_TIME_NONE) { /* create a new empty clip for the same cmml track starting at end_time */ GObject *end_clip = g_object_new (GST_TYPE_CMML_TAG_CLIP, "start-time", clip->end_time, "track", clip->track, NULL); /* encode the empty end clip */ gst_cmml_enc_push_clip (enc, GST_CMML_TAG_CLIP (end_clip), clip->start_time); g_object_unref (end_clip); } done: return res; granule_overflow: GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL), ("granulepos overflow")); return GST_FLOW_ERROR; }
static GstFlowReturn gst_dshowvideodec_chain (GstPad * pad, GstBuffer * buffer) { GstDshowVideoDec *vdec = (GstDshowVideoDec *) gst_pad_get_parent (pad); bool discont = FALSE; GstClockTime stop; if (!vdec->setup) { /* we are not setup */ GST_WARNING_OBJECT (vdec, "Decoder not set up, failing"); vdec->last_ret = GST_FLOW_FLUSHING; goto beach; } if (GST_FLOW_IS_FATAL (vdec->last_ret)) { GST_DEBUG_OBJECT (vdec, "last decoding iteration generated a fatal error " "%s", gst_flow_get_name (vdec->last_ret)); goto beach; } /* check if duration is valid and use duration only when it's valid /* because dshow is not decoding frames having stop smaller than start */ if (GST_BUFFER_DURATION_IS_VALID (buffer)) { stop = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); } else { stop = GST_BUFFER_TIMESTAMP (buffer); } GST_CAT_LOG_OBJECT (dshowvideodec_debug, vdec, "chain (size %d)=> pts %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), GST_TIME_ARGS (stop)); /* if the incoming buffer has discont flag set => flush decoder data */ if (buffer && GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) { GST_CAT_DEBUG_OBJECT (dshowvideodec_debug, vdec, "this buffer has a DISCONT flag (%" GST_TIME_FORMAT "), flushing", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); gst_dshowvideodec_flush (vdec); discont = TRUE; } /* push the buffer to the directshow decoder */ vdec->fakesrc->GetOutputPin()->PushBuffer( GST_BUFFER_DATA (buffer), GST_BUFFER_TIMESTAMP (buffer), stop, GST_BUFFER_SIZE (buffer), discont); beach: gst_buffer_unref (buffer); gst_object_unref (vdec); return vdec->last_ret; }
static GstFlowReturn gst_cmml_enc_push (GstCmmlEnc * enc, GstBuffer * buffer) { GstFlowReturn res; /* FIXME: hack to make oggmux flush every cmml tag in its own page */ GST_BUFFER_DURATION (buffer) = G_MAXINT64; res = gst_pad_push (enc->srcpad, buffer); if (GST_FLOW_IS_FATAL (res)) GST_WARNING_OBJECT (enc, "push returned: %s", gst_flow_get_name (res)); return res; }
static GstFlowReturn gst_dshowaudiodec_chain (GstPad * pad, GstBuffer * buffer) { GstDshowAudioDec *adec = (GstDshowAudioDec *) gst_pad_get_parent (pad); bool discont = FALSE; if (!adec->setup) { /* we are not set up */ GST_WARNING_OBJECT (adec, "Decoder not set up, failing"); adec->last_ret = GST_FLOW_WRONG_STATE; goto beach; } if (GST_FLOW_IS_FATAL (adec->last_ret)) { GST_DEBUG_OBJECT (adec, "last decoding iteration generated a fatal error " "%s", gst_flow_get_name (adec->last_ret)); goto beach; } GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec, "chain (size %d)=> pts %" GST_TIME_FORMAT " stop %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer))); /* if the incoming buffer has discont flag set => flush decoder data */ if (buffer && GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) { GST_CAT_DEBUG_OBJECT (dshowaudiodec_debug, adec, "this buffer has a DISCONT flag (%" GST_TIME_FORMAT "), flushing", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); gst_dshowaudiodec_flush (adec); discont = TRUE; } /* push the buffer to the directshow decoder */ adec->fakesrc->GetOutputPin()->PushBuffer ( GST_BUFFER_DATA (buffer), GST_BUFFER_TIMESTAMP (buffer), GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer), GST_BUFFER_SIZE (buffer), (bool)discont); beach: gst_buffer_unref (buffer); gst_object_unref (adec); return adec->last_ret; }
/* encode the CMML head tag and push the CMML headers */ static void gst_cmml_enc_parse_tag_head (GstCmmlEnc * enc, GstCmmlTagHead * head) { GList *headers = NULL; GList *walk; guchar *head_string; GstCaps *caps; GstBuffer *ident_buf, *preamble_buf, *head_buf; GstBuffer *buffer; if (enc->preamble == NULL) goto flow_unexpected; GST_INFO_OBJECT (enc, "parsing head tag"); enc->flow_return = gst_cmml_enc_new_ident_header (enc, &ident_buf); if (enc->flow_return != GST_FLOW_OK) goto alloc_error; headers = g_list_append (headers, ident_buf); enc->flow_return = gst_cmml_enc_new_buffer (enc, enc->preamble, strlen ((gchar *) enc->preamble), &preamble_buf); if (enc->flow_return != GST_FLOW_OK) goto alloc_error; headers = g_list_append (headers, preamble_buf); head_string = gst_cmml_parser_tag_head_to_string (enc->parser, head); enc->flow_return = gst_cmml_enc_new_buffer (enc, head_string, strlen ((gchar *) head_string), &head_buf); g_free (head_string); if (enc->flow_return != GST_FLOW_OK) goto alloc_error; headers = g_list_append (headers, head_buf); caps = gst_pad_get_caps (enc->srcpad); caps = gst_cmml_enc_set_header_on_caps (enc, caps, ident_buf, preamble_buf, head_buf); while (headers) { buffer = GST_BUFFER (headers->data); /* set granulepos 0 on headers */ GST_BUFFER_OFFSET_END (buffer) = 0; gst_buffer_set_caps (buffer, caps); enc->flow_return = gst_cmml_enc_push (enc, buffer); headers = g_list_delete_link (headers, headers); if (GST_FLOW_IS_FATAL (enc->flow_return)) goto push_error; } gst_caps_unref (caps); enc->sent_headers = TRUE; return; flow_unexpected: GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL), ("got head tag before preamble")); enc->flow_return = GST_FLOW_ERROR; return; push_error: gst_caps_unref (caps); /* fallthrough */ alloc_error: for (walk = headers; walk; walk = walk->next) gst_buffer_unref (GST_BUFFER (walk->data)); g_list_free (headers); return; }
static void gst_pngdec_task (GstPad * pad) { GstPngDec *pngdec; GstBuffer *buffer = NULL; size_t buffer_size = 0; gint i = 0; png_bytep *rows, inp; png_uint_32 rowbytes; GstFlowReturn ret = GST_FLOW_OK; pngdec = GST_PNGDEC (GST_OBJECT_PARENT (pad)); GST_LOG_OBJECT (pngdec, "read frame"); /* Let libpng come back here on error */ if (setjmp (png_jmpbuf (pngdec->png))) { ret = GST_FLOW_ERROR; goto pause; } /* Set reading callback */ png_set_read_fn (pngdec->png, pngdec, user_read_data); /* Read info */ png_read_info (pngdec->png, pngdec->info); /* Generate the caps and configure */ ret = gst_pngdec_caps_create_and_set (pngdec); if (ret != GST_FLOW_OK) { goto pause; } /* Allocate output buffer */ rowbytes = png_get_rowbytes (pngdec->png, pngdec->info); if (rowbytes > (G_MAXUINT32 - 3) || pngdec->height > G_MAXUINT32 / rowbytes) { ret = GST_FLOW_ERROR; goto pause; } rowbytes = GST_ROUND_UP_4 (rowbytes); buffer_size = pngdec->height * rowbytes; ret = gst_pad_alloc_buffer_and_set_caps (pngdec->srcpad, GST_BUFFER_OFFSET_NONE, buffer_size, GST_PAD_CAPS (pngdec->srcpad), &buffer); if (ret != GST_FLOW_OK) goto pause; rows = (png_bytep *) g_malloc (sizeof (png_bytep) * pngdec->height); inp = GST_BUFFER_DATA (buffer); for (i = 0; i < pngdec->height; i++) { rows[i] = inp; inp += rowbytes; } /* Read the actual picture */ png_read_image (pngdec->png, rows); g_free (rows); /* Push the raw RGB frame */ ret = gst_pad_push (pngdec->srcpad, buffer); if (ret != GST_FLOW_OK) goto pause; /* And we are done */ gst_pad_pause_task (pngdec->sinkpad); gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ()); return; pause: { GST_INFO_OBJECT (pngdec, "pausing task, reason %s", gst_flow_get_name (ret)); gst_pad_pause_task (pngdec->sinkpad); if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) { GST_ELEMENT_ERROR (pngdec, STREAM, FAILED, (_("Internal data stream error.")), ("stream stopped, reason %s", gst_flow_get_name (ret))); gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ()); } } }
static void gst_timidity_loop (GstPad * sinkpad) { GstTimidity *timidity = GST_TIMIDITY (GST_PAD_PARENT (sinkpad)); GstBuffer *out; GstFlowReturn ret; if (timidity->mididata_size == 0) { if (!gst_timidity_get_upstream_size (timidity, &timidity->mididata_size)) { GST_ELEMENT_ERROR (timidity, STREAM, DECODE, (NULL), ("Unable to get song length")); goto paused; } if (timidity->mididata) g_free (timidity->mididata); timidity->mididata = g_malloc (timidity->mididata_size); timidity->mididata_offset = 0; return; } if (timidity->mididata_offset < timidity->mididata_size) { GstBuffer *buffer; gint64 size; GST_DEBUG_OBJECT (timidity, "loading song"); ret = gst_pad_pull_range (timidity->sinkpad, timidity->mididata_offset, -1, &buffer); if (ret != GST_FLOW_OK) { GST_ELEMENT_ERROR (timidity, STREAM, DECODE, (NULL), ("Unable to load song")); goto paused; } size = timidity->mididata_size - timidity->mididata_offset; if (GST_BUFFER_SIZE (buffer) < size) size = GST_BUFFER_SIZE (buffer); memmove (timidity->mididata + timidity->mididata_offset, GST_BUFFER_DATA (buffer), size); gst_buffer_unref (buffer); timidity->mididata_offset += size; GST_DEBUG_OBJECT (timidity, "Song loaded"); return; } if (!timidity->song) { MidIStream *stream; GstTagList *tags = NULL; gchar *text; GST_DEBUG_OBJECT (timidity, "Parsing song"); stream = mid_istream_open_mem (timidity->mididata, timidity->mididata_size, 0); timidity->song = mid_song_load (stream, timidity->song_options); mid_istream_close (stream); if (!timidity->song) { GST_ELEMENT_ERROR (timidity, STREAM, DECODE, (NULL), ("Unable to parse midi")); goto paused; } mid_song_start (timidity->song); timidity->o_len = (GST_MSECOND * (GstClockTime) mid_song_get_total_time (timidity->song)) / timidity->time_per_frame; gst_segment_set_newsegment (timidity->o_segment, FALSE, 1.0, GST_FORMAT_DEFAULT, 0, GST_CLOCK_TIME_NONE, 0); gst_pad_push_event (timidity->srcpad, gst_timidity_get_new_segment_event (timidity, GST_FORMAT_TIME, FALSE)); /* extract tags */ text = mid_song_get_meta (timidity->song, MID_SONG_TEXT); if (text) { tags = gst_tag_list_new (); gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, text, NULL); //g_free (text); } text = mid_song_get_meta (timidity->song, MID_SONG_COPYRIGHT); if (text) { if (tags == NULL) tags = gst_tag_list_new (); gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_COPYRIGHT, text, NULL); //g_free (text); } if (tags) { gst_element_found_tags (GST_ELEMENT (timidity), tags); } GST_DEBUG_OBJECT (timidity, "Parsing song done"); return; } if (timidity->o_segment_changed) { GstSegment *segment = gst_timidity_get_segment (timidity, GST_FORMAT_TIME, !timidity->o_new_segment); GST_LOG_OBJECT (timidity, "sending newsegment from %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT ", pos=%" GST_TIME_FORMAT, GST_TIME_ARGS ((guint64) segment->start), GST_TIME_ARGS ((guint64) segment->stop), GST_TIME_ARGS ((guint64) segment->time)); if (timidity->o_segment->flags & GST_SEEK_FLAG_SEGMENT) { gst_element_post_message (GST_ELEMENT (timidity), gst_message_new_segment_start (GST_OBJECT (timidity), segment->format, segment->start)); } gst_segment_free (segment); timidity->o_segment_changed = FALSE; return; } if (timidity->o_seek) { /* perform a seek internally */ timidity->o_segment->last_stop = timidity->o_segment->time; mid_song_seek (timidity->song, (timidity->o_segment->last_stop * timidity->time_per_frame) / GST_MSECOND); } out = gst_timidity_get_buffer (timidity); if (!out) { GST_LOG_OBJECT (timidity, "Song ended, generating eos"); gst_pad_push_event (timidity->srcpad, gst_event_new_eos ()); timidity->o_seek = FALSE; goto paused; } if (timidity->o_seek) { GST_BUFFER_FLAG_SET (out, GST_BUFFER_FLAG_DISCONT); timidity->o_seek = FALSE; } gst_buffer_set_caps (out, timidity->out_caps); ret = gst_pad_push (timidity->srcpad, out); if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) goto error; return; paused: { GST_DEBUG_OBJECT (timidity, "pausing task"); gst_pad_pause_task (timidity->sinkpad); return; } error: { GST_ELEMENT_ERROR (timidity, STREAM, FAILED, ("Internal data stream error"), ("Streaming stopped, reason %s", gst_flow_get_name (ret))); gst_pad_push_event (timidity->srcpad, gst_event_new_eos ()); goto paused; } }
static GstFlowReturn gst_ogg_avi_parse_chain (GstPad * pad, GstBuffer * buffer) { GstFlowReturn result = GST_FLOW_OK; GstOggAviParse *ogg; guint8 *data; guint size; gchar *oggbuf; gint ret = -1; ogg = GST_OGG_AVI_PARSE (GST_OBJECT_PARENT (pad)); data = GST_BUFFER_DATA (buffer); size = GST_BUFFER_SIZE (buffer); GST_LOG_OBJECT (ogg, "Chain function received buffer of size %d", size); if (GST_BUFFER_IS_DISCONT (buffer)) { ogg_sync_reset (&ogg->sync); ogg->discont = TRUE; } /* write data to sync layer */ oggbuf = ogg_sync_buffer (&ogg->sync, size); memcpy (oggbuf, data, size); ogg_sync_wrote (&ogg->sync, size); gst_buffer_unref (buffer); /* try to get as many packets out of the stream as possible */ do { ogg_page page; /* try to swap out a page */ ret = ogg_sync_pageout (&ogg->sync, &page); if (ret == 0) { GST_DEBUG_OBJECT (ogg, "need more data"); break; } else if (ret == -1) { GST_DEBUG_OBJECT (ogg, "discont in pages"); ogg->discont = TRUE; } else { /* new unknown stream, init the ogg stream with the serial number of the * page. */ if (ogg->serial == -1) { ogg->serial = ogg_page_serialno (&page); ogg_stream_init (&ogg->stream, ogg->serial); } /* submit page */ if (ogg_stream_pagein (&ogg->stream, &page) != 0) { GST_WARNING_OBJECT (ogg, "ogg stream choked on page resetting stream"); ogg_sync_reset (&ogg->sync); ogg->discont = TRUE; continue; } /* try to get as many packets as possible out of the page */ do { ogg_packet packet; ret = ogg_stream_packetout (&ogg->stream, &packet); GST_LOG_OBJECT (ogg, "packetout gave %d", ret); switch (ret) { case 0: break; case -1: /* out of sync, We mark a DISCONT. */ ogg->discont = TRUE; break; case 1: result = gst_ogg_avi_parse_push_packet (ogg, &packet); if (GST_FLOW_IS_FATAL (result)) goto done; break; default: GST_WARNING_OBJECT (ogg, "invalid return value %d for ogg_stream_packetout, resetting stream", ret); break; } } while (ret != 0); } } while (ret != 0); done: return result; }
static void spc_play (GstPad * pad) { GstSpcDec *spc = GST_SPC_DEC (gst_pad_get_parent (pad)); GstFlowReturn flow_return; GstBuffer *out; gboolean seeking = spc->seeking; gint64 duration, fade, end, position; if (!seeking) { out = gst_buffer_new_and_alloc (1600 * 4); gst_buffer_set_caps (out, GST_PAD_CAPS (pad)); GST_BUFFER_TIMESTAMP (out) = (gint64) gst_util_uint64_scale ((guint64) spc->byte_pos, GST_SECOND, 32000 * 2 * 2); spc->byte_pos += OSPC_Run (-1, (short *) GST_BUFFER_DATA (out), 1600 * 4); } else { if (spc->seekpoint < spc->byte_pos) { OSPC_Init (GST_BUFFER_DATA (spc->buf), GST_BUFFER_SIZE (spc->buf)); spc->byte_pos = 0; } spc->byte_pos += OSPC_Run (-1, NULL, 1600 * 4); if (spc->byte_pos >= spc->seekpoint) { spc->seeking = FALSE; } out = gst_buffer_new (); gst_buffer_set_caps (out, GST_PAD_CAPS (pad)); } duration = gst_spc_duration (spc); fade = gst_spc_fadeout (spc); end = duration + fade; position = (gint64) gst_util_uint64_scale ((guint64) spc->byte_pos, GST_SECOND, 32000 * 2 * 2); if (position >= duration) { gint16 *data = (gint16 *) GST_BUFFER_DATA (out); guint32 size = GST_BUFFER_SIZE (out) / sizeof (gint16); unsigned int i; gint64 num = (fade - (position - duration)); for (i = 0; i < size; i++) { /* Apply a parabolic volume envelope */ data[i] = (gint16) (data[i] * num / fade * num / fade); } } if ((flow_return = gst_pad_push (spc->srcpad, out)) != GST_FLOW_OK) { GST_DEBUG_OBJECT (spc, "pausing task, reason %s", gst_flow_get_name (flow_return)); gst_pad_pause_task (pad); if (GST_FLOW_IS_FATAL (flow_return) || flow_return == GST_FLOW_NOT_LINKED) { gst_pad_push_event (pad, gst_event_new_eos ()); } } if (position >= end) { gst_pad_pause_task (pad); gst_pad_push_event (pad, gst_event_new_eos ()); } gst_object_unref (spc); return; }
static GstFlowReturn gst_nuv_demux_play (GstPad * pad) { GstFlowReturn res = GST_FLOW_OK; GstNuvDemux *nuv = GST_NUV_DEMUX (GST_PAD_PARENT (pad)); switch (nuv->state) { case GST_NUV_DEMUX_START: res = gst_nuv_demux_stream_file_header (nuv); if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) { goto pause; } if (nuv->state != GST_NUV_DEMUX_HEADER_DATA) break; case GST_NUV_DEMUX_HEADER_DATA: res = gst_nuv_demux_stream_header_data (nuv); if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) { goto pause; } if (nuv->state != GST_NUV_DEMUX_EXTRA_DATA) break; case GST_NUV_DEMUX_EXTRA_DATA: res = gst_nuv_demux_stream_extra_data (nuv); if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) { goto pause; } if (nuv->state != GST_NUV_DEMUX_MPEG_DATA) break; case GST_NUV_DEMUX_MPEG_DATA: res = gst_nuv_demux_stream_mpeg_data (nuv); if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) { goto pause; } if (nuv->state != GST_NUV_DEMUX_EXTEND_HEADER) break; case GST_NUV_DEMUX_EXTEND_HEADER: res = gst_nuv_demux_stream_extend_header (nuv); if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) { goto pause; } if (nuv->state != GST_NUV_DEMUX_EXTEND_HEADER_DATA) break; case GST_NUV_DEMUX_EXTEND_HEADER_DATA: res = gst_nuv_demux_stream_extend_header_data (nuv); if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) { goto pause; } if (nuv->state != GST_NUV_DEMUX_FRAME_HEADER) break; case GST_NUV_DEMUX_FRAME_HEADER: res = gst_nuv_demux_read_head_frame (nuv); if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) { goto pause; } if (nuv->state != GST_NUV_DEMUX_MOVI) break; case GST_NUV_DEMUX_MOVI: res = gst_nuv_demux_stream_data (nuv); if ((res != GST_FLOW_OK) && (res != GST_FLOW_CUSTOM_ERROR)) { goto pause; } break; case GST_NUV_DEMUX_INVALID_DATA: goto pause; break; default: g_assert_not_reached (); } GST_DEBUG_OBJECT (nuv, "state: %d res:%s", nuv->state, gst_flow_get_name (res)); return GST_FLOW_OK; pause: GST_LOG_OBJECT (nuv, "pausing task, reason %s", gst_flow_get_name (res)); gst_pad_pause_task (nuv->sinkpad); if (GST_FLOW_IS_FATAL (res)) { GST_ELEMENT_ERROR (nuv, STREAM, FAILED, (_("Internal data stream error.")), ("streaming stopped, reason %s", gst_flow_get_name (res))); gst_nuv_demux_send_eos (nuv); } return res; }
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_wildmidi_loop (GstPad * sinkpad) { GstWildmidi *wildmidi = GST_WILDMIDI (GST_PAD_PARENT (sinkpad)); GstFlowReturn ret; switch (wildmidi->state) { case GST_WILDMIDI_STATE_LOAD: { GstBuffer *buffer; GST_DEBUG_OBJECT (wildmidi, "loading song"); ret = gst_pad_pull_range (wildmidi->sinkpad, wildmidi->offset, -1, &buffer); if (ret == GST_FLOW_UNEXPECTED) { GST_DEBUG_OBJECT (wildmidi, "Song loaded"); wildmidi->state = GST_WILDMIDI_STATE_PARSE; } else if (ret != GST_FLOW_OK) { GST_ELEMENT_ERROR (wildmidi, STREAM, DECODE, (NULL), ("Unable to read song")); goto pause; } else { GST_DEBUG_OBJECT (wildmidi, "pushing buffer"); gst_adapter_push (wildmidi->adapter, buffer); wildmidi->offset += GST_BUFFER_SIZE (buffer); } break; } case GST_WILDMIDI_STATE_PARSE: ret = gst_wildmidi_parse_song (wildmidi); if (ret != GST_FLOW_OK) goto pause; wildmidi->state = GST_WILDMIDI_STATE_PLAY; break; case GST_WILDMIDI_STATE_PLAY: ret = gst_wildmidi_do_play (wildmidi); if (ret != GST_FLOW_OK) goto pause; break; default: break; } return; pause: { const gchar *reason = gst_flow_get_name (ret); GstEvent *event; GST_DEBUG_OBJECT (wildmidi, "pausing task, reason %s", reason); gst_pad_pause_task (sinkpad); if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) { if (ret == GST_FLOW_UNEXPECTED) { /* perform EOS logic */ event = gst_event_new_eos (); gst_pad_push_event (wildmidi->srcpad, event); } else { event = gst_event_new_eos (); /* for fatal errors we post an error message, post the error * first so the app knows about the error first. */ GST_ELEMENT_ERROR (wildmidi, STREAM, FAILED, ("Internal data flow error."), ("streaming task paused, reason %s (%d)", reason, ret)); gst_pad_push_event (wildmidi->srcpad, event); } } } }
static void gst_aiffparse_loop (GstPad * pad) { GstFlowReturn ret; AIFFParse *aiff = AIFFPARSE (GST_PAD_PARENT (pad)); GST_LOG_OBJECT (aiff, "process data"); switch (aiff->state) { case AIFFPARSE_START: GST_INFO_OBJECT (aiff, "AIFFPARSE_START"); if ((ret = gst_aiffparse_stream_init (aiff)) != GST_FLOW_OK) goto pause; aiff->state = AIFFPARSE_HEADER; /* fall-through */ case AIFFPARSE_HEADER: GST_INFO_OBJECT (aiff, "AIFFPARSE_HEADER"); if ((ret = gst_aiffparse_stream_headers (aiff)) != GST_FLOW_OK) goto pause; aiff->state = AIFFPARSE_DATA; GST_INFO_OBJECT (aiff, "AIFFPARSE_DATA"); /* fall-through */ case AIFFPARSE_DATA: if ((ret = gst_aiffparse_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 (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) { 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 { /* 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_rnd_buffer_size_loop (GstRndBufferSize * self) { GstBuffer *buf = NULL; GstFlowReturn ret; guint num_bytes; if (G_UNLIKELY (self->min > self->max)) goto bogus_minmax; if (G_UNLIKELY (self->min != self->max)) { num_bytes = g_rand_int_range (self->rand, self->min, self->max); } else { num_bytes = self->min; } GST_LOG_OBJECT (self, "pulling %u bytes at offset %" G_GUINT64_FORMAT, num_bytes, self->offset); ret = gst_pad_pull_range (self->sinkpad, self->offset, num_bytes, &buf); if (ret != GST_FLOW_OK) goto pull_failed; if (GST_BUFFER_SIZE (buf) < num_bytes) { GST_WARNING_OBJECT (self, "short buffer: %u bytes", GST_BUFFER_SIZE (buf)); } self->offset += GST_BUFFER_SIZE (buf); ret = gst_pad_push (self->srcpad, buf); if (ret != GST_FLOW_OK) goto push_failed; return; pause_task: { GST_DEBUG_OBJECT (self, "pausing task"); gst_pad_pause_task (self->sinkpad); return; } pull_failed: { if (ret == GST_FLOW_UNEXPECTED) { GST_DEBUG_OBJECT (self, "eos"); gst_pad_push_event (self->srcpad, gst_event_new_eos ()); } else { GST_WARNING_OBJECT (self, "pull_range flow: %s", gst_flow_get_name (ret)); } goto pause_task; } push_failed: { GST_DEBUG_OBJECT (self, "push flow: %s", gst_flow_get_name (ret)); if (ret == GST_FLOW_UNEXPECTED) { GST_DEBUG_OBJECT (self, "eos"); gst_pad_push_event (self->srcpad, gst_event_new_eos ()); } else if (GST_FLOW_IS_FATAL (ret) || ret == GST_FLOW_NOT_LINKED) { GST_ELEMENT_ERROR (self, STREAM, FAILED, ("Internal data stream error."), ("streaming stopped, reason: %s", gst_flow_get_name (ret))); } goto pause_task; } bogus_minmax: { GST_ELEMENT_ERROR (self, LIBRARY, SETTINGS, ("The minimum buffer size is smaller than the maximum buffer size."), ("buffer sizes: max=%ld, min=%ld", self->min, self->max)); goto pause_task; } }