diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/Makefile | 7 | ||||
-rw-r--r-- | modules/Makefile.in | 7 | ||||
-rw-r--r-- | modules/pdp_ascii.c | 1 | ||||
-rw-r--r-- | modules/pdp_compose.c | 47 | ||||
-rw-r--r-- | modules/pdp_ctrack.c | 4 | ||||
-rw-r--r-- | modules/pdp_ffmpeg~.c | 42 | ||||
-rw-r--r-- | modules/pdp_form.c | 18 | ||||
-rw-r--r-- | modules/pdp_i.c | 49 | ||||
-rw-r--r-- | modules/pdp_live~.c | 324 | ||||
-rw-r--r-- | modules/pdp_o.c | 25 | ||||
-rw-r--r-- | modules/pdp_ocanvas.c | 22 | ||||
-rw-r--r-- | modules/pdp_pen.c | 22 | ||||
-rw-r--r-- | modules/pdp_rec~.c | 5 | ||||
-rw-r--r-- | modules/pdp_shape.c | 29 | ||||
-rw-r--r-- | modules/pdp_text.c | 20 | ||||
-rw-r--r-- | modules/pdp_underwatch.c | 7 | ||||
-rw-r--r-- | modules/pdp_yqt.c | 5 |
17 files changed, 439 insertions, 195 deletions
diff --git a/modules/Makefile b/modules/Makefile index 1bca11a..66847ff 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -15,7 +15,10 @@ OBJECTS = pdp_intrusion.o pdp_yqt.o pdp_simura.o pdp_underwatch.o \ pdp_capture.o pdp_smuck.o pdp_lumafilt.o \ pdp_transition.o pdp_imgloader.o pdp_imgsaver.o pdp_cache.o \ pdp_canvas.o pdp_pen.o pdp_shape.o pdp_fqt.o pdp_fcqt.o \ - pdp_ocanvas.o pdp_spotlight.o pdp_colorgrid.o pdp_live~.o pdp_ffmpeg~.o - # pdp_xcanvas.o pdp_aa.o + pdp_ocanvas.o pdp_spotlight.o pdp_colorgrid.o \ + pdp_binary.o pdp_erode.o pdp_dilate.o pdp_hitandmiss.o \ + pdp_disintegration.o pdp_distance.o pdp_theorin~.o \ + pdp_theorout~.o pdp_cropper.o pdp_background.o \ + pdp_live~.o pdp_ffmpeg~.o # pdp_xcanvas.o pdp_aa.o all_modules: $(OBJECTS) diff --git a/modules/Makefile.in b/modules/Makefile.in index 7d9daad..56fe02b 100644 --- a/modules/Makefile.in +++ b/modules/Makefile.in @@ -15,7 +15,10 @@ OBJECTS = pdp_intrusion.o pdp_yqt.o pdp_simura.o pdp_underwatch.o \ pdp_capture.o pdp_smuck.o pdp_lumafilt.o \ pdp_transition.o pdp_imgloader.o pdp_imgsaver.o pdp_cache.o \ pdp_canvas.o pdp_pen.o pdp_shape.o pdp_fqt.o pdp_fcqt.o \ - pdp_ocanvas.o pdp_spotlight.o pdp_colorgrid.o @PDP_STREAMING_OBJECTS@ - # pdp_xcanvas.o pdp_aa.o + pdp_ocanvas.o pdp_spotlight.o pdp_colorgrid.o \ + pdp_binary.o pdp_erode.o pdp_dilate.o pdp_hitandmiss.o \ + pdp_disintegration.o pdp_distance.o pdp_theorin~.o \ + pdp_theorout~.o pdp_cropper.o pdp_background.o \ + @PDP_STREAMING_OBJECTS@ # pdp_xcanvas.o pdp_aa.o all_modules: $(OBJECTS) diff --git a/modules/pdp_ascii.c b/modules/pdp_ascii.c index a43956c..e81d3f2 100644 --- a/modules/pdp_ascii.c +++ b/modules/pdp_ascii.c @@ -27,6 +27,7 @@ #include "yuv.h" #include "default.map" #include <math.h> +#include <stdio.h> #define LINE_MAX_LENGTH 1024 diff --git a/modules/pdp_compose.c b/modules/pdp_compose.c index aad03a9..998c3a3 100644 --- a/modules/pdp_compose.c +++ b/modules/pdp_compose.c @@ -61,7 +61,9 @@ typedef struct pdp_compose_struct t_float x_f; t_int x_packet0; + t_int x_packet1; t_int x_dropped; + t_int x_queue_id; t_int x_vwidth; t_int x_vheight; @@ -228,6 +230,8 @@ static void pdp_compose_process_yv12(t_pdp_compose *x) { t_pdp *header = pdp_packet_header(x->x_packet0); short int *data = (short int *)pdp_packet_data(x->x_packet0); + t_pdp *newheader = pdp_packet_header(x->x_packet1); + short int *newdata = (short int *)pdp_packet_data(x->x_packet1); t_int i, cf; t_int px=0, py=0, ppx=0, ppy=0, found=0, xcell=0, ycell=0; t_int celldiff=0, cellwidth=0, cellheight=0; @@ -285,9 +289,9 @@ static void pdp_compose_process_yv12(t_pdp_compose *x) pfY = x->x_frame; pfV = x->x_frame+x->x_vsize; pfU = x->x_frame+x->x_vsize+(x->x_vsize>>2); - pdY = data; - pdV = data+x->x_vsize; - pdU = data+x->x_vsize+(x->x_vsize>>2); + pdY = newdata; + pdV = newdata+x->x_vsize; + pdU = newdata+x->x_vsize+(x->x_vsize>>2); prY = x->x_right_frame; prV = x->x_right_frame+x->x_vsize; prU = x->x_right_frame+x->x_vsize+(x->x_vsize>>2); @@ -326,11 +330,18 @@ static void pdp_compose_process_yv12(t_pdp_compose *x) } } - pdp_packet_pass_if_valid(x->x_pdp_output, &x->x_packet0); - return; } +static void pdp_compose_sendpacket(t_pdp_compose *x) +{ + pdp_packet_mark_unused(x->x_packet0); + x->x_packet0=-1; + + /* unregister and propagate if valid dest packet */ + pdp_packet_pass_if_valid(x->x_pdp_output, &x->x_packet1); +} + static void pdp_compose_process(t_pdp_compose *x) { int encoding; @@ -344,7 +355,8 @@ static void pdp_compose_process(t_pdp_compose *x) switch(pdp_packet_header(x->x_packet0)->info.image.encoding){ case PDP_IMAGE_YV12: - pdp_compose_process_yv12(x); + x->x_packet1 = pdp_packet_clone_rw(x->x_packet0); + pdp_queue_add(x, pdp_compose_process_yv12, pdp_compose_sendpacket, &x->x_queue_id); break; case PDP_IMAGE_GREY: @@ -365,20 +377,24 @@ static void pdp_compose_input_1(t_pdp_compose *x, t_symbol *s, t_floatarg f) { short int *rightdata = (short int *)pdp_packet_data((int)f); - if (s== gensym("register_rw")) memcpy(x->x_right_frame, rightdata, (x->x_vsize + (x->x_vsize>>1))<<1 ); + if ( s== gensym("register_rw") ) + { + memcpy(x->x_right_frame, rightdata, (x->x_vsize + (x->x_vsize>>1))<<1 ); + } + + pdp_packet_mark_unused( (int)f ); } static void pdp_compose_input_0(t_pdp_compose *x, t_symbol *s, t_floatarg f) { - /* if this is a register_ro message or register_rw message, register with packet factory */ - - if (s== gensym("register_rw")) + if ( s== gensym("register_rw") ) + { x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("image/YCrCb/*") ); + } - if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)){ - + if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)) + { pdp_compose_process(x); - } } @@ -386,7 +402,8 @@ static void pdp_compose_free(t_pdp_compose *x) { int i; - pdp_packet_mark_unused(x->x_packet0); + pdp_queue_finish(x->x_queue_id); + pdp_packet_mark_unused(x->x_packet1); pdp_compose_free_ressources( x ); } @@ -416,6 +433,8 @@ void *pdp_compose_new(void) x->x_colorV = (yuv_RGBtoV( (x->x_colorR << 16) + (x->x_colorG << 8) + x->x_colorB )-128)<<8; x->x_packet0 = -1; + x->x_packet1 = -1; + x->x_queue_id = -1; x->x_cursX = -1; x->x_cursY = -1; diff --git a/modules/pdp_ctrack.c b/modules/pdp_ctrack.c index ed35c9b..fa56ea6 100644 --- a/modules/pdp_ctrack.c +++ b/modules/pdp_ctrack.c @@ -86,8 +86,8 @@ typedef struct pdp_ctrack_struct t_outlet *x_x2; // output x2 coordinate of block which has been detected t_outlet *x_y2; // output y2 coordinate of block which has been detected t_outlet *x_R; // output R component of selected color - t_outlet *x_G; // output R component of selected color - t_outlet *x_B; // output R component of selected color + t_outlet *x_G; // output G component of selected color + t_outlet *x_B; // output B component of selected color t_canvas *x_canvas; diff --git a/modules/pdp_ffmpeg~.c b/modules/pdp_ffmpeg~.c index 58cdd61..3e229af 100644 --- a/modules/pdp_ffmpeg~.c +++ b/modules/pdp_ffmpeg~.c @@ -441,9 +441,18 @@ static void pdp_ffmpeg_process_yv12(t_pdp_ffmpeg *x) oheight = x->x_avcontext->streams[i]->codec.height; if (x->x_img_resample_ctx) img_resample_close(x->x_img_resample_ctx); + +#if LIBAVCODEC_BUILD > 4715 + x->x_img_resample_ctx = img_resample_full_init( + owidth, oheight, + x->x_vwidth, x->x_vheight, + 0, 0, 0, 0, + 0, 0, 0, 0); +#else x->x_img_resample_ctx = img_resample_full_init( owidth, oheight, x->x_vwidth, x->x_vheight, 0, 0, 0, 0); +#endif size = avpicture_get_size(x->x_avcontext->streams[i]->codec.pix_fmt, owidth, oheight ); @@ -472,6 +481,9 @@ static void pdp_ffmpeg_process_yv12(t_pdp_ffmpeg *x) // encode and send the picture { AVFrame aframe; +#if LIBAVCODEC_BUILD > 4715 + AVPacket vpkt; +#endif t_int fsize, ret; memset(&aframe, 0, sizeof(AVFrame)); @@ -482,7 +494,21 @@ static void pdp_ffmpeg_process_yv12(t_pdp_ffmpeg *x) fsize = avcodec_encode_video(&x->x_avcontext->streams[i]->codec, x->x_video_buffer, VIDEO_BUFFER_SIZE, &aframe); + +#if LIBAVCODEC_BUILD > 4715 + av_init_packet(&vpkt); + + vpkt.pts = aframe.pts; + if((&x->x_avcontext->streams[i]->codec)->coded_frame->key_frame) + vpkt.flags |= PKT_FLAG_KEY; + vpkt.stream_index= i; + vpkt.data= (uint8_t *)x->x_video_buffer; + vpkt.size= fsize; + + if ( ( ret = av_write_frame( x->x_avcontext, &vpkt) ) < 0 ) +#else if ( ( ret = av_write_frame( x->x_avcontext, i, x->x_video_buffer, fsize) ) < 0 ) +#endif { post ("pdp_ffmpeg~ : error : could not send frame : (ret=%d)", ret ); return; @@ -549,10 +575,26 @@ static void pdp_ffmpeg_process_yv12(t_pdp_ffmpeg *x) while (fifo_read(&x->x_audio_fifo[saudioindex], (uint8_t*)pencbuf, framebytes, &x->x_audio_fifo[saudioindex].rptr) == 0) { +#if LIBAVCODEC_BUILD > 4715 + AVPacket apkt; +#endif encsize = avcodec_encode_audio(&x->x_avcontext->streams[i]->codec, (uint8_t*)&x->x_audio_out, sizeof(x->x_audio_out), (short *)pencbuf); +#if LIBAVCODEC_BUILD > 4715 + av_init_packet(&apkt); + + apkt.pts = etime.tv_sec*1000000 + etime.tv_usec; + if((&x->x_avcontext->streams[i]->codec)->coded_frame->key_frame) + apkt.flags |= PKT_FLAG_KEY; + apkt.stream_index= i; + apkt.data= (uint8_t *)x->x_audio_out; + apkt.size= encsize; + + av_write_frame(x->x_avcontext, &apkt); +#else av_write_frame(x->x_avcontext, i, x->x_audio_out, encsize); +#endif } saudioindex++; } diff --git a/modules/pdp_form.c b/modules/pdp_form.c index ccbd510..b3a59b3 100644 --- a/modules/pdp_form.c +++ b/modules/pdp_form.c @@ -74,6 +74,7 @@ typedef struct pdp_form_struct t_int x_nbforms; t_int x_current; t_int x_capacity; + t_float x_alpha; /* imlib data */ Imlib_Image x_image; @@ -312,6 +313,14 @@ static void pdp_form_delete(t_pdp_form *x, t_floatarg fnum ) } } +static void pdp_form_alpha(t_pdp_form *x, t_floatarg falpha ) +{ + if ( ( falpha >= 0. ) && ( falpha <= 1. ) ) + { + x->x_alpha = falpha; + } +} + static void pdp_form_resize(t_pdp_form *x, t_floatarg fnewsize ) { t_form *forms; @@ -448,11 +457,11 @@ static void pdp_form_process_yv12(t_pdp_form *x) u = yuv_RGBtoU(imdata[py*x->x_vwidth+px]); v = yuv_RGBtoV(imdata[py*x->x_vwidth+px]); - *(pY) = y<<7; + *(pY) = (y<<7)*x->x_alpha + (*pY)*(1-x->x_alpha); if ( (px%2==0) && (py%2==0) ) { - *(pV) = (v-128)<<8; - *(pU) = (u-128)<<8; + *(pV) = ((v-128)<<8)*x->x_alpha + (*pV)*(1-x->x_alpha); + *(pU) = ((u-128)<<8)*x->x_alpha + (*pU)*(1-x->x_alpha); } } pY++; @@ -549,6 +558,7 @@ void *pdp_form_new(void) inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("r")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("g")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("b")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("alpha")); x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); x->x_packet0 = -1; @@ -567,6 +577,7 @@ void *pdp_form_new(void) x->x_nbforms = 0; x->x_current = -1; + x->x_alpha = 1.; return (void *)x; } @@ -601,6 +612,7 @@ void pdp_form_setup(void) class_addmethod(pdp_form_class, (t_method)pdp_form_clear, gensym("clear"), A_NULL); class_addmethod(pdp_form_class, (t_method)pdp_form_delete, gensym("delete"), A_DEFFLOAT, A_NULL); class_addmethod(pdp_form_class, (t_method)pdp_form_resize, gensym("resize"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_form_class, (t_method)pdp_form_alpha, gensym("alpha"), A_DEFFLOAT, A_NULL); class_sethelpsymbol( pdp_form_class, gensym("pdp_form.pd") ); } diff --git a/modules/pdp_i.c b/modules/pdp_i.c index e18a077..a89a56c 100644 --- a/modules/pdp_i.c +++ b/modules/pdp_i.c @@ -178,7 +178,7 @@ static void pdp_i_recv(t_pdp_i *x) t_hpacket *pheader; if ( ( ret = recv(x->x_socket, (void*) (x->x_inbuffer + x->x_inwriteposition), - (size_t)((x->x_inbuffersize-x->x_inwriteposition)), + (size_t)((x->x_inbuffersize-x->x_inwriteposition-1)), MSG_NOSIGNAL) ) < 0 ) { post( "pdp_i : receive error" ); @@ -189,7 +189,7 @@ static void pdp_i_recv(t_pdp_i *x) { // post( "pdp_i : received %d bytes at %d on %d ( up to %d)", // ret, x->x_inwriteposition, x->x_socket, - // x->x_inbuffersize-x->x_inwriteposition*sizeof( unsigned long) ); + // x->x_inbuffersize-x->x_inwriteposition ); if ( ret == 0 ) { @@ -197,29 +197,34 @@ static void pdp_i_recv(t_pdp_i *x) outlet_float( x->x_connection_status, 0 ); pdp_i_closesocket( x->x_socket ); sys_rmpollfn(x->x_socket); + post( "pdp_i : lost the connection." ); x->x_socket = -1; } else { // check we don't overflow input buffer - if ( x->x_inwriteposition+ret >= x->x_inbuffersize ) + if ( x->x_inwriteposition+ret >= x->x_inbuffersize/2 ) { post( "pdp_i : too much input...resetting" ); x->x_inwriteposition=0; + memset( (char*) x->x_inbuffer, 0x00, x->x_inbuffersize ); return; } x->x_inwriteposition += ret; - if ( pheader = (t_hpacket*) strstr( (char*) x->x_inbuffer, PDP_PACKET_START ) ) + if ( ( ( pheader = (t_hpacket*) strstr( (char*) x->x_inbuffer, PDP_PACKET_START ) ) != NULL ) || + ( ( pheader = (t_hpacket*) strstr( (char*) x->x_inbuffer, PDP_PACKET_DIFF ) ) != NULL ) ) { // check if a full packet is present - if ( x->x_inwriteposition >= (int)((char*)pheader - (char*)(x->x_inbuffer)) + (int)sizeof(t_hpacket) + (int)pheader->clength ) + if ( x->x_inwriteposition >= + (int)((char*)pheader - (char*)(x->x_inbuffer)) + + (int)sizeof(t_hpacket) + (int)ntohl(pheader->clength) ) { - if ( ( x->x_vwidth != pheader->width ) || - ( x->x_vheight != pheader->height ) ) + if ( ( x->x_vwidth != (t_int)ntohl(pheader->width) ) || + ( x->x_vheight != (t_int)ntohl(pheader->height) ) ) { pdp_i_free_ressources(x); - x->x_vheight = pheader->height; - x->x_vwidth = pheader->width; + x->x_vheight = ntohl(pheader->height); + x->x_vwidth = ntohl(pheader->width); x->x_vsize = x->x_vheight*x->x_vwidth; pdp_i_allocate(x); post( "pdp_i : allocated buffers : vsize=%d : hsize=%d", x->x_vsize, x->x_hsize ); @@ -230,18 +235,18 @@ static void pdp_i_recv(t_pdp_i *x) x->x_data = (short int *)pdp_packet_data(x->x_packet); memcpy( x->x_data, x->x_bdata, x->x_bsize ); - // post( "pdp_i : decompress %d in %d bytes", pheader->clength, x->x_hsize ); + // post( "pdp_i : decompress %d in %d bytes", ntohl(pheader->clength), x->x_hsize ); x->x_bzsize = x->x_hsize; if ( ( ret = BZ2_bzBuffToBuffDecompress( (char*)x->x_hdata, &x->x_bzsize, (char *) pheader+sizeof(t_hpacket), - pheader->clength, + ntohl(pheader->clength), 0, 0 ) ) == BZ_OK ) { - // post( "pdp_i : bz2 decompression (%d)->(%d)", pheader->clength, x->x_bzsize ); + // post( "pdp_i : bz2 decompression (%d)->(%d)", ntohl(pheader->clength), x->x_bzsize ); - switch( pheader->encoding ) + switch( ntohl(pheader->encoding) ) { case REGULAR : memcpy( x->x_ddata, x->x_hdata, x->x_bzsize ); @@ -285,8 +290,8 @@ static void pdp_i_recv(t_pdp_i *x) x->x_header->info.image.width = x->x_vwidth; x->x_header->info.image.height = x->x_vheight; - pdp_packet_pass_if_valid(x->x_pdp_output, &x->x_packet); // post( "pdp_i : propagate packet : %d", x->x_packet ); + pdp_packet_pass_if_valid(x->x_pdp_output, &x->x_packet); outlet_float( x->x_frames, ++x->x_framesreceived ); } else @@ -297,8 +302,20 @@ static void pdp_i_recv(t_pdp_i *x) memcpy( x->x_bdata, x->x_data, x->x_bsize ); // roll buffer - x->x_inwriteposition -= (int)((char*)pheader-(char*)(x->x_inbuffer)) + sizeof(t_hpacket) + pheader->clength; - memcpy( x->x_inbuffer, pheader+sizeof(t_hpacket) + pheader->clength, x->x_inwriteposition ); + x->x_inwriteposition -= (int)((char*)pheader-(char*)(x->x_inbuffer)) + sizeof(t_hpacket) + ntohl(pheader->clength); + if ( x->x_inwriteposition > 0 ) + { + memcpy( x->x_inbuffer, pheader+sizeof(t_hpacket) + ntohl(pheader->clength), x->x_inwriteposition ); + } + else + { + x->x_inwriteposition = 0; + memset( (char*) x->x_inbuffer, 0x00, x->x_inbuffersize ); + } + } + else + { + // post( "pdp_i : not a full frame" ); } } } diff --git a/modules/pdp_live~.c b/modules/pdp_live~.c index cae6a65..c403a15 100644 --- a/modules/pdp_live~.c +++ b/modules/pdp_live~.c @@ -35,6 +35,8 @@ #include <sys/time.h> #include <sys/resource.h> #include <avformat.h> +#include <sys/types.h> +#include <signal.h> #define VIDEO_BUFFER_SIZE (1024*1024) #define MAX_AUDIO_PACKET_SIZE (128 * 1024) @@ -46,8 +48,8 @@ #define DEFAULT_HEIGHT 240 #define DEFAULT_FRAME_RATE 25 #define END_OF_STREAM 20 -#define MIN_PRIORITY -20 -#define DEFAULT_PRIORITY 0 +#define MIN_PRIORITY 0 +#define DEFAULT_PRIORITY 1 #define MAX_PRIORITY 20 /* a trick to cope with ffmpeg versions */ @@ -66,7 +68,7 @@ typedef struct pdp_live_struct t_int x_dropped; t_pdp *x_header; - short int *x_data; + unsigned char *x_data; t_int x_vwidth; t_int x_vheight; t_int x_vsize; @@ -82,10 +84,14 @@ typedef struct pdp_live_struct pthread_t x_connectchild; // thread used for connecting to a stream pthread_t x_decodechild; // stream decoding thread t_int x_usethread; // flag to activate decoding in a thread + t_int x_autoplay; // flag to autoplay the file ( default = true ) + t_int x_nextimage; // flag to play next image in manual mode t_int x_priority; // priority of decoding thread char *x_url; t_int x_streaming; // streaming flag + t_int x_decoding; // decoding flag + t_int x_loop; // looping flag ( default = on ) t_int x_nopackets; // no packet to decode t_int x_endofstream; // end of the stream reached t_int x_nbframes; // number of frames emitted @@ -108,6 +114,7 @@ typedef struct pdp_live_struct AVPicture x_picture_decoded; long long int x_pts; // presentation time stamp long long int x_previouspts; // previous presentation time stamp + long long int x_firstpts; // first presentation time stamp ( time origin ) t_int x_newpicture; /* audio structures */ @@ -137,19 +144,80 @@ static void pdp_live_threadify(t_pdp_live *x, t_floatarg fusethread ) static void pdp_live_audio(t_pdp_live *x, t_floatarg faudio ) { - if ( ( faudio == 0.0 ) || ( faudio == 1 ) ) + if ( ( faudio == 0. ) || ( faudio == 1. ) ) { x->x_audio = (int)faudio; } } +static void pdp_live_autoplay(t_pdp_live *x, t_floatarg fautoplay ) +{ + if ( ( fautoplay == 0. ) || ( fautoplay == 1. ) ) + { + x->x_autoplay = (int)fautoplay; + } +} + +static void pdp_live_loop(t_pdp_live *x, t_floatarg floop ) +{ + if ( ( floop == 0. ) || ( floop == 1. ) ) + { + x->x_loop = (int)floop; + } +} + +static void pdp_live_bang(t_pdp_live *x) +{ + if ( x->x_nextimage == 1 ) + { + // post( "pdp_live~ : banging too fast, previous image is not decoded yet... ignored" ); + return; + } + x->x_nextimage = 1; +} + +static void pdp_live_frame_cold(t_pdp_live *x, t_floatarg frameindex) +{ + int frame = (int)frameindex; + int ret; + uint64_t newpts; + + if (!(x->x_streaming)) return; + +#if FFMPEG_VERSION_INT >= 0x000409 + if ( ( ( x->x_avcontext->iformat->flags & AVFMT_NOFILE ) == 0 ) && ( x->x_videoindex != -1 ) ) + { + if ( x->x_framerate != 0 ) + { + newpts = x->x_firstpts + ( frame * 1000000 ) / x->x_framerate; + } + else + { + post( "pdp_live~ : couldn't seek requested frame ( framerate = %d )", x->x_framerate ); + return; + } + if ( ( ret = av_seek_frame(x->x_avcontext, x->x_videoindex, newpts) ) < 0 ) + { + post( "pdp_live~ : couldn't seek the requested frame (ret=%d)", ret ); + } + } +#else + post( "pdp_live~ : no seek function with ffmpeg < 4.0.9"); +#endif +} + static t_int pdp_live_decode_packet(t_pdp_live *x) { - t_int chunksize=0, length; + t_int chunksize=0, length, err, ret; t_int audiosize, sizeout, imagesize, pictureok; AVFrame frame; uint8_t *pcktptr; - struct timeval etime; + unsigned char *pY, *pU, *pV; + uint8_t *psY, *psU, *psV; + t_int px, py; + long long tplaying; + long long ttheoretical; + struct timeval ctime; struct timespec mwait; if ( !x->x_streaming ) @@ -159,13 +227,35 @@ static t_int pdp_live_decode_packet(t_pdp_live *x) // post( "pdp_live~ : trying to read packet" ); // read new packet on the stream - if (av_read_packet(x->x_avcontext, &x->x_pkt) < 0) + if ( x->x_streaming && av_read_packet(x->x_avcontext, &x->x_pkt) < 0) { x->x_nopackets++; // post( "pdp_live~ : decoding thread : nothing to decode : no packets :%d", x->x_nopackets ); if ( x->x_nopackets > END_OF_STREAM ) { x->x_endofstream = 1; + if ( x->x_loop ) + { + +#if FFMPEG_VERSION_INT >= 0x000409 + + if ( ( x->x_avcontext->iformat->flags & AVFMT_NOFILE ) == 0 ) + { + post( "pdp_live~ : looping file reading..." ); + if ( ( ret = av_seek_frame(x->x_avcontext, x->x_videoindex, 0) ) < 0 ) + { + post( "pdp_live~ : couldn't seek the requested frame (ret=%d)", ret ); + } + else + { + x->x_endofstream = 0; + } + } + +#else + post( "pdp_live~ : no seek function with ffmpeg < 4.0.9"); +#endif + } } return -1; } @@ -182,6 +272,7 @@ static t_int pdp_live_decode_packet(t_pdp_live *x) pcktptr = x->x_pkt.data; while (length > 0) { + if ( !x->x_streaming ) break; switch(x->x_avcontext->streams[x->x_pkt.stream_index]->codec.codec_type) { case CODEC_TYPE_AUDIO: @@ -240,7 +331,7 @@ static t_int pdp_live_decode_packet(t_pdp_live *x) post( "pdp_live~ : audio overflow : packet ignored..."); x->x_audioin_position = 0; } - if ( ( x->x_audioin_position > x->x_blocksize ) && (!x->x_audioon) ) + if ( ( x->x_audioin_position > 4*x->x_blocksize ) && (!x->x_audioon) ) { x->x_audioon = 1; // post( "pdp_live~ : audio on" ); @@ -253,20 +344,9 @@ static t_int pdp_live_decode_packet(t_pdp_live *x) x->x_avcontext->streams[x->x_pkt.stream_index]->codec.height * 3) / 2; // yuv planar x->x_framerate = x->x_avcontext->streams[x->x_pkt.stream_index]->codec.frame_rate / 10000; + if ( x->x_framerate == 0 ) x->x_framerate = DEFAULT_FRAME_RATE; x->x_videoindex = x->x_pkt.stream_index; - // calculate actual frame rate - // if ( gettimeofday(&etime, NULL) == -1) - // { - // post("pdp_live~ : could not read time" ); - // } - // if ( ( etime.tv_sec - x->x_starttime.tv_sec ) > 0 ) - // { - // x->x_framerate = x->x_nbframes / ( etime.tv_sec - x->x_starttime.tv_sec ); - // } - // if ( x->x_framerate == 0 ) x->x_framerate = 1; - // post ("pdp_live~ : frame rate is %d", x->x_framerate ); - chunksize = avcodec_decode_video( &x->x_avcontext->streams[x->x_pkt.stream_index]->codec, &frame, &pictureok, @@ -304,37 +384,74 @@ static t_int pdp_live_decode_packet(t_pdp_live *x) else { x->x_newpicture=1; - x->x_previouspts = x->x_pts; - x->x_pts = frame.pts; - // post( "pdp_live : frame pts : %ld", x->x_pts ); x->x_vwidth = x->x_avcontext->streams[x->x_pkt.stream_index]->codec.width; x->x_vheight = x->x_avcontext->streams[x->x_pkt.stream_index]->codec.height; x->x_vsize = x->x_vwidth*x->x_vheight; - if ( x->x_previouspts != -1 ) + // create a new pdp packet from BITMAP YV12 image format + x->x_packet0 = pdp_packet_new_bitmap_yv12( x->x_vwidth, x->x_vheight ); + x->x_header = pdp_packet_header(x->x_packet0); + x->x_data = (unsigned char *)pdp_packet_data(x->x_packet0); + + pY = x->x_data; + pV = x->x_data+x->x_vsize; + pU = x->x_data+x->x_vsize+(x->x_vsize>>2); + + psY = x->x_picture_decoded.data[0]; + psU = x->x_picture_decoded.data[1]; + psV = x->x_picture_decoded.data[2]; + + for ( py=0; py<x->x_vheight; py++) + { + memcpy( (void*)pY, (void*)psY, x->x_vwidth ); + pY += x->x_vwidth; + psY += x->x_picture_decoded.linesize[0]; + if ( py%2==0 ) + { + memcpy( (void*)pU, (void*)psU, (x->x_vwidth>>1) ); + memcpy( (void*)pV, (void*)psV, (x->x_vwidth>>1) ); + pU += (x->x_vwidth>>1); + pV += (x->x_vwidth>>1); + psU += x->x_picture_decoded.linesize[1]; + psV += x->x_picture_decoded.linesize[2]; + } + } + + if ( x->x_firstpts == -1 ) { - mwait.tv_sec = 0; - mwait.tv_nsec = (x->x_pts - x->x_previouspts)*1000; - - if ( ( x->x_pts == 0 ) ) - { - // post("pdp_live~ : no presentation time stamp, using framerate :%d", - // x->x_framerate ); - mwait.tv_sec = 0; - mwait.tv_nsec = 1000000000/((x->x_framerate+5)); // the +5 is experimental - // it comes from the time used in decoding - } - - nanosleep( &mwait, NULL ); // wait between the two successive frames - // i know, cheap flow control + x->x_firstpts = x->x_pts; } + x->x_previouspts = x->x_pts; + x->x_pts = frame.pts; + // post( "pdp_live : frame pts : %ld", x->x_pts ); + if ( x->x_nbframes > 0 ) + { + if ( gettimeofday(&ctime, NULL) == -1) + { + post("pdp_theorin~ : could not read time" ); + } + + tplaying = ( ctime.tv_sec-x->x_starttime.tv_sec )*1000 + + ( ctime.tv_usec-x->x_starttime.tv_usec )/1000; + ttheoretical = ((x->x_nbframes)*1000 )/x->x_framerate; + // post( "pdp-theorin~ : %d playing since : %lldms ( theory : %lldms )", + // x->x_nbframes, tplaying, ttheoretical ); + + if ( tplaying < ttheoretical ) + { + mwait.tv_sec = 0; + mwait.tv_nsec = (ttheoretical - tplaying)*1000000; + + // wait between the two successive frames + if ( x->x_autoplay ) nanosleep( &mwait, NULL ); + } + } } break; } pcktptr += chunksize; length -= chunksize; - if ( !x->x_streaming ) break; } av_free_packet(&x->x_pkt); @@ -353,18 +470,10 @@ static void *pdp_decode_stream_from_url(void *tdata) twait.tv_sec = 0; twait.tv_nsec = 10000000; // 10 ms - schedprio.sched_priority = 0; - if ( sched_setscheduler(0,SCHED_OTHER,&schedprio) == -1) - { - post("pdp_live~ : couldn't set scheduler for decoding thread.\n"); - } - if ( setpriority( PRIO_PROCESS, 0, x->x_priority ) < 0 ) - { - post("pdp_live~ : couldn't set priority to %d for decoding thread.\n", x->x_priority ); - } - else + schedprio.sched_priority = sched_get_priority_min(SCHED_FIFO) + x->x_priority; + if ( sched_setscheduler(0,SCHED_FIFO,&schedprio) == -1) { - post("pdp_live~ : priority set to %d for thread %d.\n", x->x_priority, x->x_decodechild ); + post("pdp_theorin~ : couldn't set priority for decoding thread."); } if ( ! (x->x_avcontext->iformat->flags & AVFMT_NOHEADER ) ) @@ -376,19 +485,27 @@ static void *pdp_decode_stream_from_url(void *tdata) post( "pdp_live~ : read header." ); } - while ( x->x_streaming ) + while ( x->x_decodechild ) { - while ( x->x_newpicture ) nanosleep( &twait, NULL ); + if ( ( x->x_streaming ) && ( ( x->x_autoplay ) || ( x->x_nextimage == 1 ) ) ) + { + x->x_decoding = 1; + while ( x->x_newpicture ) nanosleep( &twait, NULL ); - // decode incoming packets - if ( pdp_live_decode_packet( x ) < 0 ) + // decode incoming packets + if ( ( x->x_streaming ) && ( pdp_live_decode_packet( x ) < 0 ) ) + { + nanosleep( &twait, NULL ); // nothing to read, just wait + } + x->x_nextimage = -1; + } + else { - nanosleep( &twait, NULL ); // nothing to read, just wait + x->x_decoding = 0; + nanosleep( &twait, NULL ); // nothing to do, just wait } - } - post( "pdp_live~ : decoding thread %d exiting....", x->x_decodechild ); x->x_decodechild = 0; pthread_exit(NULL); } @@ -419,7 +536,6 @@ static void *pdp_live_connect_to_url(void *tdata) if ( err == -5 ) post( "pdp_live~ : not enough memory" ); if ( err == -6 ) post( "pdp_live~ : unknown format ( stream not found? )" ); x->x_connectchild = 0; - x->x_avcontext = av_mallocz(sizeof(AVFormatContext)); pthread_exit(NULL); } /* If not enough info to get the stream parameters, we decode the @@ -507,11 +623,13 @@ static void *pdp_live_connect_to_url(void *tdata) x->x_nopackets = 0; x->x_endofstream = 0; x->x_nbframes = 0; + x->x_pts = -1; + x->x_previouspts = -1; + x->x_firstpts = -1; - x->x_connectchild = 0; - - if ( x->x_usethread ) + if ( x->x_usethread && ( x->x_decodechild == 0 )) { + x->x_decodechild = 1; // trick & treets // launch decoding thread if ( pthread_attr_init( &decode_child_attr ) < 0 ) { @@ -556,15 +674,15 @@ static void pdp_live_disconnect(t_pdp_live *x) { x->x_streaming = 0; x->x_newpicture = 0; - post("pdp_live~ : waiting for the end of decoding thread..." ); - while ( x->x_decodechild && ( count < 100 ) ) + post("pdp_live~ : waiting end of decoding..." ); + while ( x->x_decoding ) nanosleep( &twait, NULL ); + /* close each decoder */ + for(i=0;i<x->x_avcontext->nb_streams;i++) { - count++; - sleep( 1 ); - } - if ( x->x_decodechild ) - { - post("pdp_live~ : zombie thread, i guess" ); + if (avcodec_close(&x->x_avcontext->streams[i]->codec) < 0) + { + post("pdp_live~ : error while closing codec for stream #%d", i); + } } post("pdp_live~ : closing input file..." ); av_close_input_file(x->x_avcontext); @@ -631,9 +749,6 @@ static t_int *pdp_live_perform(t_int *w) t_float *out2 = (t_float *)(w[2]); // right audio inlet t_pdp_live *x = (t_pdp_live *)(w[3]); int n = (int)(w[4]); // number of samples - short int *pY, *pU, *pV; - uint8_t *psY, *psU, *psV; - t_int pixRGB, px, py; short sampleL, sampleR; struct timeval etime; t_int sn; @@ -650,7 +765,6 @@ static t_int *pdp_live_perform(t_int *w) if ( x->x_audioon ) { sn=0; - n=n*DEFAULT_CHANNELS; while (n--) { sampleL=x->x_audio_in[ sn++ ]; @@ -670,7 +784,7 @@ static t_int *pdp_live_perform(t_int *w) memcpy( &x->x_audio_in[0], &x->x_audio_in[sn], 4*MAX_AUDIO_PACKET_SIZE-sn ); x->x_audioin_position-=sn; // post( "pdp_live~ : audio in position : %d", x->x_audioin_position ); - if ( x->x_audioin_position <= sn ) + if ( x->x_audioin_position <= 0 ) { x->x_audioon = 0; // post( "pdp_live~ : audio off" ); @@ -694,7 +808,7 @@ static t_int *pdp_live_perform(t_int *w) if ( etime.tv_sec != x->x_cursec ) { x->x_cursec = etime.tv_sec; - if (x->x_streaming) outlet_float( x->x_outlet_framerate, x->x_framerate ); + if (x->x_streaming) outlet_float( x->x_outlet_framerate, x->x_secondcount ); x->x_secondcount = 0; } if ( x->x_secondcount >= x->x_framerate ) @@ -705,45 +819,13 @@ static t_int *pdp_live_perform(t_int *w) // output image if there's a new one decoded if ( x->x_newpicture ) { - // create a new pdp packet from PIX_FMT_YUV420P image format - x->x_packet0 = pdp_packet_new_image_YCrCb( x->x_vwidth, x->x_vheight ); - x->x_header = pdp_packet_header(x->x_packet0); - x->x_data = (short int *)pdp_packet_data(x->x_packet0); - - pY = x->x_data; - pV = x->x_data+x->x_vsize; - pU = x->x_data+x->x_vsize+(x->x_vsize>>2); - - psY = x->x_picture_decoded.data[0]; - psU = x->x_picture_decoded.data[1]; - psV = x->x_picture_decoded.data[2]; - - for ( py=0; py<x->x_vheight; py++) - { - for ( px=0; px<x->x_vwidth; px++) - { - *(pY) = ( *(psY+px) << 7 ); - *(pV) = ( ((*(psV+(px>>1)))-128) << 8 ); - *(pU) = ( ((*(psU+(px>>1)))-128) << 8 ); - pY++; - if ( (px%2==0) && (py%2==0) ) - { - pV++; pU++; - } - } - psY += x->x_picture_decoded.linesize[0]; - if ( py%2==0 ) psU += x->x_picture_decoded.linesize[1]; - if ( py%2==0 ) psV += x->x_picture_decoded.linesize[2]; - } - pdp_packet_pass_if_valid(x->x_pdp_out, &x->x_packet0); + x->x_newpicture = 0; // update streaming status x->x_nbframes++; x->x_secondcount++; outlet_float( x->x_outlet_nbframes, x->x_nbframes ); - - x->x_newpicture = 0; } outlet_float( x->x_outlet_streaming, x->x_streaming ); outlet_float( x->x_outlet_endofstream, x->x_endofstream ); @@ -760,18 +842,19 @@ static void pdp_live_free(t_pdp_live *x) { int i; + if ( x->x_decodechild ) + { + x->x_decodechild = 0; + x->x_decoding = 0; + sleep( 5 ); // let the decoding thread exiting + } + if ( x->x_streaming ) { pdp_live_disconnect(x); - sleep(3); } post( "pdp_live~ : freeing object" ); pdp_packet_mark_unused(x->x_packet0); - if (x->x_audio_resample_ctx) - { - audio_resample_close(x->x_audio_resample_ctx); - x->x_audio_resample_ctx = NULL; - } av_free_static(); } @@ -783,6 +866,8 @@ void *pdp_live_new(void) t_pdp_live *x = (t_pdp_live *)pd_new(pdp_live_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("frame_cold")); + x->x_pdp_out = outlet_new(&x->x_obj, &s_anything); x->x_outlet_left = outlet_new(&x->x_obj, &s_signal); @@ -796,6 +881,7 @@ void *pdp_live_new(void) x->x_packet0 = -1; x->x_connectchild = 0; x->x_decodechild = 0; + x->x_decoding = 0; x->x_usethread = 1; x->x_priority = DEFAULT_PRIORITY; x->x_framerate = DEFAULT_FRAME_RATE; @@ -807,15 +893,19 @@ void *pdp_live_new(void) x->x_secondcount = 0; x->x_audio_resample_ctx = NULL; x->x_nbvideostreams = 0; - x->x_videoindex = 0; + x->x_videoindex = -1; x->x_audioin_position = 0; x->x_newpicture = 0; x->x_endofstream = 0; x->x_nopackets = 0; x->x_blocksize = MIN_AUDIO_SIZE; + x->x_autoplay = 1; + x->x_loop = 1; + x->x_nextimage = 0; x->x_pts = -1; x->x_previouspts = -1; + x->x_firstpts = -1; x->x_avcontext = av_mallocz(sizeof(AVFormatContext)); if ( !x->x_avcontext ) @@ -851,7 +941,11 @@ void pdp_live_tilde_setup(void) class_addmethod(pdp_live_class, (t_method)pdp_live_disconnect, gensym("disconnect"), A_NULL); class_addmethod(pdp_live_class, (t_method)pdp_live_priority, gensym("priority"), A_FLOAT, A_NULL); class_addmethod(pdp_live_class, (t_method)pdp_live_audio, gensym("audio"), A_FLOAT, A_NULL); + class_addmethod(pdp_live_class, (t_method)pdp_live_autoplay, gensym("autoplay"), A_FLOAT, A_NULL); + class_addmethod(pdp_live_class, (t_method)pdp_live_loop, gensym("loop"), A_FLOAT, A_NULL); class_addmethod(pdp_live_class, (t_method)pdp_live_threadify, gensym("thread"), A_FLOAT, A_NULL); + class_addmethod(pdp_live_class, (t_method)pdp_live_bang, gensym("bang"), A_NULL); + class_addmethod(pdp_live_class, (t_method)pdp_live_frame_cold, gensym("frame_cold"), A_FLOAT, A_NULL); class_sethelpsymbol( pdp_live_class, gensym("pdp_live~.pd") ); } diff --git a/modules/pdp_o.c b/modules/pdp_o.c index ee5e084..30157cf 100644 --- a/modules/pdp_o.c +++ b/modules/pdp_o.c @@ -182,7 +182,7 @@ static void pdp_o_smoothe(t_pdp_o *x, short int *source, t_int size ) static int pdp_o_huffman(t_pdp_o *x, char *source, char *dest, t_int size, t_int *csize ) { t_int i; - char value = source[0]; + int value = source[0]; char count = 0; t_int tcount=0; char *pcount=dest; @@ -198,14 +198,14 @@ static int pdp_o_huffman(t_pdp_o *x, char *source, char *dest, t_int size, t_int } else { - value=source[i]; *(pcount)=count; *(pvalue) = value; tcount+=count; - count=1; pcount+=2; pvalue+=2; *(csize)+=2; + value=source[i]; + count=1; } } *(pcount)=count; @@ -221,7 +221,7 @@ static int pdp_o_huffman(t_pdp_o *x, char *source, char *dest, t_int size, t_int else { // post( "pdp_o : huffman : compression ratio %d/%d : %f (total count=%d)", size, (*csize), - // (t_float)size/(t_float)(*csize), tcount ); + // (t_float)size/(t_float)(*csize), tcount ); return HUFFMAN; } } @@ -349,7 +349,8 @@ static void pdp_o_process_yv12(t_pdp_o *x) { // post( "pdp_o : y value out of range : %d", downvalue ); } - if ( data[i] != x->x_previous_frame[i] ) + if ( ( data[i] != x->x_previous_frame[i] ) || + ( !strcmp( x->x_hpacket.tag, PDP_PACKET_TAG ) ) ) { x->x_diff_frame[i] = (char)downvalue; } @@ -368,7 +369,8 @@ static void pdp_o_process_yv12(t_pdp_o *x) { // post( "pdp_o : y value out of range : %d", downvalue ); } - if ( data[i] != x->x_previous_frame[i] ) + if ( ( data[i] != x->x_previous_frame[i] ) || + ( !strcmp( x->x_hpacket.tag, PDP_PACKET_TAG ) ) ) { x->x_diff_frame[i] = (char)downvalue; } @@ -378,8 +380,8 @@ static void pdp_o_process_yv12(t_pdp_o *x) } } - x->x_hpacket.width = x->x_vwidth; - x->x_hpacket.height = x->x_vheight; + x->x_hpacket.width = htonl(x->x_vwidth); + x->x_hpacket.height = htonl(x->x_vheight); if ( gettimeofday(&x->x_hpacket.etime, NULL) == -1) { post("pdp_o : could not set emit time" ); @@ -391,13 +393,16 @@ static void pdp_o_process_yv12(t_pdp_o *x) x->x_bandwidthcount = 0; } + x->x_hpacket.etime.tv_sec = htonl( x->x_hpacket.etime.tv_sec ); + x->x_hpacket.etime.tv_usec = htonl( x->x_hpacket.etime.tv_usec ); + // do not send the frame if too many frames // have been sent in the current second if ( x->x_secondcount < x->x_framerate ) { // try a huffman coding - x->x_hpacket.encoding = pdp_o_huffman(x, x->x_diff_frame, x->x_hdata, x->x_vsize+(x->x_vsize>>1), &x->x_hsize ); + x->x_hpacket.encoding = htonl( pdp_o_huffman(x, x->x_diff_frame, x->x_hdata, x->x_vsize+(x->x_vsize>>1), &x->x_hsize ) ); x->x_hpacket.clength = (x->x_vsize+(x->x_vsize>>1))*1.01+600; // compress the graphic data @@ -415,6 +420,7 @@ static void pdp_o_process_yv12(t_pdp_o *x) memcpy( x->x_previous_frame, data, (x->x_vsize+(x->x_vsize>>1))<<1 ); // send header + x->x_hpacket.clength = htonl( x->x_hpacket.clength ); count = send(x->x_fd, &x->x_hpacket, sizeof(x->x_hpacket), MSG_NOSIGNAL); if(count < 0) { @@ -430,6 +436,7 @@ static void pdp_o_process_yv12(t_pdp_o *x) } x->x_bandwidthcount += count/1024; } + x->x_hpacket.clength = ntohl( x->x_hpacket.clength ); // send data count = send(x->x_fd, x->x_cdata, x->x_hpacket.clength, MSG_NOSIGNAL); diff --git a/modules/pdp_ocanvas.c b/modules/pdp_ocanvas.c index c92253b..598821e 100644 --- a/modules/pdp_ocanvas.c +++ b/modules/pdp_ocanvas.c @@ -53,6 +53,7 @@ typedef struct pdp_ocanvas_struct t_int *x_heights; t_float *x_xoffsets; t_float *x_yoffsets; + t_float *x_alphas; t_int *x_sizes; t_int x_owidth; @@ -105,7 +106,7 @@ static void pdp_ocanvas_process_yv12(t_pdp_ocanvas *x) piU = idata+x->x_sizes[ii]+(x->x_sizes[ii]>>2); ppx = px-(int)x->x_xoffsets[ii]; ppy = py-(int)x->x_yoffsets[ii]; - *(pY+py*x->x_owidth+px) += *(piY+ppy*x->x_widths[ii]+ppx); + *(pY+py*x->x_owidth+px) += *(piY+ppy*x->x_widths[ii]+ppx)*x->x_alphas[ii]; if ( (px%2==0) && (py%2==0) ) { *(pU+(py>>1)*(x->x_owidth>>1)+(px>>1)) += @@ -175,6 +176,21 @@ static void pdp_ocanvas_offset(t_pdp_ocanvas *x, t_floatarg ni, t_floatarg xoffs x->x_yoffsets[(int)ni-1] = yoffset; } +static void pdp_ocanvas_alpha(t_pdp_ocanvas *x, t_floatarg ni, t_floatarg xalpha) +{ + if ( ( ni < 1 ) || ( ni > x->x_nbinputs ) ) + { + post( "pdp_ocanvas : alpha : wrong source : %d : must be between 1 and %d", ni, x->x_nbinputs ); + return; + } + if ( ( xalpha < .0 ) || ( xalpha > 1.0 ) ) + { + post( "pdp_ocanvas : alpha : wrong alpha value : %f : must be between 0 and 1", xalpha ); + return; + } + x->x_alphas[(int)ni-1] = xalpha; +} + static void pdp_ocanvas_select(t_pdp_ocanvas *x, t_floatarg X, t_floatarg Y) { t_int ii; @@ -324,6 +340,7 @@ static void pdp_ocanvas_free(t_pdp_ocanvas *x) if ( x->x_sizes ) freebytes( x->x_sizes, x->x_nbinputs*sizeof(t_int) ); if ( x->x_xoffsets ) freebytes( x->x_xoffsets, x->x_nbinputs*sizeof(t_float) ); if ( x->x_yoffsets ) freebytes( x->x_yoffsets, x->x_nbinputs*sizeof(t_float) ); + if ( x->x_alphas ) freebytes( x->x_alphas, x->x_nbinputs*sizeof(t_float) ); } t_class *pdp_ocanvas_class; @@ -381,6 +398,7 @@ void *pdp_ocanvas_new(t_symbol *s, int argc, t_atom *argv) x->x_sizes = ( t_int* ) getbytes( x->x_nbinputs*sizeof(t_int) ); x->x_xoffsets = ( t_float* ) getbytes( x->x_nbinputs*sizeof(t_float) ); x->x_yoffsets = ( t_float* ) getbytes( x->x_nbinputs*sizeof(t_float) ); + x->x_alphas = ( t_float* ) getbytes( x->x_nbinputs*sizeof(t_float) ); x->x_opacket = pdp_packet_new_image_YCrCb( x->x_owidth, x->x_oheight ); @@ -391,6 +409,7 @@ void *pdp_ocanvas_new(t_symbol *s, int argc, t_atom *argv) x->x_packets[ii] = -1; x->x_xoffsets[ii] = 0.; x->x_yoffsets[ii] = 0.; + x->x_alphas[ii] = 1.; } x->x_current = -1; x->x_average = 0; @@ -426,6 +445,7 @@ void pdp_ocanvas_setup(void) class_addmethod(pdp_ocanvas_class, (t_method)pdp_ocanvas_input8, gensym("pdp8"), A_SYMBOL, A_DEFFLOAT, A_NULL); class_addmethod(pdp_ocanvas_class, (t_method)pdp_ocanvas_input9, gensym("pdp9"), A_SYMBOL, A_DEFFLOAT, A_NULL); class_addmethod(pdp_ocanvas_class, (t_method)pdp_ocanvas_offset, gensym("offset"), A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, A_NULL); + class_addmethod(pdp_ocanvas_class, (t_method)pdp_ocanvas_alpha, gensym("alpha"), A_DEFFLOAT, A_DEFFLOAT, A_NULL); class_addmethod(pdp_ocanvas_class, (t_method)pdp_ocanvas_select, gensym("select"), A_DEFFLOAT, A_DEFFLOAT, A_NULL); class_addmethod(pdp_ocanvas_class, (t_method)pdp_ocanvas_drag, gensym("drag"), A_DEFFLOAT, A_DEFFLOAT, A_NULL); class_addmethod(pdp_ocanvas_class, (t_method)pdp_ocanvas_unselect, gensym("unselect"), A_NULL); diff --git a/modules/pdp_pen.c b/modules/pdp_pen.c index dad5167..6aa263c 100644 --- a/modules/pdp_pen.c +++ b/modules/pdp_pen.c @@ -52,6 +52,7 @@ typedef struct pdp_pen_struct t_int x_blue; t_int x_xoffset; t_int x_yoffset; + t_float x_alpha; t_int x_pwidth; t_int x_mode; // 0=draw ( default), 1=erase @@ -317,6 +318,14 @@ static void pdp_pen_yoffset(t_pdp_pen *x, t_floatarg yoffset) x->x_yoffset = (int) yoffset; } +static void pdp_pen_alpha(t_pdp_pen *x, t_floatarg falpha) +{ + if ( falpha >= 0. && falpha <= 1. ) + { + x->x_alpha = falpha; + } +} + static void pdp_pen_mode(t_pdp_pen *x, t_floatarg mode) { if ( ( mode == 0. ) || ( mode == 1. ) ) @@ -394,11 +403,15 @@ static void pdp_pen_process_yv12(t_pdp_pen *x) { if ( *(pbY+(py-x->x_yoffset)*x->x_vwidth+(px-x->x_xoffset)) != 0 ) { - *(pnY+py*x->x_vwidth+px) = *(pbY+(py-x->x_yoffset)*x->x_vwidth+(px-x->x_xoffset)); + *(pnY+py*x->x_vwidth+px) = + (*(pbY+(py-x->x_yoffset)*x->x_vwidth+(px-x->x_xoffset))*x->x_alpha) + + (*(pnY+py*x->x_vwidth+px)*(1-x->x_alpha)); *(pnU+(py>>1)*(x->x_vwidth>>1)+(px>>1)) = - *(pbU+((py-x->x_yoffset)>>1)*(x->x_vwidth>>1)+((px-x->x_xoffset)>>1)); + (*(pbU+((py-x->x_yoffset)>>1)*(x->x_vwidth>>1)+((px-x->x_xoffset)>>1))*x->x_alpha) + + (*(pnU+(py>>1)*(x->x_vwidth>>1)+(px>>1))*(1-x->x_alpha)); *(pnV+(py>>1)*(x->x_vwidth>>1)+(px>>1)) = - *(pbV+((py-x->x_yoffset)>>1)*(x->x_vwidth>>1)+((px-x->x_xoffset)>>1)); + (*(pbV+((py-x->x_yoffset)>>1)*(x->x_vwidth>>1)+((px-x->x_xoffset)>>1))*x->x_alpha) + + (*(pnV+(py>>1)*(x->x_vwidth>>1)+(px>>1))*(1-x->x_alpha)); } } } @@ -482,6 +495,7 @@ void *pdp_pen_new(void) x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("xoffset")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("yoffset")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("alpha")); x->x_packet0 = -1; x->x_packet1 = -1; @@ -498,6 +512,7 @@ void *pdp_pen_new(void) x->x_pwidth = 3; x->x_mode = 0; + x->x_alpha = 1.; return (void *)x; } @@ -525,6 +540,7 @@ void pdp_pen_setup(void) class_addmethod(pdp_pen_class, (t_method)pdp_pen_mode, gensym("mode"), A_DEFFLOAT, A_NULL); class_addmethod(pdp_pen_class, (t_method)pdp_pen_xoffset, gensym("xoffset"), A_DEFFLOAT, A_NULL); class_addmethod(pdp_pen_class, (t_method)pdp_pen_yoffset, gensym("yoffset"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_pen_class, (t_method)pdp_pen_alpha, gensym("alpha"), A_DEFFLOAT, A_NULL); } diff --git a/modules/pdp_rec~.c b/modules/pdp_rec~.c index 2a0d68e..5b217dd 100644 --- a/modules/pdp_rec~.c +++ b/modules/pdp_rec~.c @@ -445,8 +445,8 @@ static t_int *pdp_rec_perform(t_int *w) if (fsample < -1.0) { fsample = -1.0; } isample=(short) (32767.0 * fsample); x->x_audio_buf[1][x->x_audioin_position]=isample; - x->x_audioin_position=(x->x_audioin_position+1)%(2*MAX_AUDIO_PACKET_SIZE); - if ( x->x_audioin_position == 2*MAX_AUDIO_PACKET_SIZE-1 ) + x->x_audioin_position=(x->x_audioin_position+1)%(MAX_AUDIO_PACKET_SIZE); + if ( x->x_audioin_position == MAX_AUDIO_PACKET_SIZE-1 ) { post( "pdp_rec~ : reaching end of audio buffer" ); } @@ -624,6 +624,7 @@ static void pdp_rec_free(t_pdp_rec *x) pdp_packet_mark_unused(x->x_packet0); // close video file if existing pdp_rec_close(x); + pdp_rec_free_ressources(x); for ( i=0; i<x->x_channels; i++) { if ( x->x_audio_buf[i] ) freebytes( x->x_audio_buf[i], MAX_AUDIO_PACKET_SIZE*sizeof(int16_t) ); diff --git a/modules/pdp_shape.c b/modules/pdp_shape.c index 27239c4..5f21518 100644 --- a/modules/pdp_shape.c +++ b/modules/pdp_shape.c @@ -26,7 +26,7 @@ #include "yuv.h" #include <math.h> -static char *pdp_shape_version = "pdp_shape: version 0.1, shape recongnition object written by Yves Degoyon (ydegoyon@free.fr)"; +static char *pdp_shape_version = "pdp_shape: version 0.1, shape recognition object written by Yves Degoyon (ydegoyon@free.fr)"; typedef struct pdp_shape_struct { @@ -79,15 +79,15 @@ static void pdp_shape_allocate(t_pdp_shape *x, t_int newsize) { int i; - if ( x->x_bdata ) freebytes( x->x_bdata, (( x->x_vsize + (x->x_vsize>>1))<<1)); - if ( x->x_bbdata ) freebytes( x->x_bbdata, (( x->x_vsize + (x->x_vsize>>1))<<1)); - if ( x->x_checked ) freebytes( x->x_checked, x->x_vsize ); + if ( x->x_bdata ) free( x->x_bdata ); + if ( x->x_bbdata ) free( x->x_bbdata ); + if ( x->x_checked ) free( x->x_checked ); x->x_vsize = newsize; - x->x_bdata = (short int *)getbytes((( x->x_vsize + (x->x_vsize>>1))<<1)); - x->x_bbdata = (short int *)getbytes((( x->x_vsize + (x->x_vsize>>1))<<1)); - x->x_checked = (char *)getbytes( x->x_vsize ); + x->x_bdata = (short int *)malloc((( x->x_vsize + (x->x_vsize>>1))<<1)); + x->x_bbdata = (short int *)malloc((( x->x_vsize + (x->x_vsize>>1))<<1)); + x->x_checked = (char *)malloc( x->x_vsize ); } static void pdp_shape_tolerance(t_pdp_shape *x, t_floatarg ftolerance ) @@ -451,12 +451,15 @@ static void pdp_shape_process_yv12(t_pdp_shape *x) if ( x->x_cursX != -1 ) pdp_shape_frame_detect( x, x->x_cursX, x->x_cursY ); // paint cursor in red for debug purpose - pbbY = x->x_bbdata; - pbbU = (x->x_bbdata+x->x_vsize); - pbbV = (x->x_bbdata+x->x_vsize+(x->x_vsize>>2)); - *(pbbY+x->x_cursY*x->x_vwidth+x->x_cursX) = (yuv_RGBtoY( 0xff ))<<7; - *(pbbU+(x->x_cursY>>1)*(x->x_vwidth>>1)+(x->x_cursX>>1)) = ((yuv_RGBtoU( 0xff )-128)<<8); - *(pbbV+(x->x_cursY>>1)*(x->x_vwidth>>1)+(x->x_cursX>>1)) = ((yuv_RGBtoV( 0xff )-128)<<8); + if ( x->x_cursX != -1 ) + { + pbbY = x->x_bbdata; + pbbU = (x->x_bbdata+x->x_vsize); + pbbV = (x->x_bbdata+x->x_vsize+(x->x_vsize>>2)); + *(pbbY+x->x_cursY*x->x_vwidth+x->x_cursX) = (yuv_RGBtoY( 0xff ))<<7; + *(pbbU+(x->x_cursY>>1)*(x->x_vwidth>>1)+(x->x_cursX>>1)) = ((yuv_RGBtoU( 0xff )-128)<<8); + *(pbbV+(x->x_cursY>>1)*(x->x_vwidth>>1)+(x->x_cursX>>1)) = ((yuv_RGBtoV( 0xff )-128)<<8); + } memcpy( newdata, x->x_bbdata, (x->x_vsize+(x->x_vsize>>1))<<1 ); diff --git a/modules/pdp_text.c b/modules/pdp_text.c index d4eef94..5d2d633 100644 --- a/modules/pdp_text.c +++ b/modules/pdp_text.c @@ -60,6 +60,7 @@ typedef struct pdp_text_struct t_int *x_g; t_int *x_b; t_float *x_angle; + t_float x_alpha; t_int *x_scroll; t_int x_nbtexts; @@ -154,7 +155,7 @@ static void pdp_text_add(t_pdp_text *x, t_symbol *s, int argc, t_atom *argv) { x->x_angle[x->x_nbtexts] = argv[6].a_w.w_float; } - if ( (argc>=8) && (argv[7].a_type == A_FLOAT) ) + if ( (argc>=8) && (argv[7].a_type == A_FLOAT) ) { x->x_scroll[x->x_nbtexts] = (int)argv[7].a_w.w_float; } @@ -224,6 +225,14 @@ static void pdp_text_angle(t_pdp_text *x, t_floatarg fangle ) } } +static void pdp_text_alpha(t_pdp_text *x, t_floatarg falpha ) +{ + if ( ( falpha >= 0. ) && ( falpha <= 1. ) ) + { + x->x_alpha = falpha; + } +} + static void pdp_text_scroll(t_pdp_text *x, t_floatarg fscroll ) { if ( ( x->x_current >= 0 ) && ( x->x_current < x->x_nbtexts ) ) @@ -456,11 +465,11 @@ static void pdp_text_process_yv12(t_pdp_text *x) u = yuv_RGBtoU(imdata[py*x->x_vwidth+px]); v = yuv_RGBtoV(imdata[py*x->x_vwidth+px]); - *(pY) = y<<7; + *(pY) = ((y)<<7)*x->x_alpha + (*pY)*(1-x->x_alpha); if ( (px%2==0) && (py%2==0) ) { - *(pV) = (v-128)<<8; - *(pU) = (u-128)<<8; + *(pV) = ((v-128)<<8)*x->x_alpha + *(pV)*(1-x->x_alpha); + *(pU) = ((u-128)<<8)*x->x_alpha + *(pU)*(1-x->x_alpha); } } pY++; @@ -557,6 +566,7 @@ void *pdp_text_new(void) inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("textb")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("angle")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("scroll")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("alpha")); x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); x->x_packet0 = -1; @@ -585,6 +595,7 @@ void *pdp_text_new(void) x->x_nbtexts = 0; x->x_current = -1; + x->x_alpha = 1.; return (void *)x; } @@ -618,6 +629,7 @@ void pdp_text_setup(void) class_addmethod(pdp_text_class, (t_method)pdp_text_resize, gensym("resize"), A_DEFFLOAT, A_NULL); class_addmethod(pdp_text_class, (t_method)pdp_text_font, gensym("font"), A_SYMBOL, A_NULL); class_addmethod(pdp_text_class, (t_method)pdp_text_angle, gensym("angle"), A_DEFFLOAT, A_NULL); + class_addmethod(pdp_text_class, (t_method)pdp_text_alpha, gensym("alpha"), A_DEFFLOAT, A_NULL); class_addmethod(pdp_text_class, (t_method)pdp_text_scroll, gensym("scroll"), A_DEFFLOAT, A_NULL); class_addmethod(pdp_text_class, (t_method)pdp_text_dither, gensym("dither"), A_DEFFLOAT, A_NULL); class_addmethod(pdp_text_class, (t_method)pdp_text_blend, gensym("blend"), A_DEFFLOAT, A_NULL); diff --git a/modules/pdp_underwatch.c b/modules/pdp_underwatch.c index 674582f..c999ceb 100644 --- a/modules/pdp_underwatch.c +++ b/modules/pdp_underwatch.c @@ -73,19 +73,12 @@ static void pdp_underwatch_process_yv12(t_pdp_underwatch *x) short int *p=0, *po=0, *pu=0, *pv=0, *pou=0, *pov=0; int i; - unsigned int u_offset; - unsigned int v_offset; - unsigned int totnbpixels; int px, py, pd, t; x->x_vwidth = header->info.image.width; x->x_vheight = header->info.image.height; x->x_vsize = x->x_vwidth*x->x_vheight; - u_offset = x->x_vsize; - v_offset = x->x_vsize + (x->x_vsize>>2); - totnbpixels = x->x_vsize + (x->x_vsize>>1); - newheader->info.image.encoding = header->info.image.encoding; newheader->info.image.width = x->x_vwidth; newheader->info.image.height = x->x_vheight; diff --git a/modules/pdp_yqt.c b/modules/pdp_yqt.c index d0ada83..8795f77 100644 --- a/modules/pdp_yqt.c +++ b/modules/pdp_yqt.c @@ -237,7 +237,7 @@ static void pdp_yqt_bang(t_pdp_yqt *x) if ( gettimeofday(&etime, NULL) == -1) { - post("pdp_fcqt : could not get time" ); + post("pdp_yqt : could not get time" ); } if ( etime.tv_sec != x->x_cursec ) { @@ -248,7 +248,6 @@ static void pdp_yqt_bang(t_pdp_yqt *x) x->x_framescount++; outlet_float(x->x_curframe, (float)pos); - pdp_packet_pass_if_valid(x->x_outlet0, &object); // fills in the audio buffer with a chunk if necessary if ( x->x_audio && x->x_outunread < MIN_AUDIO_INPUT ) @@ -285,6 +284,8 @@ static void pdp_yqt_bang(t_pdp_yqt *x) } } + pdp_packet_pass_if_valid(x->x_outlet0, &object); + } static void pdp_yqt_loop(t_pdp_yqt *x, t_floatarg loop) |