[xiph-cvs] cvs commit: ices/src stream_rewrite.c Makefile.am

Michael Smith msmith at xiph.org
Tue Oct 2 05:23:51 PDT 2001



msmith      01/10/02 05:23:51

  Modified:    src      Makefile.am
  Added:       src      stream_rewrite.c
  Log:
  Add new file stream_rewrite.c, even though nothing uses it yet and the code
  is stupid and broken, because my brain is currently stupid and broken and
  I'll probably accidently delete the file if I don't commit it. And it
  compiles, so it doesn't break anything.

Revision  Changes    Path
1.2       +1 -1      ices/src/Makefile.am

Index: Makefile.am
===================================================================
RCS file: /usr/local/cvsroot/ices/src/Makefile.am,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Makefile.am	2001/09/10 02:30:49	1.1
+++ Makefile.am	2001/10/02 12:23:51	1.2
@@ -21,7 +21,7 @@
 bin_PROGRAMS = ices
 
 noinst_HEADERS = config.h input.h inputmodule.h im_playlist.h signals.h stream.h reencode.h encode.h playlist_basic.h logging.h im_stdinpcm.h $(ossheaders) $(sunheaders) event.h stream_shared.h metadata.h
-ices_SOURCES = input.c config.c stream.c ices.c signals.c im_playlist.c reencode.c encode.c playlist_basic.c im_stdinpcm.c $(osssources) $(sunsources) stream_shared.c savefile.c metadata.c
+ices_SOURCES = input.c config.c stream.c ices.c signals.c im_playlist.c reencode.c encode.c playlist_basic.c im_stdinpcm.c $(osssources) $(sunsources) stream_shared.c savefile.c metadata.c stream_rewrite.c
 
 ices_LDADD = net/libicenet.la thread/libicethread.la log/libicelog.la\
         avl/libiceavl.la timing/libicetiming.la

1.1                  ices/src/stream_rewrite.c

Index: stream_rewrite.c
===================================================================
/* stream_rewrite.c
 * - Functions to rewrite a stream (at the ogg level) at runtime, to
 *   allow a) More reliable streaming of somewhat broken files, and
 *         b) Inserting comments into 'static' files at stream time.
 *
 * Heavily based on vcedit.c from vorbiscomment.
 *
 * $Id: stream_rewrite.c,v 1.1 2001/10/02 12:23:51 msmith Exp $
 *
 * Copyright (c) 2001 Michael Smith <msmith at labyrinth.net.au>
 *
 * This program is distributed under the terms of the GNU General
 * Public License, version 2. You may use, modify, and redistribute
 * it under the terms of this license. A copy should be included
 * with this source.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ogg/ogg.h>
#include <vorbis/codec.h>

#include "config.h"
//#include "stream_rewrite.h"

typedef struct {
    ogg_sync_state    sync;
    ogg_stream_state  stream_out;
    ogg_stream_state  stream_in;

    vorbis_comment    vc;
    vorbis_info       vi;

    FILE             *in;
    long              serial;
    char             *vendor;
    int               prevW;

    short needflush,needout,in_header;

    ogg_int64_t granpos;

} stream_rewriter;

#define MODULE "stream-rewrite/"
#include "logging.h"

#define CHUNKSIZE 4096

/* Next two functions pulled straight from libvorbis, apart from one change
 * - we don't want to overwrite the vendor string.
 */
static void _v_writestring(oggpack_buffer *o,char *s)
{
        while(*s)
        {
                oggpack_write(o,*s++,8);
        }
}

tatic int _commentheader_out(vorbis_comment *vc, char *vendor, ogg_packet *op)
{
        oggpack_buffer opb;

        oggpack_writeinit(&opb);

        /* preamble */  
        oggpack_write(&opb,0x03,8);
        _v_writestring(&opb,"vorbis");

        /* vendor */
        oggpack_write(&opb,strlen(vendor),32);
        _v_writestring(&opb,vendor);

        /* comments */
        oggpack_write(&opb,vc->comments,32);
        if(vc->comments){
                int i;
                for(i=0;i<vc->comments;i++){
                        if(vc->user_comments[i]){
                                oggpack_write(&opb,vc->comment_lengths[i],32);
                                _v_writestring(&opb,vc->user_comments[i]);
                        }else{
                                oggpack_write(&opb,0,32);
                        }
                }
        }
        oggpack_write(&opb,1,1);

        op->packet = _ogg_malloc(oggpack_bytes(&opb));
        memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));

        op->bytes=oggpack_bytes(&opb);
        op->b_o_s=0;
        op->e_o_s=0;
        op->granulepos=0;

        return 0;
}

