<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <HTML ><HEAD ><TITLE >The Bytestream Object</TITLE ><META NAME="GENERATOR" CONTENT="Modular DocBook HTML Stylesheet Version 1.7"><LINK REL="HOME" TITLE="GStreamer Plugin Writer's Guide" HREF="index.html"><LINK REL="UP" TITLE="How a loopfunc works" HREF="chapter-loopbased-loopfn.html"><LINK REL="PREVIOUS" TITLE="How a loopfunc works" HREF="chapter-loopbased-loopfn.html"><LINK REL="NEXT" TITLE="Adding a second output" HREF="section-loopbased-secnd.html"></HEAD ><BODY CLASS="sect1" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#840084" ALINK="#0000FF" ><DIV CLASS="NAVHEADER" ><TABLE SUMMARY="Header navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TH COLSPAN="3" ALIGN="center" ><SPAN CLASS="application" >GStreamer</SPAN > Plugin Writer's Guide</TH ></TR ><TR ><TD WIDTH="10%" ALIGN="left" VALIGN="bottom" ><A HREF="chapter-loopbased-loopfn.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="80%" ALIGN="center" VALIGN="bottom" >Chapter 12. How a loopfunc works</TD ><TD WIDTH="10%" ALIGN="right" VALIGN="bottom" ><A HREF="section-loopbased-secnd.html" ACCESSKEY="N" >Next</A ></TD ></TR ></TABLE ><HR ALIGN="LEFT" WIDTH="100%"></DIV ><DIV CLASS="sect1" ><H1 CLASS="sect1" ><A NAME="section-loopfn-bytestream" >12.2. The Bytestream Object</A ></H1 ><P > A second type of elements that wants to be loop-based, are the so-called bytestream-elements. Until now, we've only dealt with elements that receive of pull full buffers of a random size from other elements. Often, however, it is wanted to have control over the stream at a byte-level, such as in stream parsers or demuxers. It is possible to manually pull buffers and merge them until a certain size; it is easier, however, to use bytestream, which wraps this behaviour. </P ><P > Bytestream-using elements are ususally stream parsers or demuxers. For now, we will take a parser as an example. Demuxers require some more magic that will be dealt with later in this guide: <A HREF="chapter-advanced-request.html" >Chapter 14</A >. The goal of this parser will be to parse a text-file and to push each line of text as a separate buffer over its source pad. </P ><PRE CLASS="programlisting" > static void gst_my_filter_loopfunc (GstElement *element) { GstMyFilter *filter = GST_MY_FILTER (element); gint n, num; guint8 *data; for (n = 0; ; n++) { num = gst_bytestream_peek_bytes (filter->bs, &data, n + 1); if (num != n + 1) { GstEvent *event = NULL; guint remaining; gst_bytestream_get_status (filter->bs, &remaining, &event); if (event) { if (GST_EVENT_TYPE (event) == GST_EVENT_EOS)) { /* end-of-file */ gst_pad_push (filter->srcpad, GST_DATA (event)); gst_element_set_eos (element); return; } gst_event_unref (event); } /* failed to read - throw error and bail out */ gst_element_error (element, STREAM, READ, (NULL), (NULL)); return; } /* check if the last character is a newline */ if (data[n] == '\n') { GstBuffer *buf = gst_buffer_new_and_alloc (n + 1); /* read the line of text without newline - then flush the newline */ gst_bytestream_peek_data (filter->bs, &data, n); memcpy (GST_BUFFER_DATA (buf), data, n); GST_BUFFER_DATA (buf)[n] = '\0'; gst_bytestream_flush_fast (filter->bs, n + 1); g_print ("Pushing '%s'\n", GST_BUFFER_DATA (buf)); gst_pad_push (filter->srcpad, GST_DATA (buf)); return; } } } static void gst_my_filter_change_state (GstElement *element) { GstMyFilter *filter = GST_MY_FILTER (element); switch (GST_STATE_TRANSITION (element)) { case GST_STATE_READY_TO_PAUSED: filter->bs = gst_bytestream_new (filter->sinkpad); break; case GST_STATE_PAUSED_TO_READY: gst_bytestream_destroy (filter->bs); break; default: break; } if (GST_ELEMENT_CLASS (parent_class)->change_state) return GST_ELEMENT_CLASS (parent_class)->change_state (element); return GST_STATE_SUCCESS; } </PRE ><P > In the above example, you'll notice how bytestream handles buffering of data for you. The result is that you can handle the same data multiple times. Event handling in bytestream is currently sort of <SPAN CLASS="emphasis" ><I CLASS="emphasis" >wacky</I ></SPAN >, but it works quite well. The one big disadvantage of bytestream is that it <SPAN CLASS="emphasis" ><I CLASS="emphasis" >requires</I ></SPAN > the element to be loop-based. Long-term, we hope to have a chain-based usable version of bytestream, too. </P ></DIV ><DIV CLASS="NAVFOOTER" ><HR ALIGN="LEFT" WIDTH="100%"><TABLE SUMMARY="Footer navigation table" WIDTH="100%" BORDER="0" CELLPADDING="0" CELLSPACING="0" ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" ><A HREF="chapter-loopbased-loopfn.html" ACCESSKEY="P" >Prev</A ></TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="index.html" ACCESSKEY="H" >Home</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" ><A HREF="section-loopbased-secnd.html" ACCESSKEY="N" >Next</A ></TD ></TR ><TR ><TD WIDTH="33%" ALIGN="left" VALIGN="top" >How a loopfunc works</TD ><TD WIDTH="34%" ALIGN="center" VALIGN="top" ><A HREF="chapter-loopbased-loopfn.html" ACCESSKEY="U" >Up</A ></TD ><TD WIDTH="33%" ALIGN="right" VALIGN="top" >Adding a second output</TD ></TR ></TABLE ></DIV ></BODY ></HTML >