Beispiel #1
0
        /* sync the stream and get a page.  Keep trying until we find a page.
         * Suppress 'sync errors' after reporting the first.
         *
         * return values:
         * -1) recapture (hole in data)
         * 0) need more data
         * 1) page returned
         *
         * Returns pointers into buffered data; invalidated by next call to
         * _stream, _clear, _init, or _buffer */

        static public int ogg_sync_pageout(ref ogg_sync_state oy, ref ogg_page og)
        {
            if (ogg_sync_check(ref oy) != 0)
            {
                return(0);
            }

            /* all we need to do is verify a page at the head of the stream
             * buffer.  If it doesn't verify, we look for the next potential
             * frame */

            for (;;)
            {
                int ret = ogg_sync_pageseek(ref oy, ref og);

                if (ret > 0)
                {
                    /* have a page */
                    return(1);
                }

                if (ret == 0)
                {
                    /* need more data */
                    return(0);
                }

                if (oy.unsynced == 0)
                {
                    oy.unsynced = 1;
                    return(-1);
                }
            }
        }
Beispiel #2
0
        /* checksum the page */
        /* Direct table CRC; note that this will be faster in the future if we perform the checksum simultaneously with other copies */
        static public void ogg_page_checksum_set(ref ogg_page og)
        {
            uint crc_reg = 0;

            /* safety; needed for API behavior, but not framing code */
            og.header[22] = 0;
            og.header[23] = 0;
            og.header[24] = 0;
            og.header[25] = 0;

            for (int i = 0; i < og.header_len; i++)
            {
                crc_reg = (crc_reg << 8) ^ crc_lookup[((crc_reg >> 24) & 0xff) ^ og.header[i]];
            }

            for (int i = 0; i < og.body_len; i++)
            {
                crc_reg = (crc_reg << 8) ^ crc_lookup[((crc_reg >> 24) & 0xff) ^ og.body[i]];
            }

            og.header[22] = (byte)(crc_reg & 0xff);
            og.header[23] = (byte)((crc_reg >> 8) & 0xff);
            og.header[24] = (byte)((crc_reg >> 16) & 0xff);
            og.header[25] = (byte)((crc_reg >> 24) & 0xff);
        }
Beispiel #3
0
 private void WritePage(ref ogg_page page, Stream stream)
 {
     byte[] headerData = ReadBuffer(page.header, page.header_len);
     byte[] bodyData   = ReadBuffer(page.body, page.body_len);
     stream.Write(headerData, 0, headerData.Length);
     stream.Write(bodyData, 0, bodyData.Length);
 }
Beispiel #4
0
        static public int ogg_page_packets(ref ogg_page og)
        {
            int n     = og.header[26];
            int count = 0;

            for (int i = 0; i < n; i++)
            {
                if (og.header[27 + i] < 255)
                {
                    count++;
                }
            }

            return(count);
        }
Beispiel #5
0
        /* Like the above, but an argument is provided to adjust the nominal page size for applications which are smart enough to provide their
         * own delay based flushing */

        static public int ogg_stream_pageout_fill(ref ogg_stream_state os, ref ogg_page og, int nfill)
        {
            int force = 0;

            if (ogg_stream_check(ref os) != 0)
            {
                return(0);
            }

            if ((os.e_o_s != 0 && os.lacing_fill != 0) || (os.lacing_fill != 0 && os.b_o_s == 0))
            {
                force = 1;
            }

            return(ogg_stream_flush_i(ref os, ref og, force, nfill));
        }
Beispiel #6
0
 public static extern int ogg_page_continued(ref ogg_page og);
Beispiel #7
0
 public static extern int ogg_page_version(ref ogg_page og);
Beispiel #8
0
 public static extern int ogg_stream_flush_fill(ref ogg_stream_state os, ref ogg_page og, int fillbytes);
Beispiel #9
0
 public static extern int ogg_stream_flush(ref ogg_stream_state os, ref ogg_page og);
Beispiel #10
0
 public static extern int ogg_sync_pageout(ref ogg_sync_state oy, ref ogg_page og);
Beispiel #11
0
 static public int ogg_page_continued(ref ogg_page og)
 {
     return((int)og.header[5] & 0x01);
 }
Beispiel #12
0
 public static extern int ogg_page_pageno(ref ogg_page og);
Beispiel #13
0
 public static extern long ogg_page_granulepos(ref ogg_page og);
Beispiel #14
0
 public static extern int ogg_page_packets(ref ogg_page og);
Beispiel #15
0
 static public int ogg_page_pageno(ref ogg_page og)
 {
     return(Marshal.ReadInt32((IntPtr)og.header, 18));
 }
