#include #include #include #include #include #include #ifdef __cplusplus #include "libzmpeg3.h" #else #include "../libmpeg3/libmpeg3.h" #define zmpeg3_t mpeg3_t #endif #define AUDIO #define VIDEO /* c++ `pkg-config --cflags --libs gtk+-2.0` y.C ./x86_64/libzmpeg3.a -lpthread -lasound -lm */ #ifdef AUDIO snd_pcm_t *zpcm; snd_pcm_uframes_t zpcm_ufrm_size; snd_pcm_sframes_t zpcm_sbfr_size; snd_pcm_sframes_t zpcm_sper_size; unsigned int zpcm_rate; static const char *zpcm_device = "plughw:0,0"; static unsigned int zpcm_bfr_time_us = 500000; static unsigned int zpcm_per_time_us = 200000; static snd_pcm_channel_area_t *zpcm_areas = 0; static int zpcm_channels = 0; static short **zpcm_buffers = 0; static short *zpcm_samples = 0; void alsa_close() { #ifdef __cplusplus if( zpcm_buffers != 0 ) { delete [] zpcm_buffers; zpcm_buffers = 0; } if( zpcm_areas != 0 ) { delete [] zpcm_areas; zpcm_areas = 0; } if( zpcm_samples != 0 ) { delete [] zpcm_samples; zpcm_samples = 0; } #else if( zpcm_buffers != 0 ) { free(zpcm_buffers); zpcm_buffers = 0; } if( zpcm_areas != 0 ) { free(zpcm_areas); zpcm_areas = 0; } if( zpcm_samples != 0 ) { free(zpcm_samples); zpcm_samples = 0; } #endif if( zpcm != 0 ) { snd_pcm_close(zpcm); zpcm = 0; } } void alsa_open(int chs,int rate) { int ich, bits, byts, dir, ret; snd_pcm_format_t fmt = SND_PCM_FORMAT_S16; snd_pcm_hw_params_t *phw; snd_pcm_sw_params_t *psw; snd_pcm_hw_params_alloca(&phw); snd_pcm_sw_params_alloca(&psw); zpcm = 0; ret = snd_pcm_open(&zpcm, zpcm_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if( ret >= 0 ) ret = snd_pcm_hw_params_any(zpcm, phw); if( ret >= 0 ) ret = snd_pcm_hw_params_set_rate_resample(zpcm, phw, 1); if( ret >= 0 ) ret = snd_pcm_hw_params_set_access(zpcm, phw, SND_PCM_ACCESS_RW_NONINTERLEAVED); if( ret >= 0 ) ret = snd_pcm_hw_params_set_format(zpcm, phw, fmt); if( ret >= 0 ) { zpcm_channels = chs; ret = snd_pcm_hw_params_set_channels(zpcm, phw, chs); } if( ret >= 0 ) { zpcm_rate = rate; ret = snd_pcm_hw_params_set_rate_near(zpcm, phw, &zpcm_rate, 0); if( (int)zpcm_rate != rate ) printf("nearest audio_rate for %d is %u\n",rate,zpcm_rate); } if( ret >= 0 ) ret = snd_pcm_hw_params_set_buffer_time_near(zpcm, phw, &zpcm_bfr_time_us, &dir); if( ret >= 0 ) ret = snd_pcm_hw_params_get_buffer_size(phw, &zpcm_ufrm_size); if( ret >= 0 ) { zpcm_sbfr_size = zpcm_ufrm_size; ret = snd_pcm_hw_params_set_period_time_near(zpcm, phw, &zpcm_per_time_us, &dir); } if( ret >= 0 ) ret = snd_pcm_hw_params_get_period_size(phw, &zpcm_ufrm_size, &dir); if( ret >= 0 ) { zpcm_sper_size = zpcm_ufrm_size; ret = snd_pcm_hw_params(zpcm, phw); } if( ret >= 0 ) ret = snd_pcm_sw_params_current(zpcm, psw); if( ret >= 0 ) ret = snd_pcm_sw_params_set_start_threshold(zpcm, psw, (zpcm_sbfr_size / zpcm_sper_size) * zpcm_sper_size); if( ret >= 0 ) ret = snd_pcm_sw_params_set_avail_min(zpcm, psw, zpcm_sper_size); if( ret >= 0 ) ret = snd_pcm_sw_params(zpcm, psw); /* snd_pcm_dump(zpcm, stdout); */ if( ret >= 0 ) { #ifdef __cplusplus zpcm_areas = new snd_pcm_channel_area_t[chs]; byts = snd_pcm_format_physical_width(fmt) / 8; zpcm_samples = new short[zpcm_sper_size * chs * byts/2]; zpcm_buffers = new short *[chs]; #else zpcm_areas = calloc(chs, sizeof(snd_pcm_channel_area_t)); bits = snd_pcm_format_physical_width(fmt); byts = bits / 8; zpcm_samples = malloc(zpcm_sper_size * chs * byts); zpcm_buffers = malloc(chs * sizeof(short*)); #endif if( zpcm_samples ) { for( ich = 0; ich < chs; ++ich ) { zpcm_areas[ich].addr = zpcm_samples; zpcm_areas[ich].first = ich * zpcm_sper_size * bits; zpcm_areas[ich].step = bits; zpcm_buffers[ich] = zpcm_samples + ich*zpcm_sper_size; } } else { fprintf(stderr,"alsa sample buffer allocation failure.\n"); ret = -999; } } if( ret < 0 ) { if( ret > -999 ) printf("audio error: %s\n", snd_strerror(ret)); alsa_close(); } } short *alsa_bfr(int ch) { return zpcm_buffers[ch]; } int alsa_bfrsz() { return zpcm_sper_size; } int alsa_recovery(int ret) { printf("alsa recovery\n"); switch( ret ) { case -ESTRPIPE: /* wait until the suspend flag is released, then fall through */ while( (ret=snd_pcm_resume(zpcm)) == -EAGAIN ) usleep(100000); case -EPIPE: ret = snd_pcm_prepare(zpcm); if( ret < 0 ) printf("underrun, prepare failed: %s\n", snd_strerror(ret)); break; default: printf("unhandled error: %s\n",snd_strerror(ret)); break; } return ret; } int alsa_write(int len) { int i, ret; #ifdef __cplusplus short *bfrs[zpcm_channels]; #else short **bfrs = alloca(zpcm_channels*sizeof(short *)); #endif ret = 0; for( i=0; i 0 ) { ret = snd_pcm_writen(zpcm,(void **)bfrs, len); if( ret == -EAGAIN ) continue; if ( ret < 0 ) { alsa_recovery(ret); break; } for( i=0; imem, GDK_COLORSPACE_RGB,FALSE,8,owidth,oheight,owidth*3,NULL,NULL); cap0 = gdk_pixbuf_get_pixels(pbuf0); image = gtk_image_new_from_pixbuf(pbuf0); /* double buffered */ img1 = gdk_image_new(GDK_IMAGE_SHARED, visual, owidth, oheight); pbuf1 = gdk_pixbuf_new_from_data((const guchar *)img1->mem, GDK_COLORSPACE_RGB,FALSE,8,owidth,oheight,owidth*3,NULL,NULL); cap1 = gdk_pixbuf_get_pixels(pbuf1); panel_hbox = gtk_hbox_new(FALSE,0); gtk_container_add(GTK_CONTAINER(window), panel_hbox); /* pack image into panel */ gtk_box_pack_start(GTK_BOX(panel_hbox), image, TRUE, TRUE, 0); #ifdef __cplusplus row0 = new unsigned char *[oheight]; row1 = new unsigned char *[oheight]; int cmdl = zmpeg3_t::cmdl_RGB888; #else row0 = malloc(oheight*sizeof(unsigned char *)); row1 = malloc(oheight*sizeof(unsigned char *)); int cmdl = MPEG3_RGB888; #endif for( row=0; rowstyle->black_gc; gdk_draw_rgb_image(image->window,blk, 0,0,owidth,oheight, GDK_RGB_DITHER_NONE,cap,owidth*3); *(unsigned long *)&cap ^= ((unsigned long)cap0 ^ (unsigned long)cap1); *(unsigned long *)&rows ^= ((unsigned long)row0 ^ (unsigned long)row1); now = the_time(); znow = mpeg3_get_time(zsrc); if( zstart < 0. ) zstart = znow; delay = (znow-zstart) - (now-start); if( delay > 0 ) usleep((int)(delay*100000.0)); more_data |= !mpeg3_end_of_video(zsrc,0); #endif ++frame; #ifdef VIDEO } else gtk_main_iteration(); #endif } #ifdef AUDIO alsa_close(); #endif mpeg3_close(zsrc); return 0; }