shithub: mcfs

ref: 49dc43fd64bb77001494be6721380895f1bba971
dir: /extra/adtsdump.c/

View raw version
#include <u.h>
#include <libc.h>
#include <bio.h>

static char *objtype[] = {
	"aac main",
	"aac lc  ",
	"aac ssr ",
	"aac ltp ",
};

static char *rate[] = {
	"96000",
	"88200",
	"64000",
	"48000",
	"44100",
	"32000",
	"24000",
	"22050",
	"16000",
	"12000",
	"11025",
	"8000 ",
	"7350 ",
	"???  ",
	"???  ",
	"expl ",
};

static char *chan[] = {
	"AOT",
	"1  ",
	"2  ",
	"3  ",
	"4  ",
	"5  ",
	"6  ",
	"8  ",
	"???",
	"???",
	"???",
	"???",
	"???",
	"???",
	"???",
	"???",
};

static void
usage(void)
{
	fprint(2, "usage: %s [-h hxsz] [file.aac]\n", argv0);
	exits("usage");
}

void
main(int argc, char **argv)
{
	int hxsz, fd, d, n, sz;
	Biobuf in, out;
	u8int b[7], *h;

	hxsz = 0;
	ARGBEGIN{
	case 'h':
		if((hxsz = atoi(EARGF(usage()))) > 0){
			fmtinstall('H', encodefmt);
			break;
		}
	default:
		usage();
	}ARGEND

	fd = 0;
	if(argc == 1){
		if((fd = open(*argv, OREAD)) < 0)
			sysfatal("%r");
	}else if(argc != 0)
		usage();

	if((h = malloc(hxsz)) == nil)
		sysfatal("memory");

	Binit(&in, fd, OREAD);
	Binit(&out, 1, OWRITE);
	fmtinstall('H', encodefmt);

	for(;;){
		if((n = Bread(&in, b, 7)) == 0)
			break;
		if(n < 0)
			goto err;
		if(n != 7){
			werrstr("short ADTS: %d != 7", n);
			goto err;
		}

		if(b[0] != 0xff || (b[0]&0xf0) != 0xf0){
			werrstr("invalid syncword %2x%02x", b[0], b[1]);
			goto err;
		}
		sz = (b[3]&3)<<11 | b[4]<<3 | b[5]>>5;
		sz -= 7;
		Bprint(&out, "%s %s %s %s %d %d",
			(b[1]&8) ? "mpeg2" : "mpeg4",
			objtype[b[2]>>6],
			rate[(b[2]>>2)&0xf],
			chan[(b[2]&3)<<2 | b[3]>>6],
			sz - ((b[1]&1) == 0 ? 2 : 0),
			(b[6]&3)+1
		);
		if((b[1]&1) == 0){ /* skip crc */
			if((n = Bread(&in, b, 2)) != 2){ 
				werrstr("short ADTS.crc: %d != 2", n);
				goto err;
			}
			sz -= 2;
		}
		d = sz < hxsz ? sz : hxsz;
		sz -= d;
		if(d > 0){
			if((n = Bread(&in, h, d)) != d){
				werrstr("short read: %d != %d", n, d);
				goto err;
			}
			Bprint(&out, " [%.*H]", d, h);
		}
		Bprint(&out, "\n");
		if(Bseek(&in, sz, 1) < 0)
			goto err;
	}

	Bterm(&out);
	Bterm(&in);

	exits(nil);
err:
	fprint(2, "%s: %r (at %#llx)\n", fd == 0 ? "stdin" : *argv, Boffset(&in));
	exits("error");
}