refactor unicast streaming, solve flickering frame issue

This commit is contained in:
niels
2015-04-27 21:13:41 +02:00
parent 1c0c24b150
commit 340cedbf5f
4 changed files with 163 additions and 92 deletions

View File

@@ -147,13 +147,49 @@ void *reader_thread(void *data)
if(!error && retrieve == 2) {
lock(t);
t->buf = vj_client_read_i( v, t->buf,&(t->bufsize), &ret );
int ret = 0;
int strides[3] = { 0,0,0};
int compr_len = 0;
if( vj_client_read_frame_header( v, &(t->in_w), &(t->in_h), &(t->in_fmt), &compr_len, &strides[0],&strides[1],&strides[2]) == 0 ) {
error = 1;
}
if(!error) {
int need_rlock = 0;
if( compr_len <= 0 )
need_rlock = 1;
if( need_rlock ) {
lock(t);
}
if( t->bufsize < (t->in_w * t->in_h * 3) || t->buf == NULL ) {
t->bufsize = t->in_w * t->in_h * 3;
t->buf = (uint8_t*) realloc( t->buf, RUP8(t->bufsize));
}
ret = vj_client_read_frame_data( v, compr_len, strides[0], strides[1], strides[2], t->buf );
if( ret == 2 ) {
if(!need_rlock) {
lock(t);
vj_client_decompress_frame_data( v, t->buf, t->in_fmt, t->in_w, t->in_h, compr_len, strides[0],strides[1],strides[2] );
unlock(t);
}
}
if( need_rlock ) {
unlock(t);
}
}
// lock(t);
//t->buf = vj_client_read_i( v, t->buf,&(t->bufsize), &ret );
if(ret && t->buf) {
t->have_frame = 1;
t->in_fmt = v->in_fmt;
t->in_w = v->in_width;
t->in_h = v->in_height;
t->in_fmt = v->in_fmt;
t->in_w = v->in_width;
t->in_h = v->in_height;
retrieve = 0;
}
if( ret <= 0 || t->buf == NULL ) {
@@ -163,7 +199,7 @@ void *reader_thread(void *data)
error = 1;
}
}
unlock(t);
// unlock(t);
}
NETTHREADRETRY:
@@ -259,43 +295,25 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] )
have_frame = t->have_frame;
state = t->state;
if( state == 0 || have_frame == 0 || t->bufsize == 0 || t->buf == NULL ) {
if( state == 0 || t->bufsize == 0 || t->buf == NULL ) {
unlock(t);
return 1; // not active or no frame
}
} // just continue when t->have_frame == 0
//@ color space convert frame
int len = t->w * t->h;
int b_len = t->in_w * t->in_h;
int buvlen = b_len;
if( (b_len*3) > tag->socket_len ) {
tag->socket_frame =
(uint8_t*) realloc( tag->socket_frame, RUP8(b_len*3) );
tag->socket_len = b_len*3;
}
if( PIX_FMT_YUV420P == t->in_fmt || PIX_FMT_YUVJ420P == t->in_fmt )
buvlen = b_len/4;
else
buvlen = b_len/2;
if( t->in_fmt == PIX_FMT_RGB24 || t->in_fmt == PIX_FMT_BGR24 || t->in_fmt == PIX_FMT_RGBA || t->in_fmt == PIX_FMT_RGB32_1 ) {
if( t->a == NULL )
t->a = yuv_yuv_template( t->buf, t->buf + b_len, t->buf+ b_len+ buvlen,t->in_w,t->in_h, t->in_fmt);
if(t->a == NULL )
t->a = yuv_rgb_template( tag->socket_frame, t->in_w, t->in_w, t->in_fmt );
} else {
if( t->b == NULL ) {
if( PIX_FMT_YUV420P == t->in_fmt || PIX_FMT_YUVJ420P == t->in_fmt )
buvlen = b_len/4;
else
buvlen = b_len/2;
t->a = yuv_yuv_template( t->buf, t->buf + b_len, t->buf+ b_len+ buvlen,t->in_w,t->in_h, t->in_fmt);
}
}
if( t->b == NULL ) {
if( t->b == NULL )
t->b = yuv_yuv_template( buffer[0],buffer[1], buffer[2],t->w,t->h,t->f);
}
if( t->scaler == NULL ) {
sws_template sws_templ;
@@ -312,56 +330,6 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] )
return 1;
}
int net_thread_get_frame_rgb( vj_tag *tag, uint8_t *buffer, int w, int h )
{
threaded_t *t = (threaded_t*) tag->priv;
int have_frame = 0;
int state = 0;
lock(t);
have_frame = t->have_frame;
state= t->state;
if( state == 0 || have_frame == 0 ) {
unlock(t);
return 1;
}
int len = t->w * t->h;
int uv_len = len;
int b_len = t->in_w * t->in_h;
int buvlen = b_len;
if( PIX_FMT_YUV420P == t->f || PIX_FMT_YUVJ420P == t->f )
uv_len = len/4;
else
uv_len = len/2;
if(t->have_frame )
{
if( PIX_FMT_YUV420P == t->in_fmt || PIX_FMT_YUVJ420P == t->in_fmt )
buvlen = b_len/4;
else
buvlen = b_len/2;
if( t->a == NULL ) {
t->a = yuv_yuv_template( tag->socket_frame, tag->socket_frame + b_len, tag->socket_frame+b_len+buvlen,t->in_w,t->in_h, t->in_fmt);
}
if( t->b == NULL ) {
t->b = yuv_rgb_template( buffer,w,h,PIX_FMT_RGB24);
}
yuv_convert_any_ac(t->a,t->b, t->a->format,t->b->format );
}
unlock(t);
return 1;
}
int net_thread_start(vj_tag *tag, int wid, int height, int pixelformat)
{
if(tag->source_type == VJ_TAG_TYPE_MCAST ) {

View File

@@ -25,7 +25,6 @@ void net_thread_stop(vj_tag *tag);
int net_thread_start(vj_tag *tag, int w, int h, int f);
void net_thread_remote(void *priv, void *p );
int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3]);
int net_thread_get_frame_rgb( vj_tag *tag, uint8_t *buffer, int w, int h);
void net_thread_exit(vj_tag *tag);
void *net_threader(VJFrame *frame);