Beispiel #16
0
        /* Like the above, but an argument is provided to adjust the nominal page size for applications which are smart enough to provide their
         * own delay based flushing */

        static public int ogg_stream_flush_fill(ref ogg_stream_state os, ref ogg_page og, int nfill)
        {
            return(ogg_stream_flush_i(ref os, ref og, 1, nfill));
        }
Beispiel #17
0
 static public long ogg_page_granulepos(ref ogg_page og)
 {
     return(Marshal.ReadInt64((IntPtr)og.header, 6));
 }
Beispiel #18
0
        /* This will flush remaining packets into a page (returning nonzero), even if there is not enough data to trigger a flush normally
         * (undersized page). If there are no packets or partial packets to flush, ogg_stream_flush returns 0.  Note that ogg_stream_flush will
         * try to flush a normal sized page like ogg_stream_pageout; a call to ogg_stream_flush does not guarantee that all packets have flushed.
         * Only a return value of 0 from ogg_stream_flush indicates all packet data is flushed into pages.
         *
         * since ogg_stream_flush will flush the last page in a stream even if it's undersized, you almost certainly want to use ogg_stream_pageout
         * (and *not* ogg_stream_flush) unless you specifically need to flush a page regardless of size in the middle of a stream. */

        static public int ogg_stream_flush(ref ogg_stream_state os, ref ogg_page og)
        {
            return(ogg_stream_flush_i(ref os, ref og, 1, 4096));
        }
Beispiel #19
0
 static public int ogg_page_eos(ref ogg_page og)
 {
     return((int)og.header[5] & 0x04);
 }
Beispiel #20
0
 public static extern int ogg_page_eos(ref ogg_page og);
Beispiel #21
0
        static public int ogg_sync_pageseek(ref ogg_sync_state oy, ref ogg_page og)
        {
            byte *page = oy.data + oy.returned;
            byte *next = null;

            int bytes = oy.fill - oy.returned;

            if (ogg_sync_check(ref oy) != 0)
            {
                return(0);
            }

            if (oy.headerbytes == 0)
            {
                int headerbytes;

                if (bytes < 27)
                {
                    return(0);
                }

                if
                (
                    page[0] != 'O' ||
                    page[1] != 'g' ||
                    page[2] != 'g' ||
                    page[3] != 'S'
                )
                {
                    goto sync_fail;
                }
                else
                {
                    headerbytes = page[26] + 27;

                    if (bytes < headerbytes)
                    {
                        return(0);
                    }

                    for (int i = 0; i < page[26]; i++)
                    {
                        oy.bodybytes += page[27 + i];
                    }

                    oy.headerbytes = headerbytes;
                }
            }

            if (oy.bodybytes + oy.headerbytes > bytes)
            {
                return(0);
            }

            /* The whole test page is buffered. Verify the checksum */
            {
                byte[] chksum = new byte[4];

                ogg_page log = new ogg_page();

                /* Grab the checksum bytes, set the header field to zero */
                Marshal.Copy((IntPtr)(page + 22), chksum, 0, 4);
                ZeroMemory(page + 22, 4);

                /* set up a temp page struct and recompute the checksum */
                log.header     = page;
                log.header_len = oy.headerbytes;
                log.body       = page + oy.headerbytes;
                log.body_len   = oy.bodybytes;

                ogg_page_checksum_set(ref log);

                /* Compare */
                if
                (
                    chksum[0] != page[22] ||
                    chksum[1] != page[23] ||
                    chksum[2] != page[24] ||
                    chksum[3] != page[25]
                )
                {
                    /* D'oh.  Mismatch! Corrupt page (or miscapture and not a page at all) */
                    /* replace the computed checksum with the one actually read in */
                    Marshal.Copy(chksum, 0, (IntPtr)(page + 22), 4);

                    /* Bad checksum. Lose sync */
                    goto sync_fail;
                }
            }

            /* yes, have a whole page all ready to go */
            {
                byte *_page = oy.data + oy.returned;

                bytes = oy.headerbytes + oy.bodybytes;

                if (og != null)
                {
                    og.header     = _page;
                    og.header_len = oy.headerbytes;
                    og.body       = _page + oy.headerbytes;
                    og.body_len   = oy.bodybytes;
                }

                oy.unsynced    = 0;
                oy.returned   += bytes;
                oy.headerbytes = 0;
                oy.bodybytes   = 0;

                return(bytes);
            }

sync_fail:
            oy.headerbytes = 0;
            oy.bodybytes   = 0;

            for (int i = 1; i < bytes; i++)
            {
                if (page[i] == 'O')
                {
                    next = (byte *)(page + i);
                    break;
                }
            }

            if (next == null)
            {
                next = oy.data + oy.fill;
            }

            oy.returned = (int)(next - oy.data);
            return((int)-(next - page));
        }
