From c5e843b82205c04c618a423d3bb223f1f630b7a1 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 11 Aug 2003 04:26:00 +0000 Subject: added sources from pidip-0.12.4 svn path=/trunk/externals/pidip/; revision=837 --- modules/pdp_yqt.c | 444 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 444 insertions(+) create mode 100644 modules/pdp_yqt.c (limited to 'modules/pdp_yqt.c') diff --git a/modules/pdp_yqt.c b/modules/pdp_yqt.c new file mode 100644 index 0000000..5f0ebbe --- /dev/null +++ b/modules/pdp_yqt.c @@ -0,0 +1,444 @@ +/* + * Pure Data Packet module. + * Copyright (c) by Tom Schouten + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + + +#include "pdp.h" +#include "pdp_llconv.h" +#include +#include + +#define MIN_AUDIO_INPUT 1024 /* we must have at least n chunks to play a steady sound */ +#define OUTPUT_BUFFER_SIZE 128*1024 /* audio output buffer : 128k */ +#define DECODE_PACKET_SIZE 16*1024 /* size of audio data decoded in one call */ + +typedef struct pdp_yqt_data +{ + short int gain[4]; +} t_pdp_yqt_data; + +typedef struct pdp_yqt_struct +{ + t_object x_obj; + t_float x_f; + + t_outlet *x_outlet0; + t_outlet *x_outlet1; + t_outlet *x_outlet2; + t_outlet *x_outlet3; /* audio left channel */ + t_outlet *x_outlet4; /* audio right channel */ + + int packet0; + bool initialized; + + unsigned int x_vwidth; + unsigned int x_vheight; + + bool loop; + + unsigned char * qt_rows[3]; + + unsigned char * qt_frame; + quicktime_t *qt; + int qt_cmodel; + + t_int x_audio; /* indicates the existence of an audio track */ + t_int x_audio_channels; /* number of audio channels of first track */ + t_int x_mono; /* indicates a mono audio track */ + t_int x_audio_rate; /* audio rate */ + t_int x_resampling_factor; /* resampling factor */ + + t_float *x_outbuffer; /* buffer to store audio decoded data */ + t_int x_outwriteposition; + t_int x_outreadposition; + t_int x_outunread; + t_int x_outbuffersize; + t_float *x_outl; + t_float *x_outr; + + t_pdp_yqt_data *state_data; + +} t_pdp_yqt; + + + +static void pdp_yqt_close(t_pdp_yqt *x) +{ + if (x->initialized){ + quicktime_close(x->qt); + free(x->qt_frame); + x->initialized = false; + } + +} + +static void pdp_yqt_open(t_pdp_yqt *x, t_symbol *name) +{ + unsigned int size; + + post("pdp_yqt: opening %s", name->s_name); + + pdp_yqt_close(x); + + x->qt = quicktime_open(name->s_name, 1, 0); + + if (!(x->qt)){ + post("pdp_yqt: error opening qt file"); + x->initialized = false; + return; + } + + if (!quicktime_has_video(x->qt)) { + post("pdp_yqt: no video stream"); + quicktime_close(x->qt); + x->initialized = false; + return; + + } + else if (!quicktime_supported_video(x->qt,0)) { + post("pdp_yqt: unsupported video codec\n"); + quicktime_close(x->qt); + x->initialized = false; + return; + } + else + { + x->qt_cmodel = BC_YUV420P; + x->x_vwidth = quicktime_video_width(x->qt,0); + x->x_vheight = quicktime_video_height(x->qt,0); + x->qt_frame = (unsigned char*)malloc(x->x_vwidth*x->x_vheight*4); + size = x->x_vwidth * x->x_vheight; + x->qt_rows[0] = &x->qt_frame[0]; + x->qt_rows[2] = &x->qt_frame[size]; + x->qt_rows[1] = &x->qt_frame[size + (size>>2)]; + + quicktime_set_cmodel(x->qt, x->qt_cmodel); + x->initialized = true; + outlet_float(x->x_outlet2, (float)quicktime_video_length(x->qt,0)); + + } + + if (!quicktime_has_audio(x->qt)) { + post("pdp_yqt: warning : no audio stream"); + x->x_audio = 0; + return; + } + + if ( quicktime_audio_tracks(x->qt) > 1 ) + { + post("pdp_yqt: warning : more that one audio track, using first one"); + } + + if ( ( x->x_audio_channels = quicktime_track_channels(x->qt, 0) ) != 2 ) { + x->x_mono=0; + post("pdp_yqt: track 0 has %d channels", x->x_audio_channels ); + post("pdp_yqt: warning : not a stereo audio track ( audio channels : %d )", x->x_audio_channels ); + if ( x->x_audio_channels == 1 ) x->x_mono = 1; + else x->x_audio_channels = 2; + } else { + post("pdp_yqt: track 0 has %d channels", x->x_audio_channels ); + } + + if (!quicktime_supported_audio(x->qt,0)) { + post("pdp_yqt: warning : audio not supported" ); + x->x_audio = 0; + } else { + x->x_audio = 1; + } + + if ( x->x_audio ) + { + post("pdp_yqt: using audio track 0 with %d channels", x->x_audio_channels ); + post("pdp_yqt: audio data is %d bytes, %d kHz compressed with %s", + quicktime_audio_bits(x->qt, 0), + x->x_audio_rate = quicktime_sample_rate(x->qt, 0), + quicktime_audio_compressor(x->qt, 0) ); + x->x_resampling_factor = ( sys_getsr() / x->x_audio_rate ); + } + +} + + +static void pdp_yqt_bang(t_pdp_yqt *x) +{ + unsigned int w, h, nbpixels, packet_size; + int object, length, pos, i, j; + short int* data; + t_pdp* header; + + static short int gain[4] = {0x7fff, 0x7fff, 0x7fff, 0x7fff}; + + if (!(x->initialized)){ + //post("pdp_yqt: no qt file opened"); + return; + } + + w = x->x_vwidth; + h = x->x_vheight; + nbpixels = w * h; + packet_size = (nbpixels + (nbpixels >> 1)) << 1; + + object = pdp_packet_new_image_YCrCb( x->x_vwidth, x->x_vheight ); + header = pdp_packet_header(object); + data = (short int *) pdp_packet_data(object); + + header->info.image.encoding = PDP_IMAGE_YV12; + header->info.image.width = w; + header->info.image.height = h; + + length = quicktime_video_length(x->qt,0); + pos = quicktime_video_position(x->qt,0); + // post("pdp_yqt : video position : %d length =%d", pos, length ); + + if (pos >= length){ + pos = (x->loop) ? 0 : length - 1; + // post("pdp_yqt : setting video position to %d", pos); + quicktime_set_video_position(x->qt, pos, 0); + if (x->loop) + { + // post("pdp_yqt : resetting audio position"); + if ( x->x_audio ) quicktime_set_audio_position(x->qt, 0, 0); + } + } + + lqt_decode_video(x->qt, x->qt_rows, 0); + + switch(x->qt_cmodel){ + case BC_YUV420P: + pdp_llconv(x->qt_frame, RIF_YVU__P411_U8, data, RIF_YVU__P411_S16, x->x_vwidth, x->x_vheight); + break; + + case BC_YUV422: + pdp_llconv(x->qt_frame, RIF_YUYV_P____U8, data, RIF_YVU__P411_S16, x->x_vwidth, x->x_vheight); + break; + + case BC_RGB888: + pdp_llconv(x->qt_frame, RIF_RGB__P____U8, data, RIF_YVU__P411_S16, x->x_vwidth, x->x_vheight); + break; + + default: + post("pdp_yqt : error on decode: unkown colour model"); + break; + } + + outlet_float(x->x_outlet1, (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 ) + { + int csize, rsize; + + // watch remaining size + rsize = (int ) ( quicktime_audio_length(x->qt, 0) - quicktime_audio_position(x->qt, 0) ); + csize = ( rsize < DECODE_PACKET_SIZE ) ? rsize : DECODE_PACKET_SIZE; + + // post("pdp_yqt : decode one chunk (size=%d)", csize ); + if ( ( quicktime_decode_audio(x->qt, NULL, x->x_outl, csize, 1) <0 ) || + ( !x->x_mono && ( quicktime_decode_audio(x->qt, NULL, x->x_outl, csize, 2) <0 ) ) ) + { + post("pdp_yqt : could not decode audio data" ); + } else { + for ( i=0; ix_outunread >= x->x_outbuffersize-2 ) + { + post( "pdp_yqt: decode audio : too much input ... ignored" ); + continue; + } + for ( j=0; jx_resampling_factor; j++ ) + { + *(x->x_outbuffer+x->x_outwriteposition) = x->x_outl[i]; + x->x_outwriteposition = (x->x_outwriteposition + 1)%x->x_outbuffersize; + *(x->x_outbuffer+x->x_outwriteposition) = + ((x->x_mono)? x->x_outl[i] : x->x_outr[i] ); + x->x_outwriteposition = (x->x_outwriteposition + 1)%x->x_outbuffersize; + x->x_outunread+=2; + } + } + } + } + +} + +static void pdp_yqt_loop(t_pdp_yqt *x, t_floatarg loop) +{ + int loopi = (int)loop; + x->loop = !(loopi == 0); +} + +static void pdp_yqt_frame_cold(t_pdp_yqt *x, t_floatarg frameindex) +{ + int frame = (int)frameindex; + int length; + + + if (!(x->initialized)) return; + + length = quicktime_video_length(x->qt,0); + + frame = (frame >= length) ? length-1 : frame; + frame = (frame < 0) ? 0 : frame; + + // post("pdp_yqt : frame cold : setting video position to : %d", frame ); + quicktime_set_video_position(x->qt, frame, 0); +} + +static void pdp_yqt_frame(t_pdp_yqt *x, t_floatarg frameindex) +{ + // pdp_yqt_frame_cold(x, frameindex); + pdp_yqt_bang(x); +} + +static void pdp_yqt_gain(t_pdp_yqt *x, t_floatarg f) +{ + int i; + short int g; + float bound = (float)0x7fff; + + f *= (float)0x7fff; + + f = (f>bound) ? bound : f; + f = (f<-bound) ? -bound : f; + + g = (short int)f; + + for (i=0; i<4; i++) x->state_data->gain[i] = g; +} + +static void pdp_yqt_free(t_pdp_yqt *x) +{ + + free (x->state_data); + pdp_yqt_close(x); + + freebytes(x->x_outbuffer, OUTPUT_BUFFER_SIZE*sizeof(t_float)); + freebytes(x->x_outl, DECODE_PACKET_SIZE*sizeof(t_float)); + freebytes(x->x_outr, DECODE_PACKET_SIZE*sizeof(t_float)); +} + +t_class *pdp_yqt_class; + +void *pdp_yqt_new(void) +{ + t_pdp_yqt *x = (t_pdp_yqt *)pd_new(pdp_yqt_class); + + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("frame_cold")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("gain")); + + x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); + x->x_outlet1 = outlet_new(&x->x_obj, &s_float); + x->x_outlet2 = outlet_new(&x->x_obj, &s_float); + + x->x_outlet3 = outlet_new(&x->x_obj, &s_signal); /* audio left channel */ + x->x_outlet4 = outlet_new(&x->x_obj, &s_signal); /* audio right channel */ + + x->packet0 = -1; + + x->initialized = false; + + x->loop = false; + + x->state_data = (t_pdp_yqt_data *)malloc(sizeof(t_pdp_yqt_data)); + pdp_yqt_gain(x, 1.0f); + + // allocate audio buffers + x->x_outbuffersize = OUTPUT_BUFFER_SIZE; + x->x_outl = (t_float*) getbytes(DECODE_PACKET_SIZE*sizeof(t_float)); + x->x_outr = (t_float*) getbytes(DECODE_PACKET_SIZE*sizeof(t_float)); + x->x_outbuffer = (t_float*) getbytes(OUTPUT_BUFFER_SIZE*sizeof(t_float)); + + if ( !x->x_outl || !x->x_outr || !x->x_outbuffer ) + { + post( "mp3amp~: could not allocate buffers" ); + return NULL; + } + memset( x->x_outl, 0x0, DECODE_PACKET_SIZE*sizeof(t_float) ); + memset( x->x_outr, 0x0, DECODE_PACKET_SIZE*sizeof(t_float) ); + memset( x->x_outbuffer, 0x0, OUTPUT_BUFFER_SIZE*sizeof(t_float) ); + + x->x_outreadposition = 0; + x->x_outwriteposition = 0; + x->x_outunread = 0; + + return (void *)x; +} + +static t_int *pdp_yqt_perform(t_int *w) +{ + t_pdp_yqt *x = (t_pdp_yqt*) (w[1]); + t_float *out1 = (t_float *)(w[2]); + t_float *out2 = (t_float *)(w[3]); + int n = (int)(w[4]); + int ret; + int i = 0; + + while( n-- ) + { + if ( x->x_audio && x->x_outunread > 0 ) + { + *out1++=*(x->x_outbuffer+x->x_outreadposition); + x->x_outreadposition = (x->x_outreadposition + 1)%x->x_outbuffersize; + *out2++=*(x->x_outbuffer+x->x_outreadposition); + x->x_outreadposition = (x->x_outreadposition + 1)%x->x_outbuffersize; + x->x_outunread-=2; + } + else + { + *out1++=0.; + *out2++=0.; + } + } + + return (w+5); +} + +static void pdp_yqt_dsp(t_pdp_yqt *x, t_signal **sp) +{ + dsp_add(pdp_yqt_perform, 4, x, sp[1]->s_vec, sp[2]->s_vec, sp[1]->s_n); +} + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +void pdp_yqt_setup(void) +{ + pdp_yqt_class = class_new(gensym("pdp_yqt"), (t_newmethod)pdp_yqt_new, + (t_method)pdp_yqt_free, sizeof(t_pdp_yqt), 0, A_NULL); + + class_addmethod(pdp_yqt_class, (t_method)pdp_yqt_bang, gensym("bang"), A_NULL); + class_addmethod(pdp_yqt_class, (t_method)pdp_yqt_close, gensym("close"), A_NULL); + class_addmethod(pdp_yqt_class, (t_method)pdp_yqt_open, gensym("open"), A_SYMBOL, A_NULL); + class_addmethod(pdp_yqt_class, (t_method)pdp_yqt_loop, gensym("loop"), A_DEFFLOAT, A_NULL); + class_addfloat (pdp_yqt_class, (t_method)pdp_yqt_frame); + class_addmethod(pdp_yqt_class, (t_method)pdp_yqt_frame_cold, gensym("frame_cold"), A_FLOAT, A_NULL); + class_addmethod(pdp_yqt_class, (t_method)pdp_yqt_gain, gensym("gain"), A_FLOAT, A_NULL); + class_addmethod(pdp_yqt_class, nullfn, gensym("signal"), 0); + class_addmethod(pdp_yqt_class, (t_method)pdp_yqt_dsp, gensym("dsp"), 0); + +} + +#ifdef __cplusplus +} +#endif -- cgit v1.2.1