~ft/treason

ref: c1156352ba4eceae2ec875fd06fc94c38c92271f treason/decoder_vpx.c -rw-r--r-- 2.1 KiB
c1156352 — Sigrid Solveig Haflínudóttir info: mixed up dispdelay and yuv→rgb, fix it 1 year, 1 month ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include <vpx_codec.h>
#include <vpx_decoder.h>
#include <vpx_image.h>
#include <vp8dx.h>
#include "frame.h"
#include "stream.h"
#include "decoder.h"
#include "misc.h"

#pragma lib "../libvpx/libvpx.$M.a"

typedef struct Aux Aux;

struct Aux {
	vpx_codec_ctx_t ctx;
};

static void
decode(void *x)
{
	uvlong lasttimestamp;
	Decoder *d;
	Channel *c;
	Frame *f;
	Streamframe sf;
	Aux *a;
	int res;
	u8int *pic;
    vpx_codec_iter_t iter;
    uvlong start;
    vpx_image_t *im;

	threadsetname("decoder/vpx");
	d = x;
	a = d->aux;
	lasttimestamp = 0;
	memset(&pic, 0, sizeof(pic));
	for(res = 0; res >= 0 && (res = Sread(d->s, &sf)) == 0 && sf.sz > 0;){
		start = nanosec();
		if((res = vpx_codec_decode(&a->ctx, sf.buf, sf.sz, NULL, 0)) != 0){
			werrstr("vpx_codec_decode failed");
			break;
		}
		d->decodetime = nanosec() - start;

		for(iter = nil;;){
			if((im = vpx_codec_get_frame(&a->ctx, &iter)) == nil)
				break;
			if(im->fmt != VPX_IMG_FMT_I420){
				vpx_img_free(im);
				werrstr("images other than YUV420 aren't supported");
				res = -1;
				break;
			}

			if((f = newframe(im->d_w, im->d_h, im->planes, im->stride[0], im->stride[1])) != nil){
				f->crop.left = 0;
				f->crop.top = 0;
				f->crop.right = im->d_w;
				f->crop.bottom = im->d_h;
				f->dt = (sf.timestamp - lasttimestamp) * d->timebase * 1000000000ULL;
				lasttimestamp = sf.timestamp;
				vpx_img_free(im);

				if(sendp(d->frames, f) < 0){
					free(f);
					goto done;
				}
			}
		}
	}
	if(res != 0)
		fprint(2, "vpx: %r\n");

done:
	vpx_codec_destroy(&a->ctx);
	free(a);
	c = d->finished;
	sendp(c, res == 0 ? nil : "error");
	chanclose(c);

	threadexits(nil);
}

static int
vpxopen(Decoder *d)
{
	Aux *a;
	vpx_codec_iface_t *iface;
	vpx_codec_dec_cfg_t cfg = {nproc, 0, 0};

	a = calloc(1, sizeof(*a));
	iface = d->s->fmt == FmtVP9 ? vpx_codec_vp9_dx() : vpx_codec_vp8_dx();

	if(vpx_codec_dec_init(&a->ctx, iface, &cfg, 0) != 0){
		werrstr("vpx_codec_dec_init failed");
		free(a);
		return -1;
	}

	d->aux = a;
	proccreate(decode, d, 65536);

	return 0;
}

static void
vpxclose(Decoder *d)
{
	USED(d);
}

Decoderops vpxops = {
	.open = vpxopen,
	.close = vpxclose,
};