mischiefinitial commit464c1f28 years agoHistory
171 lines · 2.6 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <bio.h>#include <thread.h>#include <draw.h>#include <memdraw.h> #include "imagefile.h"#include "avi.h"#include "fns.h" static voidfreerawimage(Rawimage *r){	int i;	for(i = 0; i < r->nchans; i++)		free(r->chans[i]);	free(r->cmap);	free(r);} static uchar*decpcm(int fd, long offset, int n){	uchar *buf; 	buf = malloc(n);	if(buf == nil)		return nil; 	seek(fd, offset, 0); 	if(readn(fd, buf, n) != n){		free(buf);		return nil;	} 	return buf;} static Memimage*decjpg(int fd, long offset){	Rawimage **jpg, *c;	Memimage *i; 	c = nil;	i = nil; 	seek(fd, offset, 0); 	jpg = readjpg(fd, CYCbCr);	if(jpg == nil){		fprint(2, "readjpg: %r\n");		return nil;	} 	if(jpg[0] == nil)		goto fail; 	c = totruecolor(jpg[0], CRGB24);	if(c == nil)		goto fail; 	i = allocmemimage(c->r, RGB24);	if(i == nil)		goto fail; 	if(loadmemimage(i, i->r, c->chans[0], c->chanlen) < 0){		freememimage(i);		i = nil;	} fail:	if(c)		freerawimage(c);	if(jpg[0])		freerawimage(jpg[0]);	free(jpg);	return i;	} static voiddecrun(void *v){	int i;	Decproc *d = v;	Decreq req;	Decresp *resp;	Dec *dec;	AVIIndex *idxp; 	threadsetname("decproc %d", threadid()); 	for(;;){		if(recv(d->in, &req) != 1){			fprint(2, "decproc dying");			break;		} 		resp = mallocz(sizeof(Decresp), 1);		if(resp == nil)			sysfatal("malloc: %r");		resp->dec = mallocz(req.count * sizeof(Dec), 1);		if(resp->dec == nil)			sysfatal("malloc: %r");		resp->ndec = req.count; 		for(i = 0; i < req.count; i++, req.index++){			idxp = &d->avi->index[req.index];			dec = &resp->dec[i]; 			// XXX: no clue why 0-length chunks appear			if(idxp->length == 0){				dec->type = DINVALID;				continue;			} 			if(memcmp(idxp->id, "01wb", 4) == 0){				dec->type = DAUDIO;				dec->nbuf = idxp->length;				dec->buf = decpcm(d->fd, d->avi->movi+idxp->offset+4, idxp->length);				if(dec->buf == nil){					rerrstr(resp->err, sizeof(resp->err));					goto out;				}			} 			if(memcmp(idxp->id, "00dc", 4) == 0){				dec->type = DIMAGE;				dec->image = decjpg(d->fd, d->avi->movi+idxp->offset+4);				if(dec->image == nil){					rerrstr(resp->err, sizeof(resp->err));					goto out;				}			}		} out:		sendp(d->out, resp);	}} Decproc*decproc(AVI *avi){	Decproc *d; 	d = mallocz(sizeof(*d), 1);	if(d == nil)		return nil; 	d->avi = avi; 	d->fd = open(avi->path, OREAD);	if(d->fd < 0){		free(d);		return nil;	} 	d->in = chancreate(sizeof(Decreq), 0);	d->out = chancreate(sizeof(Decresp*), 0); 	assert(d->in != nil);	assert(d->out != nil); 	if(proccreate(decrun, d, 16*1024) < 0)		sysfatal("proccreate: %r"); 	return d;}