/*------------------------------------------------------------------------
 *
 * 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.
 *
 * demux2.c 
 *
 * Wei-Tsang Ooi weitsng@cs.cornell.edu
 *
 * Usage : demux2 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.
 * 
 *------------------------------------------------------------------------
 */

#include "dvmbasic.h"
#include "dvmmpeg.h"

int main(int argc, char *argv[])
{
    BitParser *inbp;
    BitStream *inbs, *outbs;
    FILE *outf;
    MpegPktHdr *pkthdr;
    int sid, id, pktlen, len, currin, currout;

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

    /*
     * Initialize input and output bitstream and bitparser.
     */
    inbp = BitParserNew();
    inbs = BitStreamMmapReadNew(argv[1]);
    BitParserWrap (inbp, inbs);

    outbs = BitStreamNew(65536);

    /*
     * Allocate a new Packet header.
     */

    pkthdr = MpegPktHdrNew();
    currout = 0;

    while (1) {

	/*
	 * Find a packet by looking for its header.
	 * It not found then we are done.
	 */
	len = MpegPktHdrFind (inbp);
	if (len == -1) {
	    break;
	}

	/*
	 * Parse the header and check for the stream id to see 
	 * if this is the stream that we want.
	 */
	len = MpegPktHdrParse (inbp, pkthdr);
	sid = MpegPktHdrGetStreamId (pkthdr);
	
	/*
	 * The stream id in the header is shifted by 192, so we unshift
	 * it before compare with the input id.
	 */
	if (sid - 192 != id) {
	    continue;
	}

	/*
	 * Retrive the packet length field from the packet header.
	 * The tricky part : The packet length includes part of the 
	 * length of the header :
	 *
	 *  |<-----  header ---->|<------ body ------>|
	 *  +-----+---------+----+--------------------+
	 *  |     | length  |    |                    |
	 *  +-----+---------+----+--------------------+
	 *  |<-6->|<------------ length bytes ------->|
	 *
	 * So the number of bytes we actually going to dump
	 * is (total length) - (length of header) 
	 * == (pktlen + 6)   - len
	 */

	pktlen  = MpegPktHdrGetLength (pkthdr);
	len = pktlen + 6 - len;
    	currin = BitParserTell (inbp);

    	/*
	 * Check if the BitStream is going to be full. If yes
	 * we flush the data in BitStream to disk.
	 * 
	 * Note : instead of flushing, we may do other things here,
	 * such as decoding the stream.
	 */
	if (currout + len > 65536) {
	    BitStreamFileWriteSegment (outbs, outf, 0, currout);
	    currout = 0;
	}
	BitStreamDump (inbs, currin, outbs, currout, len);
	BitParserSeek (inbp, len + currin);
	currout += len;
    }

    /*
     * Flush what ever is left to the disk and cleanup.
     */
    BitStreamFileWriteSegment (outbs, outf, 0, currout);
    BitStreamMmapReadFree(inbs);
    BitStreamFree(outbs);
    BitParserFree(inbp);
    MpegPktHdrFree(pkthdr);
    fclose(outf);

    return 0;
}