176 lines · 3.9 KB · C
RawDownload
#include <decoder/core/inc/decoder.h>#include <decoder/core/inc/manage_dec_ref.h>#include <decoder/core/inc/decoder9.h>#include <thread.h>#include "frame.h"#include "stream.h"#include "decoder.h"#include "misc.h" #pragma lib "../openh264/codec/libopenh264.$M.a" static voidlogfun(void *ctx, const int32_t level, const char *fmt, va_list argv){	USED(ctx); 	if(debug >= level){		fprint(2, "h264: ");		vfprint(2, fmt, argv);		fprint(2, "\n");	}} static intsendframe(H264Aux *a, uvlong dt, Channel *c){	int w, h, *stride;	Frame *f; 	w = a->info.UsrData.sSystemBuffer.iWidth;	h = a->info.UsrData.sSystemBuffer.iHeight;	stride = a->info.UsrData.sSystemBuffer.iStride; 	if((f = newframe(w, h, a->data, stride[0], stride[1])) == nil)		return -1; 	f->crop.left = a->ctx.sFrameCrop.iLeftOffset;	f->crop.top = a->ctx.sFrameCrop.iTopOffset;	f->crop.right = w - a->ctx.sFrameCrop.iRightOffset;	f->crop.bottom = h - a->ctx.sFrameCrop.iBottomOffset;	f->dt = dt; 	if(sendp(c, f) < 0){		free(f);		return -1;	} 	return 0;} static voiddecode(void *x){	uvlong start, framenum, lasttimestamp, ts;	Streamframe sf;	Decoder *d;	Channel *c;	int res, n;	H264Aux *a; 	threadsetname("decoder/h264");	d = x;	a = d->aux;	lasttimestamp = 0;	for(res = 0, framenum = 0; res >= 0 && (res = Sread(d->s, &sf)) == 0 && sf.sz > 0; framenum++){		if(sf.sz > 4 && sf.buf[0] == 0 && sf.buf[1] == 0){			if(sf.buf[2] == 1)				n = sf.buf[3];			else if(sf.buf[3] == 1)				n = sf.buf[4];			else				n = 0;			n &= 0x1f;			if(n == 7 || n == 8){				/*				 * FIXME not sure whether that is correct (most likely not)				 * flush everything on sps/pps				 * obviously, there might be multiple NALs in a single stream frame				 */				while(a->iNumOfPicts > 0){					h264flush(a);					ts = a->info.uiOutYuvTimeStamp;					if(ts < lasttimestamp){						/* FIXME this happens in some videos... */						//werrstr("wrong timestamp at flush: %llud < %llud", ts, lasttimestamp);						//res = -1;						//break;						continue;					}					if(sendframe(a, (ts - lasttimestamp) * d->timebase * 1000000000ULL, d->frames) < 0)						goto done;					lasttimestamp = ts;				}				if(res < 0)					break;			}		} 		start = nanosec();		if((res = h264decode(a, sf.buf, sf.sz, &sf.timestamp)) != 0)			break;		sf.buf = nil;		sf.sz = 0;		if((res = h264decode(a, sf.buf, sf.sz, &sf.timestamp)) != 0)			break;		d->decodetime = nanosec() - start; 		if(a->data[0] == nil || sf.timestamp < lasttimestamp)			continue; 		if(sendframe(a, (sf.timestamp - lasttimestamp) * d->timebase * 1000000000ULL, d->frames) < 0)			goto done;		lasttimestamp = sf.timestamp;	}	if(res != 0)		fprint(2, "h264: frame %llud: %r\n", framenum);	else{		/* FIXME the frames are finished but there might still be left-overs */		ResetReorderingPictureBuffers(a, a->pics, false);		WelsResetRefPic(&a->ctx);	} done:	WelsEndDecoder(&a->ctx);	free(a);	c = d->finished;	sendp(c, res == 0 ? nil : "error");	chanclose(c); 	threadexits(nil);} static inth264open(Decoder *d){	H264Aux *a;	int res; 	a = calloc(1, sizeof(*a));	a->ctx.pLastDecPicInfo = &a->pic;	a->ctx.pVlcTable = &a->vlctbl;	a->ctx.pDecoderStatistics = &a->stat;	a->ctx.pMemAlign = &cMemoryAlign;	a->ctx.pPictInfoList = a->pics;	a->ctx.pPictReoderingStatus = a;	a->logctx.pfLog = logfun;	a->ctx.sLogCtx = a->logctx; 	WelsDecoderDefaults(&a->ctx, &a->logctx);	WelsDecoderSpsPpsDefaults(&a->ctx.sSpsPpsCtx); 	a->ctx.pParam = calloc(1, sizeof(SDecodingParam));	a->ctx.pParam->sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT; 	if((res = WelsInitDecoder(&a->ctx, &a->logctx)) != 0){		werrstr("WelsInitDecoder: %s", h264err2s(res));		free(a);		return -1;	}	ResetReorderingPictureBuffers(a, a->pics, true);	d->aux = a;	proccreate(decode, d, 65536); 	return res;} static voidh264close(Decoder *d){	USED(d);} Decoderops h264ops = {	.open = h264open,	.close = h264close,};

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t