tatic int _blocksize(stream_rewriter *s, ogg_packet *p)
{
        int this = vorbis_packet_blocksize(&s->vi, p);
        int ret = (this + s->prevW)/4;

        if(!s->prevW)
        {
                s->prevW = this;
                return 0;
        }

        s->prevW = this;
        return ret;
}

tatic int _fetch_next_packet(stream_rewriter *s, ogg_packet *p)
{
        int result;
        ogg_page og;
        char *buffer;
        int bytes;

        result = ogg_stream_packetout(&s->stream_in, p);

        if(result > 0)
                return 1;
        else
        {
                while(ogg_sync_pageout(&s->sync, &og) <= 0)
                {
                        buffer = ogg_sync_buffer(&s->sync, CHUNKSIZE);
                        bytes = fread(buffer,1, CHUNKSIZE, s->in);
                        ogg_sync_wrote(&s->sync, bytes);
                        if(bytes == 0) 
                                return 0;
                }

                ogg_stream_pagein(&s->stream_in, &og);
                return _fetch_next_packet(s, p);
        }
}

tatic int _get_next_page(stream_rewriter *s, ogg_page *page)
{
    if(s->needflush)
    {
        if(ogg_stream_flush(&s->stream_out, page))
        {
            s->needflush=s->needout=0;
            return 1;
        }
    }
    else if(s->needout)
    {
        if(ogg_stream_pageout(&s->stream_out, page))
        {
            s->needflush=s->needout=0;
            return 1;
        }
    }

    return 0;
}

/* (what does this do?)
 * return value: <0  Error
 *                0  No more data in current file
 *               >0  Success, page returned.
 */
int stream_get_page(stream_rewriter *s, ogg_page *page)
{
    int res;
    ogg_packet packet;

    /* See if there's a pending page already - this should do the stuff with 
     * needflush/needout, remove that from below */
    if(_get_next_page(s, page) > 0)
        return 1;

    while((_fetch_next_packet(s, &packet) > 0))
    {
        /* Ok, deal with all the icky granulepos manipulations we need */
        int size = _blocksize(s, &packet);
        int flag=0;
        s->granpos += size;

        if(_get_next_page(s, page) > 0)
            flag = 1;

        if(packet.granulepos == -1)
            packet.granulepos = s->granpos;
        else
        {
            if(s->granpos > packet.granulepos)
            {
                s->granpos = packet.granulepos;
                s->needflush = 1;
            }
            else
                s->needout = 1;
        }

        /* Header packet. Note that this doesn't catch ALL header packets
         * (some dodgy files have it wrong, it catches them all in correct
         * streams), but it always gets the first packet (primary header)
         */
        if(packet.granulepos == 0)
        {
            s->in_header = 1;
            s->needflush = 1;

            ogg_stream_init(&s->stream_out, s->serial++);
            vorbis_info_init(&s->vi);
            vorbis_comment_init(&s->vc);
        }
        
        if(s->in_header) 
        {
            if(vorbis_synthesis_headerin(&s->vi, &s->vc, &packet) < 0)
            {
                LOG_ERROR0("Bad header in vorbis bitstream, cannot send");
                /* FIXME: Clear allocations first */
                return -1;
            }

            if(s->in_header++ == 3) /* We have all 3 header packets */
            {
                s->in_header = 0;
                s->needflush = 1;
            }

            /* FIXME: Allow comment header mangling here */
        }

        ogg_stream_packetin(&s->stream_out, &packet);

        if(flag = 1)
            return 1;
    }

    /* Fall out of above loop means EOS. Try flushing output stream */
    s->stream_out.e_o_s = 1;
    if(ogg_stream_flush(&s->stream_out, page))
        return 1;

    /* Final fallthrough. Nothing left. At all. 
     * FIXME: cope with chained streams properly. */
    return 0; 
}

--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list