159 lines · 3.7 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <bio.h>#include "common.h"#include "packet.h" static intpacket(Biobuf *out, Packetctx *ctx, int htype, Packet *p, int np, uvlong granule){	/*                 magic            ver  htype  granule          serial   seq      checksum  page segments  segsz */	/*         segsz   0                4    5      6                14       18       22        26             27 */	u8int h[28+255] = {'O','g','g','S', 0,   0,     0,0,0,0,0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,  0,             0};	u32int crc;	int psz, i, n, ntot, ip; 	if(ctx->frid == 0 && ctx->fmt == FmtTheora && np > 0 && p->sz > 41){		if(memcmp(p->data, "\x80theora", 7) != 0){			werrstr("invalid Theora packet");			return -1;		}		ctx->kfgshift = ((p->data[40]<<8 | p->data[41]) >> 5) & 0x1f;	} 	h[5] = htype;	h[6] = granule;	h[7] = granule >> 8;	h[8] = granule >> 16;	h[9] = granule >> 24;	h[10] = granule >> 32;	h[11] = granule >> 40;	h[12] = granule >> 48;	h[13] = granule >> 56;	h[14] = ctx->trackuid;	h[15] = ctx->trackuid >> 8;	h[16] = ctx->trackuid >> 16;	h[17] = ctx->trackuid >> 24;	h[18] = ctx->frid;	h[19] = ctx->frid >> 8;	h[20] = ctx->frid >> 16;	h[21] = ctx->frid >> 24;	ctx->frid++;	h[22] = 0;	h[23] = 0;	h[24] = 0;	h[25] = 0; 	for(ntot = ip = 0; ip < np; ip++){		n = 1 + p[ip].sz/255;		if(27+ntot+n >= nelem(h)){			werrstr("frame is too large");			return -1;		}		for(i = 0, psz = p[ip].sz; i < n; i++){			h[27+ntot+i] = min(255, psz);			if(psz == 0)				break;			psz -= h[27+ntot+i];		}		ntot += n;	}	h[26] = ntot;	ntot += 27; 	for(ip = 0, crc = crc32(0, h, ntot); ip < np; ip++)		crc = crc32(crc, p[ip].data, p[ip].sz); 	h[22] = crc >> 24;	h[23] = crc >> 16;	h[24] = crc >> 8;	h[25] = crc;	if(Bwrite(out, h, ntot) != ntot)		return -1;	for(ip = 0; ip < np; ip++){		if(Bwrite(out, p[ip].data, p[ip].sz) != p[ip].sz)			return -1;	} 	return 0;} intoggpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key){	/*                     magic                            vendor len   list len */	u8int opuscomment[] = {'O','p','u','s','T','a','g','s', 0,0,0,0,     0,0,0,0};	int i, nsg, dsz, total;	u8int *d;	u64int gr;	int sgszs[4];	Packet onep; 	USED(key);	ts += ctx->seekpreroll - ctx->discardpad; 	if(ctx->frid == 0){ /* first packet? */		d = ctx->codec.priv.data;		dsz = ctx->codec.priv.sz; 		if(dsz < 1){			werrstr("codec private data missing");			goto err;		} 		/* id/codec setup header always goes first */		if(ctx->fmt == FmtVorbis || ctx->fmt == FmtTheora){			i = *d++;			dsz--;			for(nsg = 0, total = 0; i > 0 && dsz > 0; total += sgszs[nsg], nsg++){				sgszs[nsg] = 0;				do{					sgszs[nsg] += *d;					dsz--;					i--;				}while(*d++ == 0xff);			}			if(total > dsz){				werrstr("setup data out of bounds");				goto err;			}			for(i = 0; i < nsg && dsz > 0; d += sgszs[i], dsz -= sgszs[i], i++){				onep.data = d;				onep.sz = sgszs[i];				if(packet(out, ctx, i == 0 ? 2 : 0, &onep, 1, 0) != 0)					goto err;			}		}		if(dsz > 0){ /* either leftovers or other codecs, write as is */			onep.data = d;			onep.sz = dsz;			if(packet(out, ctx, 2, &onep, 1, 0) != 0)				goto err;		}		if(ctx->fmt == FmtOpus){ /* Opus requires a comment */			onep.data = opuscomment;			onep.sz = sizeof(opuscomment);			if(packet(out, ctx, 0, &onep, 1, 0) != 0)				goto err;		}	} 	if(ctx->fmt == FmtTheora){		ctx->nonkey++; /* FIXME VREV 1 vs 0 diff here, to make it work with 0 */		if(key){			ctx->key += ctx->nonkey;			ctx->nonkey = 0;		}		gr = (uvlong)ctx->key<<ctx->kfgshift | ctx->nonkey;	}else{		gr = (ts * 48) / 1000000;	} 	if(np > 0 && packet(out, ctx, ctx->discardpad ? 4 : 0, p, np, gr) != 0)		goto err; 	return 0;err:	werrstr("oggpacket: %r");	return -1;}

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