Beispiel #22
0
 public static extern int ogg_page_serialno(ref ogg_page og);
Beispiel #23
0
 static public int ogg_page_version(ref ogg_page og)
 {
     return((int)og.header[4]);
 }
Beispiel #24
0
 public static extern int ogg_page_checksum_set(ref ogg_page og);
Beispiel #25
0
        /* Conditionally flush a page; force==0 will only flush nominal-size pages, force==1 forces us to flush a page regardless of page size so long as there's any data available at all. */
        static public int ogg_stream_flush_i(ref ogg_stream_state os, ref ogg_page og, int force, int nfill)
        {
            int i;
            int vals    = 0;
            int maxvals = (os.lacing_fill > 255 ? 255 : os.lacing_fill);
            int bytes   = 0;
            int acc     = 0;

            long granule_pos = -1;

            if (ogg_stream_check(ref os) != 0)
            {
                return(0);
            }

            if (maxvals == 0)
            {
                return(0);
            }

            /* construct a page */
            /* decide how many segments to include */

            /* If this is the initial header case, the first page must only include the initial header packet */
            if (os.b_o_s == 0) /* 'initial header page' case */
            {
                granule_pos = 0;

                for (vals = 0; vals < maxvals; vals++)
                {
                    if ((os.lacing_vals[vals] & 0xff) < 255)
                    {
                        vals++;
                        break;
                    }
                }
            }
            else
            {
                int packets_done     = 0;
                int packet_just_done = 0;

                for (vals = 0; vals < maxvals; vals++)
                {
                    if (acc > nfill && packet_just_done >= 4)
                    {
                        force = 1;
                        break;
                    }

                    acc += os.lacing_vals[vals] & 0xff;

                    if ((os.lacing_vals[vals] & 0xff) < 255)
                    {
                        granule_pos      = os.granule_vals[vals];
                        packet_just_done = ++packets_done;
                    }
                    else
                    {
                        packet_just_done = 0;
                    }

                    if (vals == 255)
                    {
                        force = 1;
                    }
                }
            }

            if (force == 0)
            {
                return(0);
            }

            /* construct the header in temp storage */
            os.header[0] = (byte)'O';
            os.header[1] = (byte)'g';
            os.header[2] = (byte)'g';
            os.header[3] = (byte)'S';

            /* stream structure version */
            os.header[4] = 0;

            /* continued packet flag? */
            os.header[5] = 0;

            if ((os.lacing_vals[0] & 0x100) == 0)
            {
                os.header[5] += 0x01;
            }

            /* first page flag? */
            if (os.b_o_s == 0)
            {
                os.header[5] += 0x02;
            }

            /* last page flag? */
            if (os.e_o_s != 0 && os.lacing_fill == vals)
            {
                os.header[5] += 0x04;
            }

            os.b_o_s = 1;

            /* 64 bits of PCM position */
            for (i = 6; i < 14; i++)
            {
                os.header[i]  = (byte)(granule_pos & 0xff);
                granule_pos >>= 8;
            }

            /* 32 bits of stream serial number */
            {
                long serialno = os.serialno;

                for (i = 14; i < 18; i++)
                {
                    os.header[i] = (byte)(serialno & 0xff);
                    serialno   >>= 8;
                }
            }

            /* 32 bits of page counter (we have both counter and page header because this val can roll over) */
            if (os.pageno == -1)
            {
                /* because someone called stream_reset; this would be a strange thing to do in an encode stream, but it has plausible uses */
                os.pageno = 0;
            }

            long pageno = os.pageno++;

            for (i = 18; i < 22; i++)
            {
                os.header[i] = (byte)(pageno & 0xff);
                pageno     >>= 8;
            }

            /* zero for computation; filled in later */
            os.header[22] = 0;
            os.header[23] = 0;
            os.header[24] = 0;
            os.header[25] = 0;

            /* segment table */
            os.header[26] = (byte)(vals & 0xff);

            for (i = 0; i < vals; i++)
            {
                os.header[i + 27] = (byte)(os.lacing_vals[i] & 0xff);
                bytes            += os.header[i + 27];
            }

            /* set pointers in the ogg_page struct */
            og.header      = os.header;
            og.header_len  = vals + 27;
            os.header_fill = vals + 27;
            og.body        = os.body_data + os.body_returned;
            og.body_len    = bytes;

            /* advance the lacing data and set the body_returned pointer */
            os.lacing_fill -= vals;
            CopyMemory(os.lacing_vals, os.lacing_vals + vals, os.lacing_fill * sizeof(int));
            CopyMemory(os.granule_vals, os.granule_vals + vals, os.lacing_fill * sizeof(long));
            os.body_returned += bytes;

            /* calculate the checksum */
            ogg_page_checksum_set(ref og);

            /* done */
            return(1);
        }
 private void WritePage(ref ogg_page page, Stream stream)
 {
     byte[] headerData = ReadBuffer(page.header, page.header_len);
     byte[] bodyData = ReadBuffer(page.body, page.body_len);
     stream.Write(headerData, 0, headerData.Length);
     stream.Write(bodyData, 0, bodyData.Length);
 }
