mischiefinitial commit464c1f28 years agoHistory
169 lines · 3.4 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <bio.h> #include "riff.h"#include "avi.h" voidavidump(AVI *avi){	int i;	AVIMainHeader *avih;	AVIStreamHeader *strh;	WAVEFORMATEX *wf; 	avih = &avi->header; 	fprint(2, "AVI main header\n");	fprint(2, "\tframes = %ud, ms/frame = %ud\n",		avih->totalframes, avih->microsperframe/1000);	fprint(2, "\t%ud streams, %udx%ud\n",		avih->streams, avih->width, avih->height);	fprint(2, "\tflags = %b\n", avih->flags); 	//vdelay = avih.microsperframe/1000;	//print("Delay = %dms\n", vdelay); 	// dump stream header	for(i = 0; i < nelem(avi->stream); i++){		strh = &avi->stream[i];		fprint(2, "AVI Stream: '%.4s' '%.4s'\n", strh->type, strh->handler);		fprint(2, "\tflags %b\n", strh->flags);		fprint(2, "\trate %ud/%ud\n", strh->rate, strh->scale);		fprint(2, "\tstart %ud length %ud quality %ud samplesize %ud\n",			strh->start, strh->length, strh->quality, strh->samplesize);	} 	wf = &avi->waveformat;	fprint(2, "AVI Wave format: tag %hux %hud channels %hud bit @ %udHz depth\n",				wf->tag, wf->channels, wf->bitspersample, wf->samplespersec); 	fprint(2, "AVI Index: %lud entries\n", avi->nindex);} static intavichunk(AVI *avi, RiffChunk *c){	AVIStreamHeader strh; 	//fprint(2, "Chunk: '%.4s' form '%.4s' %lud bytes @ %lld\n",	//	c->type, c->form, c->size, c->offset); 	if(memcmp(c->form, "movi", 4) == 0)		avi->movi = c->offset; 	if(rifftype(c, "avih") == 0){		if(riffread(c, avi->bio, &avi->header, sizeof(AVIMainHeader)) < 0)			return -1;	} 	// messy, but ¯\_(ツ)_/¯	if(rifftype(c, "strh") == 0){		if(riffread(c, avi->bio, &strh, sizeof(strh)) < 0)			sysfatal("riffread: %r"); 		if(memcmp(strh.type, "vids", 4) == 0){			avi->stream[0] = strh;			Bseek(avi->bio, c->offset+c->size+(c->size&1), 0);			if(riffchunk(c, avi->bio) < 0)				return -1; 			if(rifftype(c, "strf") != 0)				return -1; 			if(riffread(c, avi->bio, &avi->bitmap, sizeof(avi->bitmap)) < 0)				return -1;		} 		if(memcmp(strh.type, "auds", 4) == 0){			avi->stream[1] = strh;			Bseek(avi->bio, c->offset+c->size+(c->size&1), 0);			if(riffchunk(c, avi->bio) < 0)				return -1; 			if(rifftype(c, "strf") != 0)				return -1; 			if(riffread(c, avi->bio, &avi->waveformat, sizeof(avi->waveformat)) < 0)				return -1;		}	} 	if(rifftype(c, "idx1") == 0){		avi->index = riffsnarf(c, avi->bio);		if(avi->index == nil)			return -1;		avi->nindex = c->size/sizeof(AVIIndex);	} 	return 0;} static intaviload(AVI *avi, RiffChunk *outer){	RiffChunk chunk;	vlong start, off, end; 	start = off = Boffset(avi->bio);	end = start + outer->size; 	while(off != end){		if(riffchunk(&chunk, avi->bio) < 0)			return -1; 		if(avichunk(avi, &chunk) < 0)			return -1; 		if(rifftype(&chunk, "LIST") == 0 && memcmp(chunk.form, "movi", 4) != 0){			if(aviload(avi, &chunk) < 0)				return -1;		} 		// &1 to account for RIFF padding		off = Bseek(avi->bio, chunk.offset+chunk.size+(chunk.size&1), 0);	} 	return 0;} AVI*aviopen(char *name){	Biobuf *bio;	RiffChunk r;	AVI *avi; 	bio = Bopen(name, OREAD);	if(bio == nil)		return nil; 	if(riffchunk(&r, bio) < 0){		Bterm(bio);		return nil;	} 	if(rifftype(&r, "RIFF") != 0){		Bterm(bio);		werrstr("%s: not a RIFF", name);		return nil;	} 	avi = mallocz(sizeof(AVI), 1);	if(avi == nil){		Bterm(bio);		return nil;	} 	snprint(avi->path, sizeof(avi->path), "%s", name);	avi->bio = bio; 	if(aviload(avi, &r) < 0){		free(avi);		Bterm(bio);		return nil;	} 	return avi;}