ref: 52f33c04acdec0e9123f9566f6eddfa86d707cdb
parent: 978f94bf9b2f384157f14c3ee436206a5d6b6450
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Mon Dec 14 10:05:06 EST 2020
copy YUV frames and convert to rgb on main thread
--- a/decoder_av1.c
+++ b/decoder_av1.c
@@ -79,11 +79,8 @@
werrstr("unsupported bits per component: %d", pic.p.bpc);
res = -1;
break;
- }else if((f = malloc(sizeof(*f) + pic.p.w*pic.p.h*3)) != nil){
- f->w = pic.p.w;
- f->h = pic.p.h;
+ }else if((f = newframe(pic.p.w, pic.p.h, pic.data, pic.stride[0], pic.stride[1])) != nil){
memset(&f->crop, 0, sizeof(f->crop));
- yuv420_rgb24(f->w, f->h, pic.data[0], pic.data[1], pic.data[2], pic.stride[0], pic.stride[1], f->rgb, f->w*3);
f->dt = (pic.m.timestamp - lasttimestamp) * d->timebase * 1000000000ULL;
lasttimestamp = pic.m.timestamp;
dav1d_picture_unref(&pic);
--- a/decoder_h264.c
+++ b/decoder_h264.c
@@ -192,17 +192,14 @@
w = a->info.UsrData.sSystemBuffer.iWidth;
h = a->info.UsrData.sSystemBuffer.iHeight;
- if((f = malloc(sizeof(*f) + w*h*3)) == nil)
+ stride = a->info.UsrData.sSystemBuffer.iStride;
+ if((f = newframe(w, h, a->data, stride[0], stride[1])) == nil)
continue;
- stride = a->info.UsrData.sSystemBuffer.iStride;
- f->w = w;
- f->h = h;
f->crop.left = a->ctx.sFrameCrop.iLeftOffset;
f->crop.top = a->ctx.sFrameCrop.iTopOffset;
f->crop.right = a->ctx.sFrameCrop.iRightOffset;
f->crop.bottom = a->ctx.sFrameCrop.iBottomOffset;
- yuv420_rgb24(w, h, a->data[0], a->data[1], a->data[2], stride[0], stride[1], f->rgb, w*3);
f->dt = (sf.timestamp - lasttimestamp) * d->timebase * 1000000000ULL;
lasttimestamp = sf.timestamp;
--- a/decoder_vpx.c
+++ b/decoder_vpx.c
@@ -53,17 +53,14 @@
break;
}
- if((f = malloc(sizeof(*f) + im->w*im->h*3)) != nil){
- f->w = im->w;
- f->h = im->h;
+ if((f = newframe(im->w, im->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;
- yuv420_rgb24(im->d_w, im->d_h, im->planes[0], im->planes[1], im->planes[2], im->stride[0], im->stride[1], f->rgb, f->w*3);
- vpx_img_free(im);
f->dt = (sf.timestamp - lasttimestamp) * d->timebase * 1000000000ULL;
lasttimestamp = sf.timestamp;
+ vpx_img_free(im);
if(sendp(d->frames, f) < 0){
free(f);
--- /dev/null
+++ b/frame.c
@@ -1,0 +1,25 @@
+#include <u.h>
+#include <libc.h>
+#include "frame.h"
+
+Frame *
+newframe(int w, int h, u8int *yuv[3], int ystride, int uvstride)
+{
+ Frame *f;
+
+ if((f = malloc(sizeof(*f) + (ystride+uvstride)*h)) == nil)
+ return nil;
+
+ f->w = w;
+ f->h = h;
+ f->yuv[0] = f->data;
+ memmove(f->yuv[0], yuv[0], ystride*h);
+ f->yuv[1] = f->data + ystride*h;
+ memmove(f->yuv[1], yuv[1], uvstride*h/2);
+ f->yuv[2] = f->data + ystride*h + uvstride*h/2;
+ memmove(f->yuv[2], yuv[2], uvstride*h/2);
+ f->ystride = ystride;
+ f->uvstride = uvstride;
+
+ return f;
+}
--- a/frame.h
+++ b/frame.h
@@ -6,5 +6,12 @@
struct {
int left, top, right, bottom;
}crop;
- u8int rgb[1];
+
+ u8int *yuv[3];
+ int ystride;
+ int uvstride;
+
+ u8int data[1];
};
+
+Frame *newframe(int w, int h, u8int *yuv[3], int ystride, int vstride);
--- a/main.c
+++ b/main.c
@@ -13,6 +13,7 @@
int mainstacksize = 128*1024;
static Image *curim;
+static u8int *rgb;
static uvlong lastframe;
static int audiofd = -1;
static Channel *audiosync;
@@ -59,9 +60,9 @@
lastframe = x;
end = lastframe + f->dt - dispdelay;
- if(dispdelay > 0 && x >= end+dispdelay){
+ if(x >= end+dispdelay){
late = x - (end+dispdelay);
- if(framedrop)
+ if(late > 0 && framedrop)
goto drop;
}else{
late = 0;
@@ -72,23 +73,28 @@
if(curim != nil && (Dx(curim->r) != f->w || Dy(curim->r) != f->h)){
freeimage(curim);
curim = nil;
+ free(rgb);
+ rgb = nil;
}
r = Rect(0,0,f->w,f->h);
if(curim == nil)
curim = allocimage(display, r, RGB24, 0, DNofill);
- loadimage(curim, r, f->rgb, f->w*f->h*3);
+ if(rgb == nil)
+ rgb = malloc(f->w*f->h*3);
+ yuv420_rgb24(f->w, f->h, f->yuv[0], f->yuv[1], f->yuv[2], f->ystride, f->uvstride, rgb, f->w*3);
+ loadimage(curim, r, rgb, f->w*f->h*3);
+ dispdelay = nanosec() - x;
+
while(1){
x = nanosec();
- if(x >= end)
+ if(x >= end - 1*1000ULL*1000ULL)
break;
left = end - x;
- if(left > 750000000ULL)
+ if(left > 80ULL*1000ULL*1000ULL)
sleep(70);
- else if(left > 250000000ULL)
+ else if(left > 30ULL*1000ULL*1000ULL)
sleep(20);
- else if(left > 100000000ULL)
- sleep(1);
}
clip = Rect(f->crop.left, f->crop.top, f->crop.right, f->crop.bottom);
@@ -96,7 +102,6 @@
clip = curim->r;
replclipr(curim, 0, clip);
- x = nanosec();
if(Dx(clip) < Dx(screen->r) && Dy(clip) < Dy(screen->r))
r = rectsubpt(screen->r, divpt(Pt(Dx(clip)-Dx(screen->r), Dy(clip)-Dy(screen->r)), 2));
else
@@ -107,7 +112,7 @@
flushimage(display, 1);
unlockdisplay(display);
- dispdelay = nanosec() - x;
+ dispdelay += nanosec() - x;
drop:
if(audiosync != nil)
sendp(audiosync, nil);
@@ -245,7 +250,7 @@
d->decodetime/1000000ULL,
dispdelay/1000000ULL,
yuv→rgb/1000000ULL,
- (d->decodetime + dispdelay + yuv→rgb)/1000000ULL,
+ (d->decodetime + dispdelay)/1000000ULL,
late/1000000ULL,
frame->w, frame->h,
d->info,
--- a/mkfile
+++ b/mkfile
@@ -19,6 +19,7 @@
decoder_av1.$O\
decoder_h264.$O\
decoder_vpx.$O\
+ frame.$O\
main.$O\
misc.$O\
stream.$O\