View File

@@ -232,14 +232,6 @@ static long vj_client_decompress( vj_client *t,uint8_t *in, uint8_t *out, int da
return total;
}
static uint32_t getint(uint8_t *in, int len ) {
char *ptr, *word = strndup( in, len+1 );
word[len] = '\0';
long v = strtol( word, &ptr, 10 );
free(word);
return (uint32_t) v;
}
/* packet negotation.
* read a small portion (44 bytes for veejay, its veejay's full header size)
* and try to identify which software is sending frames
@@ -288,6 +280,111 @@ static int vj_client_packet_negotiate( vj_client *v, int *tokens )
return 1;
}
int vj_client_read_frame_header( vj_client *v, int *w, int *h, int *fmt, int *compr_len, int *stride1,int *stride2, int *stride3 )
{
uint8_t line[128];
uint32_t p[4] = {0, 0,0,0 };
uint32_t strides[4] = { 0,0,0,0 };
int tokens[16];
memset( tokens,0,sizeof(tokens));
int result = vj_client_packet_negotiate( v, tokens );
if( result == 0 ) {
return 0;
}
if( tokens[0] <= 0 || tokens[1] <= 0 ) {
return 0;
}
*w = tokens[0];
*h = tokens[1];
*fmt=tokens[2];
*compr_len=tokens[3];
*stride1=tokens[4];
*stride2=tokens[5];
*stride3=tokens[6];
v->in_width = *w;
v->in_height = *h;
v->in_fmt = *fmt;
return 1;
}
int vj_client_read_frame_data( vj_client *v, int compr_len, int stride1,int stride2, int stride3, uint8_t *dst )
{
int datalen = (compr_len > 0 ? compr_len : stride1+stride2+stride3);
if( (compr_len > 0) && ( v->space == NULL || v->space_len < compr_len) ) {
if( v->space ) {
free(v->space);
v->space = NULL;
}
v->space_len = RUP8( compr_len );
v->space = vj_calloc(sizeof(uint8_t) * v->space_len );
if(!v->space) {
veejay_msg(0,"Could not allocate memory for network stream.");
return 0;
}
}
if( compr_len > 0 ) {
int n = sock_t_recv( v->fd[0],v->space,datalen );
if( n <= 0 ) {
if( n == -1 ) {
veejay_msg(VEEJAY_MSG_ERROR, "Error '%s' while reading socket", strerror(errno));
} else {
veejay_msg(VEEJAY_MSG_DEBUG,"Remote closed connection");
}
return 0;
}
if( n != compr_len && n > 0 )
{
veejay_msg(VEEJAY_MSG_ERROR, "Broken video packet , got %d out of %d bytes",n, compr_len );
return 0;
}
return 2;
}
else {
int n = sock_t_recv( v->fd[0], dst, datalen );
if( n != (stride1 + stride2 + stride3) )
{
return 0;
}
return 1;
}
return 0;
}
void vj_client_decompress_frame_data( vj_client *v, uint8_t *dst, int fmt, int w, int h, int compr_len, int stride1, int stride2, int stride3 )
{
int y_len = w * h;
int uv_len = 0;
switch(fmt) //@ veejay is sending compressed YUV data, calculate UV size
{
case PIX_FMT_YUV422P:
case PIX_FMT_YUVJ422P:
uv_len = y_len / 2;
break;
case PIX_FMT_YUV420P:
case PIX_FMT_YUVJ420P:
uv_len = y_len / 4;
break;
default:
uv_len = y_len;
break;
}
//@ decompress YUV buffer
vj_client_decompress( v, v->space, dst, compr_len, y_len, uv_len ,0, stride1,stride2,stride3);
}
uint8_t *vj_client_read_i( vj_client *v, uint8_t *dst, ssize_t *dstlen, int *ret )
{

View File

@@ -78,5 +78,12 @@ int vj_client_window_sizes( int socket_fd, int *r, int *s );
int vj_client_connect_dat(vj_client *v, char *host, int port_id );
void vj_client_decompress_frame_data( vj_client *v, uint8_t *dst, int fmt, int w, int h, int compr_len, int stride1, int stride2, int stride3 );
int vj_client_read_frame_data( vj_client *v, int compr_len, int stride1,int stride2, int stride3, uint8_t *dst );
int vj_client_read_frame_header( vj_client *v, int *w, int *h, int *fmt, int *compr_len, int *stride1,int *stride2, int *stride3 );
#endif