/*------------------------------------------------------------------------ * * 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. * *------------------------------------------------------------------------ */ #include <sys/types.h> #include <sys/stat.h> #include <dvmbasic.h> #include <dvmmpeg.h> #include <dvmcolor.h> #include <dvmavi.h> void swap (ByteImage **x, ByteImage **y) { ByteImage *temp; temp = *x; *x = *y; *y = temp; } /* *--------------------------------------------------------------- * This proc make sure that there are at least size bytes of * data in the bitstream bs, which is attached to bitparser bp. * If there is not enough data, fill up the bitstream by reading * from tcl channel chan. *--------------------------------------------------------------- */ void CheckBitStreamUnderflow (bs, bp, chan, size) BitStream *bs; BitParser *bp; FILE *chan; int size; { int off = BitParserTell(bp); int left = BitStreamBytesLeft(bs, off); if (left < size) { BitStreamShift (bs, off); BitStreamFileRead (bs, chan, left); BitParserSeek (bp, 0); } } int main(int argc, char *argv[]) { BitParser *bp = BitParserNew(); BitStream *bs = BitStreamNew(65536); BitParser *outbp; BitStream *outbs; MpegSeqHdr *sh; MpegPicHdr *fh; ByteImage *r, *g, *b, *y, *u, *v, *br, *bg, *bb; ByteImage *prevy, *prevu, *prevv, *futurey, *futureu, *futurev; ScImage *scy, *scu, *scv; VectorImage *fwdmv, *bwdmv; AviFile *aviFile; AviStream *aviStream; FILE *file; int codec, play_order, bnum=0, togo=0; int currCode, len; int halfw, halfh, w, h, seqw, seqh, picSize, remw, remh, counter, type; if (argc < 4) { fprintf(stderr, "usage : %s input output.avi codec\n", argv[0]); exit(1); } file = fopen(argv[1], "rb"); if (file == NULL) { fprintf(stderr, "unable to open %s for reading.\n", argv[1]); exit(1); } BitStreamFileRead(bs, file, 0); BitParserWrap(bp, bs); sh = MpegSeqHdrNew(); MpegSeqHdrFind(bp); MpegSeqHdrParse(bp, sh); seqw = MpegSeqHdrGetWidth(sh); seqh = MpegSeqHdrGetHeight(sh); picSize = MpegSeqHdrGetBufferSize(sh); remw = seqw % 16; remh = seqh % 16; if (remw != 0) { w = seqw + 16 - remw; } else { w = seqw; } if (remh != 0) { h = seqh + 16 - remh; } else { h = seqh; } halfw = w/2; halfh = h/2; y = ByteNew (w, h); prevy = ByteNew (w, h); futurey = ByteNew (w, h); r = ByteNew (seqw, seqh); g = ByteNew (seqw, seqh); b = ByteNew (seqw, seqh); br = ByteNew (seqw, seqh); bg = ByteNew (seqw, seqh); bb = ByteNew (seqw, seqh); u = ByteNew (halfw, halfh); prevu = ByteNew (halfw, halfh); futureu = ByteNew (halfw, halfh); v = ByteNew (halfw, halfh); prevv = ByteNew (halfw, halfh); futurev = ByteNew (halfw, halfh); fwdmv = VectorNew (w/16, h/16); bwdmv = VectorNew (w/16, h/16); scy = ScNew (w/8, h/8); scu = ScNew (w/16, h/16); scv = ScNew (w/16, h/16); fh = MpegPicHdrNew(); outbs = BitStreamNew(3*seqw*seqh + 20); outbp = BitParserNew(); BitParserWrap(outbp, outbs); len = MpegPicHdrFind(bp); counter = 0; AVIFileInit(); if (AviFileCreate(argv[2], &aviFile) != 0) { fprintf(stderr, "unable to create avifile %s \n", argv[2]); exit(1); } codec = mmioFOURCC(argv[3][0], argv[3][1], argv[3][2], argv[3][3]); if (AviVideoStreamCreate (aviFile, codec, seqw, seqh, 15, 30, 75, 50000, &aviStream) != 0) { fprintf(stderr, "unable to create avistream \n"); exit(1); } while (1) { CheckBitStreamUnderflow(bs, bp, file, picSize); MpegPicHdrParse(bp, fh); play_order = MpegPicHdrGetTemporalRef(fh); type = MpegPicHdrGetType(fh); if (type == I_FRAME) { swap(&futurey, &prevy); swap(&futureu, &prevu); swap(&futurev, &prevv); MpegPicIParse(bp, sh, fh, scy, scu, scv); ScIToByte(scy, y); ScIToByte(scu, u); ScIToByte(scv, v); YuvToRgb420(y, u, v, r, g, b); swap(&y, &futurey); swap(&u, &futureu); swap(&v, &futurev); } else if (type == P_FRAME) { swap(&futurey, &prevy); swap(&futureu, &prevu); swap(&futurev, &prevv); MpegPicPParse(bp, sh, fh, scy, scu, scv, fwdmv); ScPToY(scy, fwdmv, prevy, y); ScPToUV(scu, fwdmv, prevu, u); ScPToUV(scv, fwdmv, prevv, v); YuvToRgb420(y, u, v, r, g, b); swap(&y, &futurey); swap(&u, &futureu); swap(&v, &futurev); } else { MpegPicBParse(bp, sh, fh, scy, scu, scv, fwdmv, bwdmv); ScBToY(scy, fwdmv, bwdmv, prevy, futurey, y); ScBToUV(scu, fwdmv, bwdmv, prevu, futureu, u); ScBToUV(scv, fwdmv, bwdmv, prevv, futurev, v); YuvToRgb420(y, u, v, r, g, b); } /* Convert to display order */ if (play_order == togo) { AviVideoFrameWrite(aviStream, r, g, b); togo++; if (bnum == togo) { AviVideoFrameWrite(aviStream, br, bg, bb); bnum=0; togo++; } } else if(play_order > togo) { swap(&r, &br); swap(&g, &bg); swap(&b, &bb); bnum = play_order; } else { togo = 0; if (play_order == togo) { AviVideoFrameWrite(aviStream, r, g, b); togo++; } else { swap(&r, &br); swap(&g, &bg); swap(&b, &bb); bnum = play_order; } } MpegPicHdrFind(bp); currCode = MpegGetCurrStartCode(bp); if (currCode == SEQ_END_CODE) { break; } counter++; printf("Frame %d\n", counter); } MpegPicHdrFree(fh); MpegSeqHdrFree(sh); BitStreamFree(bs); BitParserFree(bp); ByteFree(r); ByteFree(g); ByteFree(b); ByteFree(br); ByteFree(bg); ByteFree(bb); ByteFree(y); ByteFree(u); ByteFree(v); ByteFree(prevy); ByteFree(prevu); ByteFree(prevv); ByteFree(futurey); ByteFree(futureu); ByteFree(futurev); ScFree(scy); ScFree(scu); ScFree(scv); VectorFree(fwdmv); VectorFree(bwdmv); AviStreamClose(aviStream); AviFileClose(aviFile); return 0; }