/** * gst_adapter_push: * @adapter: a #GstAdapter * @buf: (transfer full): a #GstBuffer to add to queue in the adapter * * Adds the data from @buf to the data stored inside @adapter and takes * ownership of the buffer. */ void gst_adapter_push (GstAdapter * adapter, GstBuffer * buf) { gsize size; g_return_if_fail (GST_IS_ADAPTER (adapter)); g_return_if_fail (GST_IS_BUFFER (buf)); size = gst_buffer_get_size (buf); adapter->size += size; /* Note: merging buffers at this point is premature. */ if (G_UNLIKELY (adapter->buflist == NULL)) { GST_LOG_OBJECT (adapter, "pushing %p first %" G_GSIZE_FORMAT " bytes", buf, size); adapter->buflist = adapter->buflist_end = g_slist_append (NULL, buf); update_timestamps (adapter, buf); } else { /* Otherwise append to the end, and advance our end pointer */ GST_LOG_OBJECT (adapter, "pushing %p %" G_GSIZE_FORMAT " bytes at end, " "size now %" G_GSIZE_FORMAT, buf, size, adapter->size); adapter->buflist_end = g_slist_append (adapter->buflist_end, buf); adapter->buflist_end = g_slist_next (adapter->buflist_end); } }
/*Flushes the first @flush bytes in the @adapter*/ static void gst_adapter_flush_unchecked (GstAdapter * adapter, gsize flush) { GstBuffer *cur; gsize size; GSList *g; GST_LOG_OBJECT (adapter, "flushing %" G_GSIZE_FORMAT " bytes", flush); if (adapter->info.memory) gst_adapter_unmap (adapter); /* clear state */ adapter->size -= flush; adapter->assembled_len = 0; /* take skip into account */ flush += adapter->skip; /* distance is always at least the amount of skipped bytes */ adapter->pts_distance -= adapter->skip; adapter->dts_distance -= adapter->skip; g = adapter->buflist; cur = g->data; size = gst_buffer_get_size (cur); while (flush >= size) { /* can skip whole buffer */ GST_LOG_OBJECT (adapter, "flushing out head buffer"); adapter->pts_distance += size; adapter->dts_distance += size; flush -= size; gst_buffer_unref (cur); g = g_slist_delete_link (g, g); --adapter->count; if (G_UNLIKELY (g == NULL)) { GST_LOG_OBJECT (adapter, "adapter empty now"); adapter->buflist_end = NULL; break; } /* there is a new head buffer, update the timestamps */ cur = g->data; update_timestamps (adapter, cur); size = gst_buffer_get_size (cur); } adapter->buflist = g; /* account for the remaining bytes */ adapter->skip = flush; adapter->pts_distance += flush; adapter->dts_distance += flush; /* invalidate scan position */ adapter->scan_offset = 0; adapter->scan_entry = NULL; }
static GstFlowReturn gst_dvdlpcmdec_chain_raw (GstPad * pad, GstBuffer * buf) { GstDvdLpcmDec *dvdlpcmdec; guint8 *data; guint size; GstFlowReturn ret; guint samples = 0; dvdlpcmdec = GST_DVDLPCMDEC (gst_pad_get_parent (pad)); size = GST_BUFFER_SIZE (buf); data = GST_BUFFER_DATA (buf); GST_LOG_OBJECT (dvdlpcmdec, "got buffer %p of size %d with ts %" GST_TIME_FORMAT, buf, size, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); if (dvdlpcmdec->rate == 0) goto not_negotiated; if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) dvdlpcmdec->timestamp = GST_BUFFER_TIMESTAMP (buf); /* We don't currently do anything at all regarding emphasis, mute or * dynamic_range - I'm not sure what they're for */ switch (dvdlpcmdec->width) { case 16: { /* We can just pass 16-bits straight through intact, once we set * appropriate things on the buffer */ samples = size / dvdlpcmdec->channels / 2; if (samples < 1) goto drop; buf = gst_buffer_make_metadata_writable (buf); break; } case 20: { /* Allocate a new buffer and copy 20-bit width to 24-bit */ gint64 samples = size * 8 / 20; gint64 count = size / 10; gint64 i; guint8 *src; guint8 *dest; GstBuffer *outbuf; GstCaps *bufcaps = GST_PAD_CAPS (dvdlpcmdec->srcpad); if (samples < 1) goto drop; ret = gst_pad_alloc_buffer_and_set_caps (dvdlpcmdec->srcpad, 0, samples * 3, bufcaps, &outbuf); if (ret != GST_FLOW_OK) goto buffer_alloc_failed; gst_buffer_copy_metadata (outbuf, buf, GST_BUFFER_COPY_TIMESTAMPS); /* adjust samples so we can calc the new timestamp */ samples = samples / dvdlpcmdec->channels; src = data; dest = GST_BUFFER_DATA (outbuf); /* Copy 20-bit LPCM format to 24-bit buffers, with 0x00 in the lowest * nibble. Note that the first 2 bytes are already correct */ for (i = 0; i < count; i++) { dest[0] = src[0]; dest[1] = src[1]; dest[2] = src[8] & 0xf0; dest[3] = src[2]; dest[4] = src[3]; dest[5] = (src[8] & 0x0f) << 4; dest[6] = src[4]; dest[7] = src[5]; dest[8] = src[9] & 0x0f; dest[9] = src[6]; dest[10] = src[7]; dest[11] = (src[9] & 0x0f) << 4; src += 10; dest += 12; } gst_buffer_unref (buf); buf = outbuf; break; } case 24: { /* Rearrange 24-bit LPCM format in-place. Note that the first 2 * and last byte are already correct */ guint count = size / 12; gint i; guint8 *src; samples = size / dvdlpcmdec->channels / 3; if (samples < 1) goto drop; /* Ensure our output buffer is writable */ buf = gst_buffer_make_writable (buf); src = GST_BUFFER_DATA (buf); for (i = 0; i < count; i++) { guint8 tmp; tmp = src[10]; src[10] = src[7]; src[7] = src[5]; src[5] = src[9]; src[9] = src[6]; src[6] = src[4]; src[4] = src[3]; src[3] = src[2]; src[2] = src[8]; src[8] = tmp; src += 12; } break; } default: goto invalid_width; } /* Set appropriate caps on it to pass downstream */ gst_buffer_set_caps (buf, GST_PAD_CAPS (dvdlpcmdec->srcpad)); update_timestamps (dvdlpcmdec, buf, samples); ret = gst_pad_push (dvdlpcmdec->srcpad, buf); done: gst_object_unref (dvdlpcmdec); return ret; /* ERRORS */ drop: { GST_DEBUG_OBJECT (dvdlpcmdec, "Buffer of size %u is too small. Dropping", GST_BUFFER_SIZE (buf)); gst_buffer_unref (buf); ret = GST_FLOW_OK; goto done; } not_negotiated: { GST_ELEMENT_ERROR (dvdlpcmdec, STREAM, FORMAT, (NULL), ("Buffer pushed before negotiation")); gst_buffer_unref (buf); ret = GST_FLOW_NOT_NEGOTIATED; goto done; } buffer_alloc_failed: { GST_ELEMENT_ERROR (dvdlpcmdec, RESOURCE, FAILED, (NULL), ("Buffer allocation failed")); gst_buffer_unref (buf); goto done; } invalid_width: { GST_ELEMENT_ERROR (dvdlpcmdec, STREAM, WRONG_TYPE, (NULL), ("Invalid sample width configured")); gst_buffer_unref (buf); ret = GST_FLOW_NOT_NEGOTIATED; goto done; } }
int main (int argc, char **argv) { int opt, i, j, bufsize, retcode; int bitrate, invert, packets, packetsize, tssize, packetnum, bytes; unsigned char *data, *p; char *endptr; unsigned long long int timestamp, sum; bitrate = 0; invert = 0; packets = -1; /* Generate an infinite number of packets */ packetsize = 188; while ((opt = getopt (argc, argv, "b:hin:V2")) != -1) { switch (opt) { case 'b': bitrate = strtol (optarg, &endptr, 0); if ((*endptr != '\0') || (bitrate <= 0) || (bitrate > 216000000)) { fprintf (stderr, "%s: invalid bitrate: %s\n", argv[0], optarg); return -1; } break; case 'h': printf ("Usage: %s [OPTION]...\n", argv[0]); printf ("Repeatedly output null " "MPEG-2 transport stream packets\n" "with an ascending continuity_counter " "and a payload of 0xff.\n\n"); printf (" -b BITRATE\tprepend timestamps " "at BITRATE bits per second\n"); printf (" -h\t\tdisplay this help and exit\n"); printf (" -i\t\tinvert every eighth " "packet synchronization byte\n"); printf (" -n NUM\tstop after NUM packets\n"); printf (" -V\t\toutput version information " "and exit\n"); printf (" -2\t\tappend sixteen 0x00 bytes " "to each 188-byte packet\n"); printf ("\nReport bugs to <*****@*****.**>.\n"); return 0; case 'i': invert = 1; break; case 'n': packets = strtol (optarg, &endptr, 0); if (*endptr != '\0') { fprintf (stderr, "%s: invalid number of packets: %s\n", argv[0], optarg); return -1; } break; case 'V': printf ("%s from master-%s (%s)\n", progname, MASTER_DRIVER_VERSION, MASTER_DRIVER_DATE); printf ("\nCopyright (C) 2001-2006 " "Linear Systems Ltd.\n" "This is free software; " "see the source for copying conditions. " "There is NO\n" "warranty; not even for MERCHANTABILITY " "or FITNESS FOR A PARTICULAR PURPOSE.\n"); return 0; case '2': packetsize = 204; break; case '?': goto USAGE; } } /* Check the number of arguments */ if ((argc - optind) > 0) { fprintf (stderr, "%s: extra operand\n", argv[0]); goto USAGE; } /* Allocate a buffer */ tssize = (bitrate > 0) ? 8 : 0; bufsize = BUFFERED_PACKETS * (packetsize + tssize); if ((data = (unsigned char *)malloc (bufsize)) == NULL) { fprintf (stderr, "%s: unable to allocate memory\n", argv[0]); return -1; } /* Initialize the buffer */ p = data; packetnum = 0; for (i = 0; i < BUFFERED_PACKETS; i++) { if (bitrate > 0) { p += 8; } if (invert) { *p++ = (packetnum % 8) ? 0x47 : 0xB8; } else { *p++ = 0x47; } *p++ = 0x1f; *p++ = 0xff; *p++ = 0x10 | packetnum; packetnum = (packetnum + 1) & 0x0f; for (j = 4; j < 188; j++) { *p++ = 0xff; } for (j = 188; j < packetsize; j++) { *p++ = 0x00; } } timestamp = 0ULL; sum = 0ULL; if (bitrate > 0) { uint64_t *ts = (uint64_t *)data; update_timestamps (data, ×tamp, &sum, bitrate, packetsize); *ts |= UINT64_C(0x8000000000000000); } /* Generate the data */ while (packets) { bytes = 0; if ((packets < BUFFERED_PACKETS) && (packets > 0)) { /* The number of packets to write is less than * the buffer size and is not infinite (-1). */ while (bytes < (packets * (packetsize + tssize))) { if ((retcode = write (STDOUT_FILENO, data + bytes, (packets * (packetsize + tssize)) - bytes)) < 0) { fprintf (stderr, "%s: ", argv[0]); perror ("unable to write to output"); free (data); return -1; } bytes += retcode; } packets = 0; } else { /* The number of packets to write is greater than * or equal to the buffer size or is infinite (-1). */ while (bytes < bufsize) { if ((retcode = write (STDOUT_FILENO, data + bytes, bufsize - bytes)) < 0) { fprintf (stderr, "%s: ", argv[0]); perror ("unable to write to output"); free (data); return -1; } bytes += retcode; } if (packets > 0) { packets -= BUFFERED_PACKETS; } if (bitrate > 0) { update_timestamps (data, ×tamp, &sum, bitrate, packetsize); } } } free (data); return 0; USAGE: fprintf (stderr, "Try '%s -h' for more information.\n", argv[0]); return -1; }