Пример #1
0
        bool Flush(OggPage og, bool force, int fill)
        {
            int maxvals = Math.Min(LacingFill, 0xFF);

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

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

            int  vals        = 0;
            int  acc         = 0;
            long granule_pos = -1;

            // If this is the initial header case, the first page must only include
            // the initial header packet
            if (!BoS)   // 'initial header page' case
            {
                granule_pos = 0;
                for (vals = 0; vals < maxvals; vals++)
                {
                    if ((LacingVals[vals] & 0xFF) < 0xFF)
                    {
                        vals++;
                        break;
                    }
                }
            }
            else
            {
                int packets_done     = 0;
                int packet_just_done = 0;
                for (vals = 0; vals < maxvals; vals++)
                {
                    if (acc > fill && packet_just_done >= 4)
                    {
                        force = true;
                        break;
                    }
                    acc += LacingVals[vals] & 0xFF;
                    if ((LacingVals[vals] & 0xFF) < 0xFF)
                    {
                        granule_pos      = GranuleVals[vals];
                        packet_just_done = ++packets_done;
                    }
                    else
                    {
                        packet_just_done = 0;
                    }
                }
                if (0xFF == vals)
                {
                    force = true;
                }
            }
            if (!force)
            {
                return(false);
            }

            // construct the header in temp storage
            Encoding.ASCII.GetBytes("OggS", 0, 4, Header, 0);

            // stream structure version
            Header[4] = 0;

            // continued packet flag?
            Header[5] = 0;
            if ((LacingVals[0] & 0x100) == 0)
            {
                Header[5] |= 1;
            }
            // first page flag?
            if (!BoS)
            {
                Header[5] |= 2;
            }
            // last page flag?
            if (EoS && LacingFill == vals)
            {
                Header[5] |= 4;
            }
            BoS = true;

            // 64 bits of PCM position
            LittleEndian.Pack(granule_pos, Header, 6);

            // 32 bits of stream serial number
            LittleEndian.Pack(SerialNo, Header, 14);

            // 32 bits of page counter (we have both counter and page header because this
            // val can roll over)
            if (-1 == PageNo)
            {
                PageNo = 0;
            }
            LittleEndian.Pack(PageNo, Header, 18);
            ++PageNo;

            int bytes = 0;

            // segment table
            Header[26] = (byte)vals;
            for (int i = 0; i < vals; ++i)
            {
                bytes += Header[i + 27] = (byte)LacingVals[i];
            }

            // set pointers in the ogg_page struct
            og.Header       = Header;
            og.HeaderLength = HeaderFill = vals + 27;
            og.Body         = BodyData;
            og.BodyStart    = BodyReturned;
            og.BodyLength   = bytes;

            // advance the lacing data and set the body_returned pointer
            LacingFill -= vals;
            Array.Copy(LacingVals, vals, LacingVals, 0, LacingFill);
            Array.Copy(GranuleVals, vals, GranuleVals, 0, LacingFill);
            BodyReturned += bytes;

            // calculate the checksum
            og.SetChecksum();

            return(true);
        }
Пример #2
0
        public bool PageOut(OggPage page)
        {
            bool force = EoS && (LacingFill > 0) || (LacingFill > 0 && !BoS);

            return(Flush(page, force, 0x1000));
        }