static void run_test_take (struct TestParams *params) { /* Create an adapter and feed it data of fixed size, then retrieve it in * a different size */ GstAdapter *adapter = gst_adapter_new (); guint8 *data; GstBuffer *buf; int i; gint ntimes = params->tot_size / params->write_size; for (i = 0; i < ntimes; i++) { buf = gst_buffer_new_and_alloc (params->write_size); memset (GST_BUFFER_DATA (buf), 0, params->write_size); gst_adapter_push (adapter, buf); } do { data = gst_adapter_take (adapter, params->read_size); if (data == NULL) break; g_free (data); } while (TRUE); g_object_unref (adapter); }
static GstFlowReturn gst_wildmidi_parse_song (GstWildmidi * wildmidi) { struct _WM_Info *info; GstCaps *outcaps; guint8 *data; guint size; GST_DEBUG_OBJECT (wildmidi, "Parsing song"); size = gst_adapter_available (wildmidi->adapter); data = gst_adapter_take (wildmidi->adapter, size); /* this method takes our memory block */ GST_OBJECT_LOCK (wildmidi); wildmidi->song = WildMidi_OpenBuffer (data, size); if (!wildmidi->song) goto open_failed; WildMidi_LoadSamples (wildmidi->song); WildMidi_SetOption (wildmidi->song, WM_MO_LINEAR_VOLUME, wildmidi->linear_volume); WildMidi_SetOption (wildmidi->song, WM_MO_EXPENSIVE_INTERPOLATION, wildmidi->high_quality); info = WildMidi_GetInfo (wildmidi->song); GST_OBJECT_UNLOCK (wildmidi); wildmidi->o_len = info->approx_total_samples; outcaps = gst_caps_copy (gst_pad_get_pad_template_caps (wildmidi->srcpad)); gst_pad_set_caps (wildmidi->srcpad, outcaps); gst_caps_unref (outcaps); /* we keep an internal segment in samples */ gst_segment_set_newsegment (wildmidi->o_segment, FALSE, 1.0, GST_FORMAT_DEFAULT, 0, GST_CLOCK_TIME_NONE, 0); gst_pad_push_event (wildmidi->srcpad, gst_wildmidi_get_new_segment_event (wildmidi, GST_FORMAT_TIME)); GST_DEBUG_OBJECT (wildmidi, "Parsing song done"); return GST_FLOW_OK; /* ERRORS */ open_failed: { GST_OBJECT_UNLOCK (wildmidi); GST_ELEMENT_ERROR (wildmidi, STREAM, DECODE, (NULL), ("Unable to parse midi data")); return GST_FLOW_ERROR; } }
static gboolean gst_rsvg_overlay_data_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstRsvgOverlay *overlay = GST_RSVG_OVERLAY (GST_PAD_PARENT (pad)); GST_LOG_OBJECT (pad, "Got %s event", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS:{ guint data_size; GST_RSVG_LOCK (overlay); /* FIXME: rsvgdec looks for </svg> in data to determine the end of SVG code. Should we really do the same here? IOW, could data be sent and _pushed() before the EOS gets processed? */ data_size = gst_adapter_available (overlay->adapter); if (data_size) { gst_rsvg_overlay_set_svg_data (overlay, (const gchar *) gst_adapter_take (overlay->adapter, data_size), FALSE); gst_adapter_clear (overlay->adapter); } GST_RSVG_UNLOCK (overlay); } break; case GST_EVENT_FLUSH_STOP: gst_adapter_clear (overlay->adapter); break; default: break; } /* Dropping all events here */ gst_event_unref (event); return TRUE; }
static GstFlowReturn gst_flxdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) { GstCaps *caps; guint avail; GstFlowReturn res = GST_FLOW_OK; GstFlxDec *flxdec; FlxHeader *flxh; g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); flxdec = (GstFlxDec *) parent; g_return_val_if_fail (flxdec != NULL, GST_FLOW_ERROR); gst_adapter_push (flxdec->adapter, buf); avail = gst_adapter_available (flxdec->adapter); if (flxdec->state == GST_FLXDEC_READ_HEADER) { if (avail >= FlxHeaderSize) { const guint8 *data = gst_adapter_map (flxdec->adapter, FlxHeaderSize); GstCaps *templ; memcpy ((gchar *) & flxdec->hdr, data, FlxHeaderSize); FLX_HDR_FIX_ENDIANNESS (&(flxdec->hdr)); gst_adapter_unmap (flxdec->adapter); gst_adapter_flush (flxdec->adapter, FlxHeaderSize); flxh = &flxdec->hdr; /* check header */ if (flxh->type != FLX_MAGICHDR_FLI && flxh->type != FLX_MAGICHDR_FLC && flxh->type != FLX_MAGICHDR_FLX) goto wrong_type; GST_LOG ("size : %d", flxh->size); GST_LOG ("frames : %d", flxh->frames); GST_LOG ("width : %d", flxh->width); GST_LOG ("height : %d", flxh->height); GST_LOG ("depth : %d", flxh->depth); GST_LOG ("speed : %d", flxh->speed); flxdec->next_time = 0; if (flxh->type == FLX_MAGICHDR_FLI) { flxdec->frame_time = JIFFIE * flxh->speed; } else if (flxh->speed == 0) { flxdec->frame_time = GST_SECOND / 70; } else { flxdec->frame_time = flxh->speed * GST_MSECOND; } flxdec->duration = flxh->frames * flxdec->frame_time; GST_LOG ("duration : %" GST_TIME_FORMAT, GST_TIME_ARGS (flxdec->duration)); templ = gst_pad_get_pad_template_caps (flxdec->srcpad); caps = gst_caps_copy (templ); gst_caps_unref (templ); gst_caps_set_simple (caps, "width", G_TYPE_INT, flxh->width, "height", G_TYPE_INT, flxh->height, "framerate", GST_TYPE_FRACTION, (gint) GST_MSECOND, (gint) flxdec->frame_time / 1000, NULL); gst_pad_set_caps (flxdec->srcpad, caps); gst_caps_unref (caps); if (flxh->depth <= 8) flxdec->converter = flx_colorspace_converter_new (flxh->width, flxh->height); if (flxh->type == FLX_MAGICHDR_FLC || flxh->type == FLX_MAGICHDR_FLX) { GST_LOG ("(FLC) aspect_dx : %d", flxh->aspect_dx); GST_LOG ("(FLC) aspect_dy : %d", flxh->aspect_dy); GST_LOG ("(FLC) oframe1 : 0x%08x", flxh->oframe1); GST_LOG ("(FLC) oframe2 : 0x%08x", flxh->oframe2); } flxdec->size = (flxh->width * flxh->height); /* create delta and output frame */ flxdec->frame_data = g_malloc (flxdec->size); flxdec->delta_data = g_malloc (flxdec->size); flxdec->state = GST_FLXDEC_PLAYING; } } else if (flxdec->state == GST_FLXDEC_PLAYING) { GstBuffer *out; /* while we have enough data in the adapter */ while (avail >= FlxFrameChunkSize && res == GST_FLOW_OK) { FlxFrameChunk flxfh; guchar *chunk; const guint8 *data; GstMapInfo map; chunk = NULL; data = gst_adapter_map (flxdec->adapter, FlxFrameChunkSize); memcpy (&flxfh, data, FlxFrameChunkSize); FLX_FRAME_CHUNK_FIX_ENDIANNESS (&flxfh); gst_adapter_unmap (flxdec->adapter); switch (flxfh.id) { case FLX_FRAME_TYPE: /* check if we have the complete frame */ if (avail < flxfh.size) goto need_more_data; /* flush header */ gst_adapter_flush (flxdec->adapter, FlxFrameChunkSize); chunk = gst_adapter_take (flxdec->adapter, flxfh.size - FlxFrameChunkSize); FLX_FRAME_TYPE_FIX_ENDIANNESS ((FlxFrameType *) chunk); if (((FlxFrameType *) chunk)->chunks == 0) break; /* create 32 bits output frame */ // res = gst_pad_alloc_buffer_and_set_caps (flxdec->srcpad, // GST_BUFFER_OFFSET_NONE, // flxdec->size * 4, GST_PAD_CAPS (flxdec->srcpad), &out); // if (res != GST_FLOW_OK) // break; out = gst_buffer_new_and_alloc (flxdec->size * 4); /* decode chunks */ flx_decode_chunks (flxdec, ((FlxFrameType *) chunk)->chunks, chunk + FlxFrameTypeSize, flxdec->frame_data); /* save copy of the current frame for possible delta. */ memcpy (flxdec->delta_data, flxdec->frame_data, flxdec->size); gst_buffer_map (out, &map, GST_MAP_WRITE); /* convert current frame. */ flx_colorspace_convert (flxdec->converter, flxdec->frame_data, map.data); gst_buffer_unmap (out, &map); GST_BUFFER_TIMESTAMP (out) = flxdec->next_time; flxdec->next_time += flxdec->frame_time; res = gst_pad_push (flxdec->srcpad, out); break; default: /* check if we have the complete frame */ if (avail < flxfh.size) goto need_more_data; gst_adapter_flush (flxdec->adapter, flxfh.size); break; } if (chunk) g_free (chunk); avail = gst_adapter_available (flxdec->adapter); } } need_more_data: return res; /* ERRORS */ wrong_type: { GST_ELEMENT_ERROR (flxdec, STREAM, WRONG_TYPE, (NULL), ("not a flx file (type %x)", flxh->type)); gst_object_unref (flxdec); return GST_FLOW_ERROR; } }
static GstFlowReturn gst_speex_enc_encode (GstSpeexEnc * enc, gboolean flush) { gint frame_size = enc->frame_size; gint bytes = frame_size * 2 * enc->channels; GstFlowReturn ret = GST_FLOW_OK; if (flush && gst_adapter_available (enc->adapter) % bytes != 0) { guint diff = gst_adapter_available (enc->adapter) % bytes; GstBuffer *buf = gst_buffer_new_and_alloc (diff); memset (GST_BUFFER_DATA (buf), 0, diff); gst_adapter_push (enc->adapter, buf); } while (gst_adapter_available (enc->adapter) >= bytes) { gint16 *data; gint outsize, written; GstBuffer *outbuf; data = (gint16 *) gst_adapter_take (enc->adapter, bytes); enc->samples_in += frame_size; GST_DEBUG_OBJECT (enc, "encoding %d samples (%d bytes)", frame_size, bytes); if (enc->channels == 2) { speex_encode_stereo_int (data, frame_size, &enc->bits); } speex_encode_int (enc->state, data, &enc->bits); g_free (data); enc->frameno++; enc->frameno_out++; if ((enc->frameno % enc->nframes) != 0) continue; speex_bits_insert_terminator (&enc->bits); outsize = speex_bits_nbytes (&enc->bits); ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, GST_BUFFER_OFFSET_NONE, outsize, GST_PAD_CAPS (enc->srcpad), &outbuf); if ((GST_FLOW_OK != ret)) goto done; written = speex_bits_write (&enc->bits, (gchar *) GST_BUFFER_DATA (outbuf), outsize); g_assert (written == outsize); speex_bits_reset (&enc->bits); GST_BUFFER_TIMESTAMP (outbuf) = enc->start_ts + gst_util_uint64_scale_int ((enc->frameno_out - enc->nframes) * frame_size - enc->lookahead, GST_SECOND, enc->rate); GST_BUFFER_DURATION (outbuf) = gst_util_uint64_scale_int (frame_size * enc->nframes, GST_SECOND, enc->rate); /* set gp time and granulepos; see gst-plugins-base/ext/ogg/README */ GST_BUFFER_OFFSET_END (outbuf) = enc->granulepos_offset + ((enc->frameno_out) * frame_size - enc->lookahead); GST_BUFFER_OFFSET (outbuf) = gst_util_uint64_scale_int (GST_BUFFER_OFFSET_END (outbuf), GST_SECOND, enc->rate); ret = gst_speex_enc_push_buffer (enc, outbuf); if ((GST_FLOW_OK != ret) && (GST_FLOW_NOT_LINKED != ret)) goto done; } done: return ret; }
static GstFlowReturn gst_gdp_depay_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { GstGDPDepay *this; GstFlowReturn ret = GST_FLOW_OK; GstCaps *caps; GstBuffer *buf; GstEvent *event; guint available; this = GST_GDP_DEPAY (parent); /* On DISCONT, get rid of accumulated data. We assume a buffer after the * DISCONT contains (part of) a new valid header, if not we error because we * lost sync */ if (GST_BUFFER_IS_DISCONT (buffer)) { gst_adapter_clear (this->adapter); this->state = GST_GDP_DEPAY_STATE_HEADER; } gst_adapter_push (this->adapter, buffer); while (TRUE) { switch (this->state) { case GST_GDP_DEPAY_STATE_HEADER: { guint8 *header; /* collect a complete header, validate and store the header. Figure out * the payload length and switch to the PAYLOAD state */ available = gst_adapter_available (this->adapter); if (available < GST_DP_HEADER_LENGTH) goto done; GST_LOG_OBJECT (this, "reading GDP header from adapter"); header = gst_adapter_take (this->adapter, GST_DP_HEADER_LENGTH); if (!gst_dp_validate_header (GST_DP_HEADER_LENGTH, header)) { g_free (header); goto header_validate_error; } /* store types and payload length. Also store the header, which we need * to make the payload. */ this->payload_length = gst_dp_header_payload_length (header); this->payload_type = gst_dp_header_payload_type (header); /* free previous header and store new one. */ g_free (this->header); this->header = header; GST_LOG_OBJECT (this, "read GDP header, payload size %d, payload type %d, switching to state PAYLOAD", this->payload_length, this->payload_type); this->state = GST_GDP_DEPAY_STATE_PAYLOAD; break; } case GST_GDP_DEPAY_STATE_PAYLOAD: { /* in this state we wait for all the payload data to be available in the * adapter. Then we switch to the state where we actually process the * payload. */ available = gst_adapter_available (this->adapter); if (available < this->payload_length) goto done; /* change state based on type */ if (this->payload_type == GST_DP_PAYLOAD_BUFFER) { GST_LOG_OBJECT (this, "switching to state BUFFER"); this->state = GST_GDP_DEPAY_STATE_BUFFER; } else if (this->payload_type == GST_DP_PAYLOAD_CAPS) { GST_LOG_OBJECT (this, "switching to state CAPS"); this->state = GST_GDP_DEPAY_STATE_CAPS; } else if (this->payload_type >= GST_DP_PAYLOAD_EVENT_NONE) { GST_LOG_OBJECT (this, "switching to state EVENT"); this->state = GST_GDP_DEPAY_STATE_EVENT; } else { goto wrong_type; } if (this->payload_length) { const guint8 *data; gboolean res; data = gst_adapter_map (this->adapter, this->payload_length); res = gst_dp_validate_payload (GST_DP_HEADER_LENGTH, this->header, data); gst_adapter_unmap (this->adapter); if (!res) goto payload_validate_error; } break; } case GST_GDP_DEPAY_STATE_BUFFER: { /* if we receive a buffer without caps first, we error out */ if (!this->caps) goto no_caps; GST_LOG_OBJECT (this, "reading GDP buffer from adapter"); buf = gst_dp_buffer_from_header (GST_DP_HEADER_LENGTH, this->header); if (!buf) goto buffer_failed; /* now take the payload if there is any */ if (this->payload_length > 0) { GstMapInfo map; gst_buffer_map (buf, &map, GST_MAP_WRITE); gst_adapter_copy (this->adapter, map.data, 0, this->payload_length); gst_buffer_unmap (buf, &map); gst_adapter_flush (this->adapter, this->payload_length); } /* set caps and push */ GST_LOG_OBJECT (this, "deserialized buffer %p, pushing, timestamp %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT ", offset %" G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT ", size %" G_GSIZE_FORMAT ", flags 0x%x", buf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), gst_buffer_get_size (buf), GST_BUFFER_FLAGS (buf)); ret = gst_pad_push (this->srcpad, buf); if (ret != GST_FLOW_OK) goto push_error; GST_LOG_OBJECT (this, "switching to state HEADER"); this->state = GST_GDP_DEPAY_STATE_HEADER; break; } case GST_GDP_DEPAY_STATE_CAPS: { guint8 *payload; /* take the payload of the caps */ GST_LOG_OBJECT (this, "reading GDP caps from adapter"); payload = gst_adapter_take (this->adapter, this->payload_length); caps = gst_dp_caps_from_packet (GST_DP_HEADER_LENGTH, this->header, payload); g_free (payload); if (!caps) goto caps_failed; GST_DEBUG_OBJECT (this, "deserialized caps %" GST_PTR_FORMAT, caps); gst_caps_replace (&(this->caps), caps); gst_pad_set_caps (this->srcpad, caps); /* drop the creation ref we still have */ gst_caps_unref (caps); GST_LOG_OBJECT (this, "switching to state HEADER"); this->state = GST_GDP_DEPAY_STATE_HEADER; break; } case GST_GDP_DEPAY_STATE_EVENT: { guint8 *payload; GST_LOG_OBJECT (this, "reading GDP event from adapter"); /* adapter doesn't like 0 length payload */ if (this->payload_length > 0) payload = gst_adapter_take (this->adapter, this->payload_length); else payload = NULL; event = gst_dp_event_from_packet (GST_DP_HEADER_LENGTH, this->header, payload); g_free (payload); if (!event) goto event_failed; GST_DEBUG_OBJECT (this, "deserialized event %p of type %s, pushing", event, gst_event_type_get_name (event->type)); gst_pad_push_event (this->srcpad, event); GST_LOG_OBJECT (this, "switching to state HEADER"); this->state = GST_GDP_DEPAY_STATE_HEADER; break; } } } done: return ret; /* ERRORS */ header_validate_error: { GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL), ("GDP packet header does not validate")); ret = GST_FLOW_ERROR; goto done; } payload_validate_error: { GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL), ("GDP packet payload does not validate")); ret = GST_FLOW_ERROR; goto done; } wrong_type: { GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL), ("GDP packet header is of wrong type")); ret = GST_FLOW_ERROR; goto done; } no_caps: { GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL), ("Received a buffer without first receiving caps")); ret = GST_FLOW_NOT_NEGOTIATED; goto done; } buffer_failed: { GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL), ("could not create buffer from GDP packet")); ret = GST_FLOW_ERROR; goto done; } push_error: { GST_WARNING_OBJECT (this, "pushing depayloaded buffer returned %d", ret); goto done; } caps_failed: { GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL), ("could not create caps from GDP packet")); ret = GST_FLOW_ERROR; goto done; } event_failed: { GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL), ("could not create event from GDP packet")); ret = GST_FLOW_ERROR; goto done; } }
static GstFlowReturn gst_siren_enc_chain (GstPad * pad, GstBuffer * buf) { GstSirenEnc *enc; GstFlowReturn ret = GST_FLOW_OK; GstBuffer *out_buf; guint8 *in_data, *out_data; guint8 *to_free = NULL; guint i, size, num_frames; gint out_size, in_size; gint encode_ret; gboolean discont; GstClockTime timestamp; guint64 distance; GstCaps *outcaps; enc = GST_SIREN_ENC (GST_PAD_PARENT (pad)); discont = GST_BUFFER_IS_DISCONT (buf); if (discont) { GST_DEBUG_OBJECT (enc, "received DISCONT, flush adapter"); gst_adapter_clear (enc->adapter); enc->discont = TRUE; } gst_adapter_push (enc->adapter, buf); size = gst_adapter_available (enc->adapter); GST_LOG_OBJECT (enc, "Received buffer of size %d with adapter of size : %d", GST_BUFFER_SIZE (buf), size); /* we need to process 640 input bytes to produce 40 output bytes */ /* calculate the amount of frames we will handle */ num_frames = size / 640; /* no frames, wait some more */ if (num_frames == 0) goto done; /* this is the input/output size */ in_size = num_frames * 640; out_size = num_frames * 40; GST_LOG_OBJECT (enc, "we have %u frames, %u in, %u out", num_frames, in_size, out_size); /* set output caps when needed */ if ((outcaps = GST_PAD_CAPS (enc->srcpad)) == NULL) { outcaps = gst_static_pad_template_get_caps (&srctemplate); gst_pad_set_caps (enc->srcpad, outcaps); gst_caps_unref (outcaps); } /* get a buffer */ ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, -1, out_size, outcaps, &out_buf); if (ret != GST_FLOW_OK) goto alloc_failed; /* get the timestamp for the output buffer */ timestamp = gst_adapter_prev_timestamp (enc->adapter, &distance); /* add the amount of time taken by the distance */ if (timestamp != -1) timestamp += gst_util_uint64_scale_int (distance / 2, GST_SECOND, 16000); GST_LOG_OBJECT (enc, "timestamp %" GST_TIME_FORMAT ", distance %" G_GUINT64_FORMAT, GST_TIME_ARGS (timestamp), distance); /* get the input data for all the frames */ to_free = in_data = gst_adapter_take (enc->adapter, in_size); out_data = GST_BUFFER_DATA (out_buf); for (i = 0; i < num_frames; i++) { GST_LOG_OBJECT (enc, "Encoding frame %u/%u", i, num_frames); /* encode 640 input bytes to 40 output bytes */ encode_ret = Siren7_EncodeFrame (enc->encoder, in_data, out_data); if (encode_ret != 0) goto encode_error; /* move to next frame */ out_data += 40; in_data += 640; } GST_LOG_OBJECT (enc, "Finished encoding"); /* mark discont */ if (enc->discont) { GST_BUFFER_FLAG_SET (out_buf, GST_BUFFER_FLAG_DISCONT); enc->discont = FALSE; } GST_BUFFER_TIMESTAMP (out_buf) = timestamp; GST_BUFFER_DURATION (out_buf) = num_frames * FRAME_DURATION; ret = gst_pad_push (enc->srcpad, out_buf); done: if (to_free) g_free (to_free); return ret; /* ERRORS */ alloc_failed: { GST_DEBUG_OBJECT (enc, "failed to pad_alloc buffer: %d (%s)", ret, gst_flow_get_name (ret)); goto done; } encode_error: { GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL), ("Error encoding frame: %d", encode_ret)); ret = GST_FLOW_ERROR; gst_buffer_unref (out_buf); goto done; } }
static GstFlowReturn gst_midi_parse_parse_song (GstMidiParse * midiparse) { GstCaps *outcaps; guint8 *data; guint size, offset, length; gchar *stream_id; GST_DEBUG_OBJECT (midiparse, "Parsing song"); gst_segment_init (&midiparse->segment, GST_FORMAT_TIME); midiparse->segment.duration = 0; midiparse->pulse = 0; size = gst_adapter_available (midiparse->adapter); data = gst_adapter_take (midiparse->adapter, size); midiparse->data = data; midiparse->tempo = DEFAULT_TEMPO; if (!find_midi_chunk (midiparse, data, size, &offset, &length)) goto invalid_format; while (length) { guint consumed; consumed = gst_midi_parse_chunk (midiparse, &data[offset], length); if (consumed == 0) goto short_file; offset += consumed; length -= consumed; } GST_DEBUG_OBJECT (midiparse, "song duration %" GST_TIME_FORMAT, GST_TIME_ARGS (midiparse->segment.duration)); stream_id = gst_pad_create_stream_id (midiparse->srcpad, GST_ELEMENT_CAST (midiparse), NULL); gst_pad_push_event (midiparse->srcpad, gst_event_new_stream_start (stream_id)); g_free (stream_id); outcaps = gst_pad_get_pad_template_caps (midiparse->srcpad); gst_pad_set_caps (midiparse->srcpad, outcaps); gst_caps_unref (outcaps); midiparse->segment_pending = TRUE; midiparse->discont = TRUE; GST_DEBUG_OBJECT (midiparse, "Parsing song done"); return GST_FLOW_OK; /* ERRORS */ short_file: { GST_ERROR_OBJECT (midiparse, "not enough data"); return GST_FLOW_ERROR; } invalid_format: { GST_ERROR_OBJECT (midiparse, "invalid format"); return GST_FLOW_ERROR; } }
static GstFlowReturn gst_amrnbenc_chain (GstPad * pad, GstBuffer * buffer) { GstAmrnbEnc *amrnbenc; GstFlowReturn ret; amrnbenc = GST_AMRNBENC (GST_PAD_PARENT (pad)); g_return_val_if_fail (amrnbenc->handle, GST_FLOW_WRONG_STATE); if (amrnbenc->rate == 0 || amrnbenc->channels == 0) goto not_negotiated; /* discontinuity clears adapter, FIXME, maybe we can set some * encoder flag to mask the discont. */ if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) { gst_adapter_clear (amrnbenc->adapter); amrnbenc->ts = 0; } /* take latest timestamp, FIXME timestamp is the one of the * first buffer in the adapter. */ if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) amrnbenc->ts = GST_BUFFER_TIMESTAMP (buffer); ret = GST_FLOW_OK; gst_adapter_push (amrnbenc->adapter, buffer); /* Collect samples until we have enough for an output frame */ while (gst_adapter_available (amrnbenc->adapter) >= 320) { GstBuffer *out; guint8 *data; gint outsize; /* get output, max size is 32 */ out = gst_buffer_new_and_alloc (32); GST_BUFFER_DURATION (out) = amrnbenc->duration; GST_BUFFER_TIMESTAMP (out) = amrnbenc->ts; if (amrnbenc->ts != -1) amrnbenc->ts += amrnbenc->duration; gst_buffer_set_caps (out, GST_PAD_CAPS (amrnbenc->srcpad)); /* The AMR encoder actually writes into the source data buffers it gets */ data = gst_adapter_take (amrnbenc->adapter, 320); /* encode */ outsize = Encoder_Interface_Encode (amrnbenc->handle, amrnbenc->bandmode, (short *) data, (guint8 *) GST_BUFFER_DATA (out), 0); g_free (data); GST_BUFFER_SIZE (out) = outsize; /* play */ if ((ret = gst_pad_push (amrnbenc->srcpad, out)) != GST_FLOW_OK) break; } return ret; /* ERRORS */ not_negotiated: { GST_ELEMENT_ERROR (amrnbenc, STREAM, TYPE_NOT_FOUND, (NULL), ("unknown type")); return GST_FLOW_NOT_NEGOTIATED; } }