ref: 66c086c68d190935c0113735278a99b100bf07da
dir: /decoder_h264.c/
#include <h264bsd_decoder.h>
#include <h264bsd_util.h>
#include <thread.h>
#include "frame.h"
#include "stream.h"
#include "decoder.h"
#include "misc.h"
#pragma lib "../h264bsd/src/libh264bsd.$M.a"
typedef struct Aux Aux;
struct Aux {
storage_t c;
};
static void
decode(void *x)
{
uvlong lasttimestamp;
Decoder *d;
Channel *c;
Frame *f;
Streamframe sf;
Aux *a;
int res, off;
u32int used, nerr, isidr, picid;
u32int realw, realh, w, h, crop, left, top;
u8int *pic;
d = x;
a = d->aux;
lasttimestamp = 0;
realw = 0;
realh = 0;
for(res = 0; res >= 0 && (res = Sread(d->s, &sf)) == 0 && sf.sz > 0;){
off = 0;
next:
if((res = h264bsdDecode(&a->c, sf.buf+off, sf.sz-off, 0, &used)) < 0){
werrstr("h264bsdDecode: %r (%d)", res);
break;
}
off += used;
switch(res){
case H264BSD_PIC_RDY:
if((pic = h264bsdNextOutputPicture(&a->c, &picid, &isidr, &nerr)) == nil){
werrstr("nil pic");
res = -1;
}else if((f = malloc(sizeof(*f) + w*h*3)) != nil){
f->w = w;
f->h = realh;
f->crop.left = left;
f->crop.top = top;
f->crop.right = realw;
f->crop.bottom = realh;
yuv420_rgb24(w, h, pic, pic+w*h, pic+w*h*5/4, w, w/2, f->rgb, w*3);
f->dt = (sf.timestamp - lasttimestamp) * d->timebase * 1000000000ULL;
lasttimestamp = sf.timestamp;
if(sendp(d->frames, f) < 0){
free(f);
goto done;
}
}
break;
case H264BSD_HDRS_RDY:
h264bsdCroppingParams(&a->c, &crop, &left, &w, &top, &h);
if(!crop){
w = h264bsdPicWidth(&a->c) * 16;
h = h264bsdPicHeight(&a->c) * 16;
}
realw = w;
realh = h;
if(w & 15)
w += 16 - (w & 15);
if(h & 15)
h += 16 - (h & 15);
break;
case H264BSD_RDY:
break;
case H264BSD_ERROR:
res = -1;
werrstr("decoding error: %r");
break;
case H264BSD_PARAM_SET_ERROR:
res = -1;
werrstr("param set error: %r");
break;
}
if(off < sf.sz)
goto next;
}
if(res != 0)
fprint(2, "h264: %r\n");
done:
h264bsdShutdown(&a->c);
free(a);
c = d->finished;
sendp(c, res == 0 ? nil : "error");
chanclose(c);
threadexits(nil);
}
static int
h264open(Decoder *d)
{
Aux *a;
int res;
a = calloc(1, sizeof(*a));
if((res = h264bsdInit(&a->c, HANTRO_FALSE)) != 0){
werrstr("h264bsdInit: %d", res);
free(a);
return -1;
}
d->aux = a;
proccreate(decode, d, 65536);
return res;
}
static void
h264close(Decoder *d)
{
USED(d);
}
Decoderops h264ops = {
.open = h264open,
.close = h264close,
};