/** * gst_adapter_take_buffer: * @adapter: a #GstAdapter * @nbytes: the number of bytes to take * * Returns a #GstBuffer containing the first @nbytes bytes of the * @adapter. The returned bytes will be flushed from the adapter. * This function is potentially more performant than gst_adapter_take() * since it can reuse the memory in pushed buffers by subbuffering * or merging. * * Caller owns returned value. gst_buffer_unref() after usage. * * Since: 0.10.6 * * Returns: a #GstBuffer containing the first @nbytes of the adapter, * or #NULL if @nbytes bytes are not available */ GstBuffer * gst_adapter_take_buffer (GstAdapter * adapter, guint nbytes) { GstBuffer *buffer; GstBuffer *cur; guint hsize, skip; guint8 *data; g_return_val_if_fail (GST_IS_ADAPTER (adapter), NULL); g_return_val_if_fail (nbytes > 0, NULL); GST_LOG_OBJECT (adapter, "taking buffer of %u bytes", nbytes); /* we don't have enough data, return NULL. This is unlikely * as one usually does an _available() first instead of grabbing a * random size. */ if (G_UNLIKELY (nbytes > adapter->size)) return NULL; cur = adapter->buflist->data; skip = adapter->skip; hsize = GST_BUFFER_SIZE (cur); /* our head buffer has enough data left, return it */ if (skip == 0 && hsize == nbytes) { GST_LOG_OBJECT (adapter, "providing buffer of %d bytes as head buffer", nbytes); buffer = gst_buffer_ref (cur); goto done; } else if (hsize >= nbytes + skip) { GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer", nbytes); buffer = gst_buffer_create_sub (cur, skip, nbytes); goto done; } if (gst_adapter_try_to_merge_up (adapter, nbytes)) { /* Merged something, let's try again for sub-buffering */ cur = adapter->buflist->data; if (GST_BUFFER_SIZE (cur) >= nbytes + skip) { GST_LOG_OBJECT (adapter, "providing buffer of %d bytes via sub-buffer", nbytes); buffer = gst_buffer_create_sub (cur, skip, nbytes); goto done; } } data = gst_adapter_take_internal (adapter, nbytes); buffer = gst_buffer_new (); GST_BUFFER_SIZE (buffer) = nbytes; GST_BUFFER_DATA (buffer) = data; GST_BUFFER_MALLOCDATA (buffer) = data; done: gst_adapter_flush_unchecked (adapter, nbytes); return buffer; }
static void gst_deinterlace2_push_history (GstDeinterlace2 * self, GstBuffer * buffer) { int i = 1; GstClockTime timestamp; g_assert (self->history_count < MAX_FIELD_HISTORY - 2); for (i = MAX_FIELD_HISTORY - 1; i >= 2; i--) { self->field_history[i].buf = self->field_history[i - 2].buf; self->field_history[i].flags = self->field_history[i - 2].flags; } if (self->field_layout == GST_DEINTERLACE2_LAYOUT_AUTO) { GST_WARNING ("Could not detect field layout. Assuming top field first."); self->field_layout = GST_DEINTERLACE2_LAYOUT_TFF; } if (self->field_layout == GST_DEINTERLACE2_LAYOUT_TFF) { GST_DEBUG ("Top field first"); self->field_history[0].buf = gst_buffer_create_sub (buffer, self->line_length, GST_BUFFER_SIZE (buffer) - self->line_length); self->field_history[0].flags = PICTURE_INTERLACED_BOTTOM; self->field_history[1].buf = buffer; self->field_history[1].flags = PICTURE_INTERLACED_TOP; } else { GST_DEBUG ("Bottom field first"); self->field_history[0].buf = buffer; self->field_history[0].flags = PICTURE_INTERLACED_TOP; self->field_history[1].buf = gst_buffer_create_sub (buffer, self->line_length, GST_BUFFER_SIZE (buffer) - self->line_length); self->field_history[1].flags = PICTURE_INTERLACED_BOTTOM; } /* Timestamps are assigned to the field buffers under the assumption that the timestamp of the buffer equals the first fields timestamp */ timestamp = GST_BUFFER_TIMESTAMP (buffer); GST_BUFFER_TIMESTAMP (self->field_history[0].buf) = timestamp + self->field_duration; GST_BUFFER_TIMESTAMP (self->field_history[1].buf) = timestamp; self->history_count += 2; GST_DEBUG ("push, size(history): %d", self->history_count); }
EXPORT_C #endif GstBuffer * gst_rtp_buffer_get_payload_subbuffer (GstBuffer * buffer, guint offset, guint len) { guint poffset, plen; g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); g_return_val_if_fail (GST_BUFFER_DATA (buffer) != NULL, NULL); plen = gst_rtp_buffer_get_payload_len (buffer); /* we can't go past the length */ if (G_UNLIKELY (offset >= plen)) { GST_WARNING ("offset=%u should be less then plen=%u", offset, plen); return (NULL); } /* apply offset */ poffset = gst_rtp_buffer_get_header_len (buffer) + offset; plen -= offset; /* see if we need to shrink the buffer based on @len */ if (len != -1 && len < plen) plen = len; return gst_buffer_create_sub (buffer, poffset, plen); }
static GstBuffer * buffer_slice(AudioTrim *filter, GstBuffer *buf, gint64 start, gint64 end) { GstBuffer *sub; gint byte_start; gint byte_size; g_assert(start <= end); /* Check if buffer is outside range */ if (start >= GST_BUFFER_OFFSET_END(buf) || end <= GST_BUFFER_OFFSET(buf) || start == end) { return NULL; } /* Return original buffer if possible */ if (start <= GST_BUFFER_OFFSET(buf) && end >= GST_BUFFER_OFFSET_END(buf)) { return gst_buffer_ref(buf); } if (start < GST_BUFFER_OFFSET(buf)) start = GST_BUFFER_OFFSET(buf); if (end > GST_BUFFER_OFFSET_END(buf)) end = GST_BUFFER_OFFSET_END(buf); byte_start = (start - GST_BUFFER_OFFSET(buf)) * sizeof(gfloat); g_assert(byte_start < GST_BUFFER_SIZE(buf)); byte_size = (end - start) * sizeof(gfloat); sub = gst_buffer_create_sub(buf, byte_start, byte_size); copy_caps(buf, sub); GST_BUFFER_TIMESTAMP(sub) = sample_to_time(filter, start); GST_BUFFER_OFFSET(sub) = start; GST_BUFFER_DURATION(sub) = sample_to_time(filter, end-start); GST_BUFFER_OFFSET_END(sub) = end; return sub; }
static GstBuffer * gst_timidity_clip_buffer (GstTimidity * timidity, GstBuffer * buffer) { gint64 new_start, new_stop; gint64 offset, length; GstBuffer *out; return buffer; if (!gst_segment_clip (timidity->o_segment, GST_FORMAT_DEFAULT, GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET_END (buffer), &new_start, &new_stop)) { gst_buffer_unref (buffer); return NULL; } if (GST_BUFFER_OFFSET (buffer) == new_start && GST_BUFFER_OFFSET_END (buffer) == new_stop) return buffer; offset = new_start - GST_BUFFER_OFFSET (buffer); length = new_stop - new_start; out = gst_buffer_create_sub (buffer, offset * timidity->bytes_per_frame, length * timidity->bytes_per_frame); GST_BUFFER_OFFSET (out) = new_start; GST_BUFFER_OFFSET_END (out) = new_stop; GST_BUFFER_TIMESTAMP (out) = new_start * timidity->time_per_frame; GST_BUFFER_DURATION (out) = (new_stop - new_start) * timidity->time_per_frame; gst_buffer_unref (buffer); return out; }
/** * gst_rtp_buffer_get_payload_subbuffer: * @buffer: the buffer * @offset: the offset in the payload * @len: the length in the payload * * Create a subbuffer of the payload of the RTP packet in @buffer. @offset bytes * are skipped in the payload and the subbuffer will be of size @len. * If @len is -1 the total payload starting from @offset if subbuffered. * * Returns: A new buffer with the specified data of the payload. * * Since: 0.10.10 */ GstBuffer * gst_rtp_buffer_get_payload_subbuffer (GstBuffer * buffer, guint offset, guint len) { guint poffset, plen; plen = gst_rtp_buffer_get_payload_len (buffer); /* we can't go past the length */ if (G_UNLIKELY (offset >= plen)) goto wrong_offset; /* apply offset */ poffset = gst_rtp_buffer_get_header_len (buffer) + offset; plen -= offset; /* see if we need to shrink the buffer based on @len */ if (len != -1 && len < plen) plen = len; return gst_buffer_create_sub (buffer, poffset, plen); /* ERRORS */ wrong_offset: { g_warning ("offset=%u should be less then plen=%u", offset, plen); return NULL; } }
static GstBuffer * gst_vdp_mpeg_packetizer_get_next_packet (GstVdpMpegPacketizer * packetizer) { guint offset, size; GstBuffer *buf; if (packetizer->start == -1) return NULL; if (!gst_byte_reader_set_pos (&packetizer->reader, packetizer->start + 3)) return NULL; offset = gst_byte_reader_masked_scan_uint32 (&packetizer->reader, 0xffffff00, 0x00000100, 0, gst_byte_reader_get_remaining (&packetizer->reader)); if (offset != -1) { offset = gst_byte_reader_get_pos (&packetizer->reader) + offset; size = offset - packetizer->start; } else size = gst_byte_reader_get_remaining (&packetizer->reader) + 3; buf = gst_buffer_create_sub (packetizer->buffer, packetizer->start, size); packetizer->start = offset; return buf; }
static void dxr3videosink_discard_data (Dxr3VideoSink * sink, guint cut) { GstBuffer *sub; guint size; g_return_if_fail (sink->cur_buf != NULL); g_assert (cut <= sink->scan_pos); size = sink->scan_pos - cut; g_return_if_fail (size <= GST_BUFFER_SIZE (sink->cur_buf)); if (GST_BUFFER_SIZE (sink->cur_buf) == size) { gst_buffer_unref (sink->cur_buf); sink->cur_buf = NULL; } else { sub = gst_buffer_create_sub (sink->cur_buf, size, GST_BUFFER_SIZE (sink->cur_buf) - size); gst_buffer_unref (sink->cur_buf); sink->cur_buf = sub; } sink->scan_state = SCAN_STATE_WAITING; sink->scan_pos = cut; sink->cur_ts = GST_CLOCK_TIME_NONE; }
/** * gst_buffer_span: * @buf1: the first source #GstBuffer to merge. * @offset: the offset in the first buffer from where the new * buffer should start. * @buf2: the second source #GstBuffer to merge. * @len: the total length of the new buffer. * * Creates a new buffer that consists of part of buf1 and buf2. * Logically, buf1 and buf2 are concatenated into a single larger * buffer, and a new buffer is created at the given offset inside * this space, with a given length. * * If the two source buffers are children of the same larger buffer, * and are contiguous, the new buffer will be a child of the shared * parent, and thus no copying is necessary. you can use * gst_buffer_is_span_fast() to determine if a memcpy will be needed. * * MT safe. * Returns: the new #GstBuffer that spans the two source buffers. * Returns NULL if the arguments are invalid. */ GstBuffer * gst_buffer_span (GstBuffer * buf1, guint32 offset, GstBuffer * buf2, guint32 len) { GstBuffer *newbuf; g_return_val_if_fail (buf1 != NULL && buf2 != NULL, NULL); g_return_val_if_fail (buf1->mini_object.refcount > 0, NULL); g_return_val_if_fail (buf2->mini_object.refcount > 0, NULL); g_return_val_if_fail (len > 0, NULL); g_return_val_if_fail (len <= buf1->size + buf2->size - offset, NULL); /* if the two buffers have the same parent and are adjacent */ if (gst_buffer_is_span_fast (buf1, buf2)) { GstBuffer *parent = GST_SUBBUFFER_CAST (buf1)->parent; /* we simply create a subbuffer of the common parent */ newbuf = gst_buffer_create_sub (parent, buf1->data - parent->data + offset, len); } else { GST_CAT_DEBUG (GST_CAT_BUFFER, "slow path taken while spanning buffers %p and %p", buf1, buf2); /* otherwise we simply have to brute-force copy the buffers */ newbuf = gst_buffer_new_and_alloc (len); /* copy the first buffer's data across */ memcpy (newbuf->data, buf1->data + offset, buf1->size - offset); /* copy the second buffer's data across */ memcpy (newbuf->data + (buf1->size - offset), buf2->data, len - (buf1->size - offset)); } /* if the offset is 0, the new buffer has the same timestamp as buf1 */ if (offset == 0) { GST_BUFFER_OFFSET (newbuf) = GST_BUFFER_OFFSET (buf1); GST_BUFFER_TIMESTAMP (newbuf) = GST_BUFFER_TIMESTAMP (buf1); /* if we completely merged the two buffers (appended), we can * calculate the duration too. Also make sure we's not messing with * invalid DURATIONS */ if (buf1->size + buf2->size == len) { if (GST_BUFFER_DURATION_IS_VALID (buf1) && GST_BUFFER_DURATION_IS_VALID (buf2)) { /* add duration */ GST_BUFFER_DURATION (newbuf) = GST_BUFFER_DURATION (buf1) + GST_BUFFER_DURATION (buf2); } if (GST_BUFFER_OFFSET_END_IS_VALID (buf2)) { /* add offset_end */ GST_BUFFER_OFFSET_END (newbuf) = GST_BUFFER_OFFSET_END (buf2); } } } return newbuf; }
static GstFlowReturn gst_dtsdec_chain_raw (GstPad * pad, GstBuffer * buf) { GstDtsDec *dts; guint8 *data; gint size; gint length, flags, sample_rate, bit_rate, frame_length; GstFlowReturn result = GST_FLOW_OK; dts = GST_DTSDEC (GST_PAD_PARENT (pad)); if (dts->cache) { buf = gst_buffer_join (dts->cache, buf); dts->cache = NULL; } data = GST_BUFFER_DATA (buf); size = GST_BUFFER_SIZE (buf); length = 0; while (size >= 7) { length = dts_syncinfo (dts->state, data, &flags, &sample_rate, &bit_rate, &frame_length); if (length == 0) { /* shift window to re-find sync */ data++; size--; } else if (length <= size) { GST_DEBUG ("Sync: frame size %d", length); result = gst_dtsdec_handle_frame (dts, data, length, flags, sample_rate, bit_rate); if (result != GST_FLOW_OK) { size = 0; break; } size -= length; data += length; } else { GST_LOG ("Not enough data available (needed %d had %d)", length, size); break; } } /* keep cache */ if (length == 0) { GST_LOG ("No sync found"); } if (size > 0) { dts->cache = gst_buffer_create_sub (buf, GST_BUFFER_SIZE (buf) - size, size); } gst_buffer_unref (buf); return result; }
/* Output buffer preparation... if the buffer has no caps, and * our allowed output caps is fixed, then give the caps to the * buffer. * This ensures that outgoing buffers have caps if we can, so * that pipelines like: * gst-launch filesrc location=rawsamples.raw ! * audio/x-raw-int,width=16,depth=16,rate=48000,channels=2, * endianness=4321,signed='(boolean)'true ! alsasink * will work. */ static GstFlowReturn gst_capsfilter_prepare_buf (GstBaseTransform * trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf) { if (GST_BUFFER_CAPS (input) != NULL) { /* Output buffer already has caps */ GST_DEBUG_OBJECT (trans, "Input buffer already has caps (implicitely fixed)"); /* FIXME : Move this behaviour to basetransform. The given caps are the ones * of the source pad, therefore our outgoing buffers should always have * those caps. */ gst_buffer_set_caps (input, caps); gst_buffer_ref (input); *buf = input; } else { /* Buffer has no caps. See if the output pad only supports fixed caps */ GstCaps *out_caps; out_caps = GST_PAD_CAPS (trans->srcpad); if (out_caps != NULL) { gst_caps_ref (out_caps); } else { out_caps = gst_pad_get_allowed_caps (trans->srcpad); g_return_val_if_fail (out_caps != NULL, GST_FLOW_ERROR); } out_caps = gst_caps_make_writable (out_caps); gst_caps_do_simplify (out_caps); if (gst_caps_is_fixed (out_caps) && !gst_caps_is_empty (out_caps)) { GST_DEBUG_OBJECT (trans, "Have fixed output caps %" GST_PTR_FORMAT " to apply to buffer with no caps", out_caps); if (gst_buffer_is_metadata_writable (input)) { gst_buffer_ref (input); *buf = input; } else { GST_DEBUG_OBJECT (trans, "Creating sub-buffer and setting caps"); *buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input)); } GST_BUFFER_CAPS (*buf) = out_caps; if (GST_PAD_CAPS (trans->srcpad) == NULL) gst_pad_set_caps (trans->srcpad, out_caps); } else { GST_DEBUG_OBJECT (trans, "Have unfixed output caps %" GST_PTR_FORMAT, out_caps); gst_caps_unref (out_caps); } } return GST_FLOW_OK; }
static GstData * gst_v4ljpegsrc_get (GstPad * pad) { GstV4lJpegSrc *v4ljpegsrc; GstV4lSrc *v4lsrc; GstData *data; GstBuffer *buf; GstBuffer *outbuf; int jpeg_size; g_return_val_if_fail (pad != NULL, NULL); v4ljpegsrc = GST_V4LJPEGSRC (gst_pad_get_parent (pad)); v4lsrc = GST_V4LSRC (v4ljpegsrc); /* Fetch from the v4lsrc class get fn. */ data = v4ljpegsrc->getfn (pad); /* If not a buffer, return it unchanged */ if (!data || (!GST_IS_BUFFER (data))) return data; buf = GST_BUFFER (data); /* Confirm that the buffer contains jpeg data */ /* * Create a new subbuffer from the jpeg data * The first 2 bytes in the buffer are the size of the jpeg data */ if (GST_BUFFER_SIZE (buf) > 2) { jpeg_size = (int) (GST_READ_UINT16_LE (GST_BUFFER_DATA (buf))) * 8; } else jpeg_size = 0; /* Check that the size is sensible */ if ((jpeg_size <= 0) || (jpeg_size > GST_BUFFER_SIZE (buf) - 2)) { GST_ELEMENT_ERROR (v4ljpegsrc, STREAM, FORMAT, (NULL), ("Invalid non-jpeg frame from camera")); return NULL; } GST_DEBUG_OBJECT (v4ljpegsrc, "Creating JPEG subbuffer of size %d", jpeg_size); outbuf = gst_buffer_create_sub (buf, 2, jpeg_size); /* Copy timestamps onto the subbuffer */ gst_buffer_stamp (outbuf, buf); /* Release the main buffer */ gst_buffer_unref (buf); return GST_DATA (outbuf); }
static void gst_rfc2250_enc_add_slice (GstRFC2250Enc * enc, GstBuffer * buffer) { gint slice_length = GST_BUFFER_SIZE (buffer); /* see if the slice fits in the current buffer */ if (slice_length <= enc->remaining) { GstBuffer *newbuf; newbuf = gst_buffer_merge (enc->packet, buffer); gst_buffer_unref (buffer); gst_buffer_unref (enc->packet); enc->packet = newbuf; enc->remaining -= slice_length; } /* it doesn't fit */ else { /* do we need to start a new packet? */ if (slice_length <= enc->MTU) { GstBuffer *newbuf; gst_rfc2250_enc_new_buffer (enc); newbuf = gst_buffer_merge (enc->packet, buffer); gst_buffer_unref (buffer); gst_buffer_unref (enc->packet); enc->packet = newbuf; enc->remaining -= slice_length; } /* else we have to fragment */ else { gint offset = 0; while (slice_length > 0) { GstBuffer *outbuf; GstBuffer *newbuf; outbuf = gst_buffer_create_sub (buffer, offset, MIN (enc->remaining, slice_length)); newbuf = gst_buffer_merge (enc->packet, outbuf); slice_length -= GST_BUFFER_SIZE (outbuf); offset += GST_BUFFER_SIZE (outbuf); gst_buffer_unref (outbuf); gst_buffer_unref (newbuf); enc->packet = newbuf; gst_rfc2250_enc_new_buffer (enc); } gst_buffer_unref (buffer); } } }
/* FIXME: use version from gstcdxastrip.c */ static GstBuffer * gst_cdxa_parse_strip (GstBuffer * buf) { GstBuffer *sub; g_assert (GST_BUFFER_SIZE (buf) >= GST_CDXA_SECTOR_SIZE); /* Skip CDXA headers, only keep data. * FIXME: check sync, resync, ... */ sub = gst_buffer_create_sub (buf, GST_CDXA_HEADER_SIZE, GST_CDXA_DATA_SIZE); gst_buffer_unref (buf); return sub; }
static GstFlowReturn gst_video_rate_prepare_output_buffer (GstBaseTransform * trans, GstBuffer * input, gint size, GstCaps * caps, GstBuffer ** buf) { if (gst_buffer_is_metadata_writable (input)) { gst_buffer_set_caps (input, caps); *buf = gst_buffer_ref (input); } else { *buf = gst_buffer_create_sub (input, 0, GST_BUFFER_SIZE (input)); gst_buffer_set_caps (*buf, caps); } return GST_FLOW_OK; }
GstBuffer * gst_rdt_packet_to_buffer (GstRDTPacket * packet) { GstBuffer *result; g_return_val_if_fail (packet != NULL, NULL); g_return_val_if_fail (packet->type != GST_RDT_TYPE_INVALID, NULL); result = gst_buffer_create_sub (packet->buffer, packet->offset, packet->length); /* timestamp applies to all packets in this buffer */ GST_BUFFER_TIMESTAMP (result) = GST_BUFFER_TIMESTAMP (packet->buffer); return result; }
/** * gst_buffer_make_metadata_writable: * @buf: a #GstBuffer * * Similar to gst_buffer_make_writable, but does not ensure that the buffer * data array is writable. Instead, this just ensures that the returned buffer * is solely owned by the caller, by creating a subbuffer of the original * buffer if necessary. * * After calling this function, @buf should not be referenced anymore. The * result of this function has guaranteed writable metadata. * * Returns: A new #GstBuffer with writable metadata. */ GstBuffer * gst_buffer_make_metadata_writable (GstBuffer * buf) { GstBuffer *ret; if (gst_buffer_is_metadata_writable (buf)) { ret = buf; } else { ret = gst_buffer_create_sub (buf, 0, GST_BUFFER_SIZE (buf)); gst_buffer_unref (buf); } return ret; }
static GstBuffer * asf_packet_create_payload_buffer (AsfPacket * packet, const guint8 ** p_data, guint * p_size, guint payload_len) { guint off; g_assert (payload_len <= *p_size); off = (guint) (*p_data - GST_BUFFER_DATA (packet->buf)); g_assert (off < GST_BUFFER_SIZE (packet->buf)); *p_data += payload_len; *p_size -= payload_len; return gst_buffer_create_sub (packet->buf, off, payload_len); }
static GstBuffer * buffer_head(AudioTrim *filter, GstBuffer *buf, gint64 pos) { GstBuffer *head; guint end; if (pos <= GST_BUFFER_OFFSET(buf)) return NULL; if (pos >= GST_BUFFER_OFFSET_END(buf)) return gst_buffer_ref(buf); end = (pos - GST_BUFFER_OFFSET(buf)) * sizeof(gfloat); g_assert(end < GST_BUFFER_SIZE(buf)); head = gst_buffer_create_sub(buf, 0, end); copy_caps(buf, head); GST_BUFFER_DURATION(head) = sample_to_time(filter, pos - GST_BUFFER_OFFSET(buf)); GST_BUFFER_OFFSET_END(head) = pos; return head; }
static GstBuffer * gst_fake_src_create_buffer (GstFakeSrc * src) { GstBuffer *buf; guint size; gboolean dump = src->dump; size = gst_fake_src_get_size (src); if (size == 0) return gst_buffer_new (); switch (src->data) { case FAKE_SRC_DATA_ALLOCATE: buf = gst_fake_src_alloc_buffer (src, size); break; case FAKE_SRC_DATA_SUBBUFFER: /* see if we have a parent to subbuffer */ if (!src->parent) { gst_fake_src_alloc_parent (src); g_assert (src->parent); } /* see if it's large enough */ if ((GST_BUFFER_SIZE (src->parent) - src->parentoffset) >= size) { buf = gst_buffer_create_sub (src->parent, src->parentoffset, size); src->parentoffset += size; } else { /* the parent is useless now */ gst_buffer_unref (src->parent); src->parent = NULL; /* try again (this will allocate a new parent) */ return gst_fake_src_create_buffer (src); } gst_fake_src_prepare_buffer (src, buf); break; default: g_warning ("fakesrc: dunno how to allocate buffers !"); buf = gst_buffer_new (); break; } if (dump) { gst_util_dump_mem (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); } return buf; }
/* generate audio data and advance internal timers */ static GstBuffer * gst_timidity_fill_buffer (GstTimidity * timidity, GstBuffer * buffer) { size_t bytes_read; gint64 samples; bytes_read = mid_song_read_wave (timidity->song, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); if (bytes_read == 0) { gst_buffer_unref (buffer); return NULL; } GST_BUFFER_OFFSET (buffer) = timidity->o_segment->last_stop * timidity->bytes_per_frame; GST_BUFFER_TIMESTAMP (buffer) = timidity->o_segment->last_stop * timidity->time_per_frame; if (bytes_read < GST_BUFFER_SIZE (buffer)) { GstBuffer *old = buffer; buffer = gst_buffer_create_sub (buffer, 0, bytes_read); gst_buffer_unref (old); } samples = GST_BUFFER_SIZE (buffer) / timidity->bytes_per_frame; timidity->o_segment->last_stop += samples; GST_BUFFER_OFFSET_END (buffer) = timidity->o_segment->last_stop * timidity->bytes_per_frame; GST_BUFFER_DURATION (buffer) = samples * timidity->time_per_frame; GST_DEBUG_OBJECT (timidity, "generated buffer %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT " (%" G_GINT64_FORMAT " samples)", GST_TIME_ARGS ((guint64) GST_BUFFER_TIMESTAMP (buffer)), GST_TIME_ARGS (((guint64) (GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer)))), samples); return buffer; }
static GstBuffer * buffer_tail(AudioTrim *filter, GstBuffer *buf, gint64 pos) { GstBuffer *head; guint start; if (pos >= GST_BUFFER_OFFSET_END(buf)) return NULL; if (pos <= GST_BUFFER_OFFSET(buf)) return gst_buffer_ref(buf); start = (pos - GST_BUFFER_OFFSET(buf)) * sizeof(gfloat); g_assert(start < GST_BUFFER_SIZE(buf)); head = gst_buffer_create_sub(buf, start, GST_BUFFER_SIZE(buf) - start); copy_caps(buf, head); GST_BUFFER_TIMESTAMP(head) = sample_to_time(filter, pos); GST_BUFFER_OFFSET(head) = pos; GST_BUFFER_DURATION(head) = sample_to_time(filter, GST_BUFFER_OFFSET_END(buf) - pos); GST_BUFFER_OFFSET_END(head) = GST_BUFFER_OFFSET_END(buf); return head; }
static GstBuffer * gst_wildmidi_clip_buffer (GstWildmidi * wildmidi, GstBuffer * buffer) { gint64 start, stop; gint64 new_start, new_stop; gint64 offset, length; GstBuffer *out; guint64 bpf; /* clipping disabled for now */ return buffer; start = GST_BUFFER_OFFSET (buffer); stop = GST_BUFFER_OFFSET_END (buffer); if (!gst_segment_clip (wildmidi->o_segment, GST_FORMAT_DEFAULT, start, stop, &new_start, &new_stop)) { gst_buffer_unref (buffer); return NULL; } if (start == new_start && stop == new_stop) return buffer; offset = new_start - start; length = new_stop - new_start; bpf = wildmidi->bytes_per_frame; out = gst_buffer_create_sub (buffer, offset * bpf, length * bpf); GST_BUFFER_OFFSET (out) = new_start; GST_BUFFER_OFFSET_END (out) = new_stop; GST_BUFFER_TIMESTAMP (out) = gst_util_uint64_scale_int (new_start, GST_SECOND, WILDMIDI_RATE); GST_BUFFER_DURATION (out) = gst_util_uint64_scale_int (new_stop, GST_SECOND, WILDMIDI_RATE) - GST_BUFFER_TIMESTAMP (out); gst_buffer_unref (buffer); return out; }
static GstBuffer * gst_file_src_map_small_region (GstFileSrc * src, off_t offset, gsize size) { GstBuffer *ret; off_t mod; guint pagesize; GST_LOG_OBJECT (src, "attempting to map a small buffer at %" G_GUINT64_FORMAT "+%d", (guint64) offset, (gint) size); pagesize = src->pagesize; mod = offset % pagesize; /* if the offset starts at a non-page boundary, we have to special case */ if (mod != 0) { gsize mapsize; off_t mapbase; GstBuffer *map; mapbase = offset - mod; mapsize = ((size + mod + pagesize - 1) / pagesize) * pagesize; GST_LOG_OBJECT (src, "not on page boundaries, resizing to map to %" G_GUINT64_FORMAT "+%d", (guint64) mapbase, (gint) mapsize); map = gst_file_src_map_region (src, mapbase, mapsize, FALSE); if (map == NULL) return NULL; ret = gst_buffer_create_sub (map, offset - mapbase, size); GST_BUFFER_OFFSET (ret) = GST_BUFFER_OFFSET (map) + offset - mapbase; gst_buffer_unref (map); } else { ret = gst_file_src_map_region (src, offset, size, FALSE); } return ret; }
/** * gst_collect_pads_read_buffer: * @pads: the collectspads to query * @data: the data to use * @size: the number of bytes to read * * Get a buffer of @size bytes from the given pad @data. * * This function should be called with @pads LOCK held, such as in the callback. * * Since: 0.10.18 * * Returns: A #GstBuffer. The size of the buffer can be less that requested. * A return of NULL signals that the pad is end-of-stream. * Unref the buffer after use. * * MT safe. */ GstBuffer * gst_collect_pads_read_buffer (GstCollectPads * pads, GstCollectData * data, guint size) { guint readsize, bufsize; GstBuffer *buffer; g_return_val_if_fail (pads != NULL, NULL); g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), NULL); g_return_val_if_fail (data != NULL, NULL); /* no buffer, must be EOS */ if ((buffer = data->buffer) == NULL) return NULL; bufsize = GST_BUFFER_SIZE (buffer); readsize = MIN (size, bufsize - data->pos); if (data->pos == 0 && readsize == bufsize) return gst_buffer_ref (buffer); else return gst_buffer_create_sub (buffer, data->pos, readsize); }
static GstVaapiDecoderStatus decode_buffer(GstVaapiDecoderVC1 *decoder, GstBuffer *buffer) { GstVaapiDecoderVC1Private * const priv = decoder->priv; GstVaapiDecoderStatus status; GstVC1ParserResult result; GstVC1BDU ebdu; GstBuffer *codec_data; guchar *buf; guint buf_size, ofs; buf = GST_BUFFER_DATA(buffer); buf_size = GST_BUFFER_SIZE(buffer); if (!buf && buf_size == 0) return decode_sequence_end(decoder); gst_buffer_ref(buffer); gst_adapter_push(priv->adapter, buffer); /* Assume demuxer sends out plain frames if codec-data */ codec_data = GST_VAAPI_DECODER_CODEC_DATA(decoder); if (codec_data && codec_data != buffer) { ebdu.type = GST_VC1_FRAME; ebdu.size = buf_size; ebdu.sc_offset = 0; ebdu.offset = 0; ebdu.data = buf; status = decode_ebdu(decoder, &ebdu); if (gst_adapter_available(priv->adapter) >= buf_size) gst_adapter_flush(priv->adapter, buf_size); return status; } if (priv->sub_buffer) { buffer = gst_buffer_merge(priv->sub_buffer, buffer); if (!buffer) return GST_VAAPI_DECODER_STATUS_ERROR_ALLOCATION_FAILED; gst_buffer_unref(priv->sub_buffer); priv->sub_buffer = NULL; } buf = GST_BUFFER_DATA(buffer); buf_size = GST_BUFFER_SIZE(buffer); ofs = 0; do { result = gst_vc1_identify_next_bdu( buf + ofs, buf_size - ofs, &ebdu ); status = get_status(result); if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA) { priv->sub_buffer = gst_buffer_create_sub(buffer, ofs, buf_size - ofs); break; } if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) break; ofs += ebdu.offset + ebdu.size; if (gst_adapter_available(priv->adapter) >= ebdu.offset) gst_adapter_flush(priv->adapter, ebdu.offset); status = decode_ebdu(decoder, &ebdu); if (gst_adapter_available(priv->adapter) >= ebdu.size) gst_adapter_flush(priv->adapter, ebdu.size); } while (status == GST_VAAPI_DECODER_STATUS_SUCCESS); return status; }
static GstFlowReturn gst_icydemux_chain (GstPad * pad, GstBuffer * buf) { GstICYDemux *icydemux; guint size, chunk, offset; GstBuffer *sub; GstFlowReturn ret = GST_FLOW_OK; icydemux = GST_ICYDEMUX (GST_PAD_PARENT (pad)); if (G_UNLIKELY (icydemux->meta_interval < 0)) goto not_negotiated; if (icydemux->meta_interval == 0) { ret = gst_icydemux_typefind_or_forward (icydemux, buf); goto done; } /* Go through the buffer, chopping it into appropriate chunks. Forward as * tags or buffers, as appropriate */ size = GST_BUFFER_SIZE (buf); offset = 0; while (size) { if (icydemux->remaining) { chunk = (size <= icydemux->remaining) ? size : icydemux->remaining; if (offset == 0 && chunk == size) { sub = buf; buf = NULL; } else { sub = gst_buffer_create_sub (buf, offset, chunk); } offset += chunk; icydemux->remaining -= chunk; size -= chunk; /* This buffer goes onto typefinding, and/or directly pushed out */ ret = gst_icydemux_typefind_or_forward (icydemux, sub); if (ret != GST_FLOW_OK) goto done; } else if (icydemux->meta_remaining) { chunk = (size <= icydemux->meta_remaining) ? size : icydemux->meta_remaining; sub = gst_buffer_create_sub (buf, offset, chunk); gst_icydemux_add_meta (icydemux, sub); offset += chunk; icydemux->meta_remaining -= chunk; size -= chunk; if (icydemux->meta_remaining == 0) { /* Parse tags from meta_adapter, send off as tag messages */ GST_DEBUG_OBJECT (icydemux, "No remaining metadata, parsing for tags"); gst_icydemux_parse_and_send_tags (icydemux); icydemux->remaining = icydemux->meta_interval; } } else { /* We need to read a single byte (always safe at this point in the loop) * to figure out how many bytes of metadata exist. * The 'spec' tells us to read 16 * (byte_value) bytes of metadata after * this (zero is common, and means the metadata hasn't changed). */ icydemux->meta_remaining = 16 * GST_BUFFER_DATA (buf)[offset]; if (icydemux->meta_remaining == 0) icydemux->remaining = icydemux->meta_interval; offset += 1; size -= 1; } } done: if (buf) gst_buffer_unref (buf); return ret; /* ERRORS */ not_negotiated: { GST_WARNING_OBJECT (icydemux, "meta_interval not set, buffer probably had " "no caps set. Try enabling iradio-mode on the http source element"); gst_buffer_unref (buf); return GST_FLOW_NOT_NEGOTIATED; } }
static GstFlowReturn gst_file_src_create_mmap (GstFileSrc * src, guint64 offset, guint length, GstBuffer ** buffer) { GstBuffer *buf = NULL; gsize readsize, mapsize; off_t readend, mapstart, mapend; int i; /* calculate end pointers so we don't have to do so repeatedly later */ readsize = length; readend = offset + readsize; /* note this is the byte *after* the read */ mapstart = GST_BUFFER_OFFSET (src->mapbuf); mapsize = GST_BUFFER_SIZE (src->mapbuf); mapend = mapstart + mapsize; /* note this is the byte *after* the map */ GST_LOG ("attempting to read %08lx, %08lx, %08lx, %08lx", (unsigned long) readsize, (unsigned long) readend, (unsigned long) mapstart, (unsigned long) mapend); /* if the start is past the mapstart */ if (offset >= mapstart) { /* if the end is before the mapend, the buffer is in current mmap region... */ /* ('cause by definition if readend is in the buffer, so's readstart) */ if (readend <= mapend) { GST_LOG_OBJECT (src, "read buf %" G_GUINT64_FORMAT "+%u lives in " "current mapbuf %u+%u, creating subbuffer of mapbuf", offset, (guint) readsize, (guint) mapstart, (guint) mapsize); buf = gst_buffer_create_sub (src->mapbuf, offset - mapstart, readsize); GST_BUFFER_OFFSET (buf) = offset; /* if the start actually is within the current mmap region, map an overlap buffer */ } else if (offset < mapend) { GST_LOG_OBJECT (src, "read buf %" G_GUINT64_FORMAT "+%u starts in " "mapbuf %u+%u but ends outside, creating new mmap", offset, (guint) readsize, (guint) mapstart, (guint) mapsize); buf = gst_file_src_map_small_region (src, offset, readsize); if (buf == NULL) goto could_not_mmap; } /* the only other option is that buffer is totally outside, which means we search for it */ /* now we can assume that the start is *before* the current mmap region */ /* if the readend is past mapstart, we have two options */ } else if (readend >= mapstart) { /* either the read buffer overlaps the start of the mmap region */ /* or the read buffer fully contains the current mmap region */ /* either way, it's really not relevant, we just create a new region anyway */ GST_LOG_OBJECT (src, "read buf %" G_GUINT64_FORMAT "+%d starts before " "mapbuf %d+%d, but overlaps it", (guint64) offset, (gint) readsize, (gint) mapstart, (gint) mapsize); buf = gst_file_src_map_small_region (src, offset, readsize); if (buf == NULL) goto could_not_mmap; } /* then deal with the case where the read buffer is totally outside */ if (buf == NULL) { /* first check to see if there's a map that covers the right region already */ GST_LOG_OBJECT (src, "searching for mapbuf to cover %" G_GUINT64_FORMAT "+%d", offset, (int) readsize); /* if the read buffer crosses a mmap region boundary, create a one-off region */ if ((offset / src->mapsize) != (readend / src->mapsize)) { GST_LOG_OBJECT (src, "read buf %" G_GUINT64_FORMAT "+%d crosses a " "%d-byte boundary, creating a one-off", offset, (int) readsize, (int) src->mapsize); buf = gst_file_src_map_small_region (src, offset, readsize); if (buf == NULL) goto could_not_mmap; /* otherwise we will create a new mmap region and set it to the default */ } else { gsize mapsize; off_t nextmap = offset - (offset % src->mapsize); GST_LOG_OBJECT (src, "read buf %" G_GUINT64_FORMAT "+%d in new mapbuf " "at %" G_GUINT64_FORMAT "+%d, mapping and subbuffering", offset, (gint) readsize, (guint64) nextmap, (gint) src->mapsize); /* first, we're done with the old mapbuf */ gst_buffer_unref (src->mapbuf); mapsize = src->mapsize; /* double the mapsize as long as the readsize is smaller */ while (readsize + offset > nextmap + mapsize) { GST_LOG_OBJECT (src, "readsize smaller then mapsize %08x %d", (guint) readsize, (gint) mapsize); mapsize <<= 1; } /* create a new one */ src->mapbuf = gst_file_src_map_region (src, nextmap, mapsize, FALSE); if (src->mapbuf == NULL) goto could_not_mmap; /* subbuffer it */ buf = gst_buffer_create_sub (src->mapbuf, offset - nextmap, readsize); GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET (src->mapbuf) + offset - nextmap; } } /* if we need to touch the buffer (to bring it into memory), do so */ if (src->touch) { volatile guchar *p = GST_BUFFER_DATA (buf); /* read first byte of each page */ for (i = 0; i < GST_BUFFER_SIZE (buf); i += src->pagesize) (void) p[i]; } /* we're done, return the buffer */ *buffer = buf; return GST_FLOW_OK; /* ERROR */ could_not_mmap: { return GST_FLOW_ERROR; } }
static gboolean gst_ogg_avi_parse_setcaps (GstPad * pad, GstCaps * caps) { GstOggAviParse *ogg; GstStructure *structure; const GValue *codec_data; GstBuffer *buffer; guint8 *data; guint size; guint32 sizes[3]; GstCaps *outcaps; gint i, offs; ogg = GST_OGG_AVI_PARSE (GST_OBJECT_PARENT (pad)); structure = gst_caps_get_structure (caps, 0); /* take codec data */ codec_data = gst_structure_get_value (structure, "codec_data"); if (codec_data == NULL) goto no_data; /* only buffers are valid */ if (G_VALUE_TYPE (codec_data) != GST_TYPE_BUFFER) goto wrong_format; /* Now parse the data */ buffer = gst_value_get_buffer (codec_data); /* first 22 bytes are bits_per_sample, channel_mask, GUID * Then we get 3 LE guint32 with the 3 header sizes * then we get the bytes of the 3 headers. */ data = GST_BUFFER_DATA (buffer); size = GST_BUFFER_SIZE (buffer); GST_LOG_OBJECT (ogg, "configuring codec_data of size %u", size); /* skip headers */ data += 22; size -= 22; /* we need at least 12 bytes for the packet sizes of the 3 headers */ if (size < 12) goto buffer_too_small; /* read sizes of the 3 headers */ sizes[0] = GST_READ_UINT32_LE (data); sizes[1] = GST_READ_UINT32_LE (data + 4); sizes[2] = GST_READ_UINT32_LE (data + 8); GST_DEBUG_OBJECT (ogg, "header sizes: %u %u %u", sizes[0], sizes[1], sizes[2]); data += 12; size -= 12; /* and we need at least enough data for all the headers */ if (size < sizes[0] + sizes[1] + sizes[2]) goto buffer_too_small; /* set caps */ outcaps = gst_caps_new_simple ("audio/x-vorbis", NULL); gst_pad_set_caps (ogg->srcpad, outcaps); /* copy header data */ offs = 34; for (i = 0; i < 3; i++) { GstBuffer *out; /* now output the raw vorbis header packets */ out = gst_buffer_create_sub (buffer, offs, sizes[i]); gst_buffer_set_caps (out, outcaps); gst_pad_push (ogg->srcpad, out); offs += sizes[i]; } gst_caps_unref (outcaps); return TRUE; /* ERRORS */ no_data: { GST_DEBUG_OBJECT (ogg, "no codec_data found in caps"); return FALSE; } wrong_format: { GST_DEBUG_OBJECT (ogg, "codec_data is not a buffer"); return FALSE; } buffer_too_small: { GST_DEBUG_OBJECT (ogg, "codec_data is too small"); return FALSE; } }
static GstBuffer * gst_avi_subtitle_extract_file (GstAviSubtitle * sub, GstBuffer * buffer, guint offset, guint len) { const gchar *input_enc = NULL; GstBuffer *ret = NULL; gchar *data; data = (gchar *) GST_BUFFER_DATA (buffer) + offset; if (len >= (3 + 1) && IS_BOM_UTF8 (data) && g_utf8_validate (data + 3, len - 3, NULL)) { ret = gst_buffer_create_sub (buffer, offset + 3, len - 3); } else if (len >= 2 && IS_BOM_UTF16_BE (data)) { input_enc = "UTF-16BE"; data += 2; len -= 2; } else if (len >= 2 && IS_BOM_UTF16_LE (data)) { input_enc = "UTF-16LE"; data += 2; len -= 2; } else if (len >= 4 && IS_BOM_UTF32_BE (data)) { input_enc = "UTF-32BE"; data += 4; len -= 4; } else if (len >= 4 && IS_BOM_UTF32_LE (data)) { input_enc = "UTF-32LE"; data += 4; len -= 4; } else if (g_utf8_validate (data, len, NULL)) { /* not specified, check if it's UTF-8 */ ret = gst_buffer_create_sub (buffer, offset, len); } else { /* we could fall back to gst_tag_freeform_to_utf8() here */ GST_WARNING_OBJECT (sub, "unspecified encoding, and not UTF-8"); return NULL; } g_return_val_if_fail (ret != NULL || input_enc != NULL, NULL); if (input_enc) { GError *err = NULL; gchar *utf8; GST_DEBUG_OBJECT (sub, "converting subtitles from %s to UTF-8", input_enc); utf8 = g_convert (data, len, "UTF-8", input_enc, NULL, NULL, &err); if (err != NULL) { GST_WARNING_OBJECT (sub, "conversion to UTF-8 failed : %s", err->message); g_error_free (err); return NULL; } ret = gst_buffer_new (); GST_BUFFER_DATA (ret) = (guint8 *) utf8; GST_BUFFER_MALLOCDATA (ret) = (guint8 *) utf8; GST_BUFFER_SIZE (ret) = strlen (utf8); GST_BUFFER_OFFSET (ret) = 0; } GST_BUFFER_CAPS (ret) = gst_caps_new_simple ("application/x-subtitle", NULL); return ret; }