Beispiel #27
0
        /* add the incoming page to the stream state; we decompose the page
         * into packet segments here as well. */

        static public int ogg_stream_pagein(ref ogg_stream_state os, ref ogg_page og)
        {
            byte *header = og.header;
            byte *body   = og.body;

            int  bodysize   = og.body_len;
            int  version    = ogg_page_version(ref og);
            int  continued  = ogg_page_continued(ref og);
            int  bos        = ogg_page_bos(ref og);
            int  eos        = ogg_page_eos(ref og);
            long granulepos = ogg_page_granulepos(ref og);
            int  serialno   = ogg_page_serialno(ref og);
            int  pageno     = ogg_page_pageno(ref og);
            int  segments   = header[26];

            if (ogg_stream_check(ref os) != 0)
            {
                return(-1);
            }

            /* clean up 'returned data' */
            {
                int lr = os.lacing_returned;
                int br = os.body_returned;

                /* body data */
                if (br > 0)
                {
                    os.body_fill -= br;

                    if (os.body_fill > 0)
                    {
                        CopyMemory(os.body_data, os.body_data + br, os.body_fill);
                    }

                    os.body_returned = 0;
                }

                /* segment table */
                if (lr > 0)
                {
                    if (os.lacing_fill - lr > 0)
                    {
                        CopyMemory(os.lacing_vals, os.lacing_vals + lr, (os.lacing_fill - lr) * sizeof(int));
                    }
                    else
                    {
                        CopyMemory(os.granule_vals, os.granule_vals + lr, (os.lacing_fill - lr) * sizeof(long));
                    }
                }

                os.lacing_fill    -= lr;
                os.lacing_packet  -= lr;
                os.lacing_returned = 0;
            }

            /* check the serial number */
            if (serialno != os.serialno)
            {
                return(-1);
            }

            if (version > 0)
            {
                return(-1);
            }

            if (_os_lacing_expand(ref os, segments + 1) != 0)
            {
                return(-1);
            }

            /* are we in sequence? */
            if (pageno != os.pageno)
            {
                /* unroll previous partial packet (if any) */
                for (int i = os.lacing_packet; i < os.lacing_fill; i++)
                {
                    os.body_fill -= os.lacing_vals[i] & 0xff;
                }

                os.lacing_fill = os.lacing_packet;

                /* make a note of dropped data in segment table */
                if (os.pageno != -1)
                {
                    os.lacing_vals[os.lacing_fill++] = 0x400;
                    os.lacing_packet++;
                }
            }

            int segptr = 0;

            /* are we a 'continued packet' page? If so, we may need to skip some segments */
            if (continued != 0)
            {
                if (os.lacing_fill < 1 || os.lacing_vals[os.lacing_fill - 1] == 0x400)
                {
                    bos = 0;

                    for (segptr = 0; segptr < segments; segptr++)
                    {
                        int val = header[27 + segptr];

                        body     += val;
                        bodysize -= val;

                        if (val < 255)
                        {
                            segptr++;
                            break;
                        }
                    }
                }
            }

            if (bodysize > 0)
            {
                if (_os_body_expand(ref os, bodysize) != 0)
                {
                    return(-1);
                }

                CopyMemory(os.body_data + os.body_fill, body, bodysize);
                os.body_fill += bodysize;
            }

            int saved = -1;

            while (segptr < segments)
            {
                int val = og.header[27 + segptr];

                os.lacing_vals[os.lacing_fill]  = val;
                os.granule_vals[os.lacing_fill] = -1;

                if (bos != 0)
                {
                    os.lacing_vals[os.lacing_fill] |= 0x100;
                    bos = 0;
                }

                if (val < 255)
                {
                    saved = os.lacing_fill;
                }

                os.lacing_fill++;
                segptr++;

                if (val < 255)
                {
                    os.lacing_packet = os.lacing_fill;
                }
            }

            if (saved != -1)
            {
                os.granule_vals[saved] = granulepos;
            }

            if (eos != 0)
            {
                os.e_o_s = 1;

                if (os.lacing_fill > 0)
                {
                    os.lacing_vals[os.lacing_fill - 1] |= 0x200;
                }
            }

            os.pageno = pageno + 1;

            return(0);
        }