mirror of
https://github.com/game-stop/veejay.git
synced 2025-12-16 21:00:00 +01:00
refactor unicast streaming, solve flickering frame issue
This commit is contained in:
@@ -147,8 +147,44 @@ void *reader_thread(void *data)
|
|||||||
|
|
||||||
|
|
||||||
if(!error && retrieve == 2) {
|
if(!error && retrieve == 2) {
|
||||||
|
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);
|
lock(t);
|
||||||
t->buf = vj_client_read_i( v, t->buf,&(t->bufsize), &ret );
|
}
|
||||||
|
|
||||||
|
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) {
|
if(ret && t->buf) {
|
||||||
t->have_frame = 1;
|
t->have_frame = 1;
|
||||||
t->in_fmt = v->in_fmt;
|
t->in_fmt = v->in_fmt;
|
||||||
@@ -163,7 +199,7 @@ void *reader_thread(void *data)
|
|||||||
error = 1;
|
error = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unlock(t);
|
// unlock(t);
|
||||||
}
|
}
|
||||||
NETTHREADRETRY:
|
NETTHREADRETRY:
|
||||||
|
|
||||||
@@ -259,43 +295,25 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] )
|
|||||||
have_frame = t->have_frame;
|
have_frame = t->have_frame;
|
||||||
state = t->state;
|
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);
|
unlock(t);
|
||||||
return 1; // not active or no frame
|
return 1; // not active or no frame
|
||||||
}
|
} // just continue when t->have_frame == 0
|
||||||
|
|
||||||
//@ color space convert frame
|
//@ color space convert frame
|
||||||
int len = t->w * t->h;
|
|
||||||
int b_len = t->in_w * t->in_h;
|
int b_len = t->in_w * t->in_h;
|
||||||
int buvlen = b_len;
|
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( 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_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 )
|
if( PIX_FMT_YUV420P == t->in_fmt || PIX_FMT_YUVJ420P == t->in_fmt )
|
||||||
buvlen = b_len/4;
|
buvlen = b_len/4;
|
||||||
else
|
else
|
||||||
buvlen = b_len/2;
|
buvlen = b_len/2;
|
||||||
|
|
||||||
|
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);
|
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);
|
t->b = yuv_yuv_template( buffer[0],buffer[1], buffer[2],t->w,t->h,t->f);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if( t->scaler == NULL ) {
|
if( t->scaler == NULL ) {
|
||||||
sws_template sws_templ;
|
sws_template sws_templ;
|
||||||
@@ -312,56 +330,6 @@ int net_thread_get_frame( vj_tag *tag, uint8_t *buffer[3] )
|
|||||||
return 1;
|
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)
|
int net_thread_start(vj_tag *tag, int wid, int height, int pixelformat)
|
||||||
{
|
{
|
||||||
if(tag->source_type == VJ_TAG_TYPE_MCAST ) {
|
if(tag->source_type == VJ_TAG_TYPE_MCAST ) {
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ void net_thread_stop(vj_tag *tag);
|
|||||||
int net_thread_start(vj_tag *tag, int w, int h, int f);
|
int net_thread_start(vj_tag *tag, int w, int h, int f);
|
||||||
void net_thread_remote(void *priv, void *p );
|
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( 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_thread_exit(vj_tag *tag);
|
||||||
void *net_threader(VJFrame *frame);
|
void *net_threader(VJFrame *frame);
|
||||||
|
|
||||||
|
|||||||
@@ -232,14 +232,6 @@ static long vj_client_decompress( vj_client *t,uint8_t *in, uint8_t *out, int da
|
|||||||
return total;
|
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.
|
/* packet negotation.
|
||||||
* read a small portion (44 bytes for veejay, its veejay's full header size)
|
* read a small portion (44 bytes for veejay, its veejay's full header size)
|
||||||
* and try to identify which software is sending frames
|
* 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;
|
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 )
|
uint8_t *vj_client_read_i( vj_client *v, uint8_t *dst, ssize_t *dstlen, int *ret )
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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 );
|
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
|
#endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user