/*------------------------------------------------------------------------
 *
 * Copyright (c) 1997-1998 by Cornell University.
 * 
 * See the file "license.txt" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * demux.c 
 *
 * Wei-Tsang Ooi weitsng@cs.cornell.edu
 *
 * Usage : demux mpegSystem streamId output 
 *
 * Takes an MPEG-1 system stream, and an id of the stream to extract.  This
 * programs extract the stream and dumped it into a file.
 * 
 * NOTE : There are more than one way to demux a stream.  This example
 * uses the SysToc structure.  This structure is provided for convinience
 * but it does not follow Dali's philosophies since it hides many details
 * including memory allocation.  There is also no way for the programmer to
 * specifies which stream the SysToc should include/exclude.  Please see
 * another example demux2.c which uses hdr find/parse/skip to demux a stream.
 *
 *------------------------------------------------------------------------
 */
#include <dvmbasic.h>
#include <dvmmpeg.h>

int main(int argc, char *argv[])
{
    BitParser *bp;
    BitStream *bs;
    FILE *inf, *outf;
    int id, len, off;
    MpegSysToc *toc;
    BitStreamFilter *filter;

    /* 
     * Parse arguments and open input file.
     */
    if (argc < 4) {
        fprintf(stderr, "usage : %s input streamId output", argv[0]);
	exit(1);
    }
    id = atoi(argv[2]);
    inf = fopen(argv[1], "rb");
    if (inf == NULL) {
        fprintf(stderr, "unable to open file %s\n", argv[1]);
	exit(1);
    }

    /*
     * Initialize input bitstream and bitparser.
     */
    bp = BitParserNew();
    bs = BitStreamNew(65536);
    BitParserWrap (bp, bs);
    len = BitStreamFileRead(bs, inf, 0);

    /*
     * Creates a new MpegSysToc structure.   Read a bunch of bytes from
     * input bitstream and call MpegSysTocAdd to parse the bitstream and
     * create entries in SysToc.  We repeat until we reach the end of
     * files.
     */
    toc = MpegSysTocNew();
    off = 0;
    MpegSysTocAdd(bp, toc, off);
    while (!feof(inf)) {
        int pos, bytesInBuf;
        pos = BitParserTell (bp);
	bytesInBuf = 65536-pos;
        BitStreamShift(bs, pos);
	off += pos;
	len = BitStreamFileRead(bs, inf, bytesInBuf);
	BitParserSeek(bp, 0);
	MpegSysTocAdd(bp, toc, off);
    }
    
    /*
     * We rewinds to the beginning of the input file.  And creates a new
     * output file.
     */
    fseek(inf, 0, SEEK_SET);
    outf = fopen(argv[3], "wb");
    if (outf == NULL) {
        fprintf(stderr, "unable to open file %s\n", argv[3]);
	exit(1);
    }

    /*
     * We find the filter for the corresponding stream we are interested in.
     */
    filter = MpegSysTocGetFilter(toc, id);

    /*
     * Using that filter, we read in segments corresponding to the stream,
     * and dump it out to the output file.
     */
    len = BitStreamFileFilterIn(bs, inf, 0, filter);
    while (len == 65536) {
        BitStreamFileWriteSegment(bs, outf, 0, len);
	len = BitStreamFileFilterIn(bs, inf, 0, filter);
    }
    BitStreamFileWriteSegment(bs, outf, 0, len);

    /*
     * Finally we clean up the structures we allocated.
     */
    MpegSysTocFree(toc);
    BitStreamFree(bs);
    fclose(inf);
    fclose(outf);

    return 0;
}