X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Flibzmpeg3%2Fdmux.C;fp=cinelerra-5.1%2Flibzmpeg3%2Fdmux.C;h=879cd8a2d69c6f6f9b7cfff26675f01102da4359;hb=30bdb85eb33a8ee7ba675038a86c6be59c43d7bd;hp=0000000000000000000000000000000000000000;hpb=52fcc46226f9df46f9ce9d0566dc568455a7db0b;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/libzmpeg3/dmux.C b/cinelerra-5.1/libzmpeg3/dmux.C new file mode 100644 index 00000000..879cd8a2 --- /dev/null +++ b/cinelerra-5.1/libzmpeg3/dmux.C @@ -0,0 +1,931 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* c++ `pkg-config --cflags --libs gtk+-2.0` dmux.C thread.C ./x86_64/libzmpeg3.a -lpthread -lasound -lm */ + +#include "libzmpeg3.h" +#include "thread.h" + +double the_time(); +void reset(); +int open_tuner(int dev_no,int chan,int vid_pid,int aud_pid); +void close_tuner(); +double audio_time(int stream); +void alsa_close(); +void alsa_open(int chs,int rate); +short *alsa_bfr(int ch); +int alsa_bfrsz(); +int alsa_recovery(int ret); +int alsa_write(int len); +void dst_exit(GtkWidget *widget, gpointer data); +gint key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer data); +double video_time(int stream); +void stats(); +void sig_int(int n); +int main(int ac,char **av); + +/* alpha currently is broken in gdk */ +/* would render faster if alpha worked correctly */ +#define RGBA FALSE + +#if RGBA +#define BPP 4 +#define COLOR_MODEL zmpeg3_t::cmdl_RGBA8888 +#else +#define BPP 3 +#define COLOR_MODEL zmpeg3_t::cmdl_RGB888 +#endif + +int verbose = 0; +double nudge = .5; // 3.5; +const double ahead = .5; + +//#define DEBUG +#ifndef DEBUG +#define dprintf(s...) do{}while(0) +#else +#define dprintf(s...) printf(s) +#endif + +#define NETTUNE_AIR 1 +#define NETTUNE_CABLE 2 + +static unsigned long ntsc_dvb[ ] = { + 0, 0, 57, 63, 69, 79, 85, 177, 183, 189 , + 195, 201, 207, 213, 473, 479, 485, 491, 497, 503 , + 509, 515, 521, 527, 533, 539, 545, 551, 557, 563 , + 569, 575, 581, 587, 593, 599, 605, 611, 617, 623 , + 629, 635, 641, 647, 653, 659, 665, 671, 677, 683 , + 689, 695, 701, 707, 713, 719, 725, 731, 737, 743 , + 749, 755, 761, 767, 773, 779, 785, 791, 797, 803 , + 809, 815, 821, 827, 833, 839, 845, 851, 857, 863 , + 869, 875, 881, 887, 893, 899, 905, 911, 917, 923 , + 929, 935, 941, 947, 953, 959, 965, 971, 977, 983 , + 989, 995, 1001, 1007, 1013, 1019, 1025, 1031, 1037, 1043 +}; + +static unsigned long catv_dvb[] = { + 0, 0, 57, 63, 69, 79, 85, 177, 183, 189, + 195, 201, 207, 213, 123, 129, 135, 141, 147, 153, + 159, 165, 171, 219, 225, 231, 237, 243, 249, 255, + 261, 267, 273, 279, 285, 291, 297, 303, 309, 315, + 321, 327, 333, 339, 345, 351, 357, 363, 369, 375, + 381, 387, 393, 399, 405, 411, 417, 423, 429, 435, + 441, 447, 453, 459, 465, 471, 477, 483, 489, 495, + 501, 507, 513, 519, 525, 531, 537, 543, 549, 555, + 561, 567, 573, 579, 585, 591, 597, 603, 609, 615, + 621, 627, 633, 639, 645, 93, 99, 105, 111, 117, + 651, 657, 663, 669, 675, 681, 687, 693, 699, 705, + 711, 717, 723, 729, 735, 741, 747, 753, 759, 765, + 771, 777, 783, 789, 795, 781, 807, 813, 819, 825, + 831, 837, 843, 849, 855, 861, 867, 873, 879, 885, + 891, 897, 903, 909, 915, 921, 927, 933, 939, 945, + 951, 957, 963, 969, 975, 981, 987, 993, 999 +}; + +int frontend_fd; +int audio_fd; +int video_fd; +int dvr_fd; +int prev_lock; +int has_lock; +int done; +zmpeg3_t *zsrc; +int aud, vid; +int subchan; +int audio_done; +int video_done; + +class vid_thread : public Thread +{ + void Proc(); +} *the_vid; + +class aud_thread : public Thread +{ + void Proc(); +} *the_aud; + +class lck_thread : public Thread +{ + void Proc(); +} *the_lck; + +int do_status() +{ + fe_status_t status; + uint16_t snr, signal; + uint32_t ber, uncorrected_blocks; + + bzero(&status, sizeof(status)); + ioctl(frontend_fd, FE_READ_STATUS, &status); + if( verbose ) { + ioctl(frontend_fd, FE_READ_SIGNAL_STRENGTH, &signal); + ioctl(frontend_fd, FE_READ_SNR, &snr); + ioctl(frontend_fd, FE_READ_BER, &ber); + ioctl(frontend_fd, FE_READ_UNCORRECTED_BLOCKS, &uncorrected_blocks); + printf("lck:: %02x | signal %04x | snr %04x | ber %08x | unc %08x | ", + status, signal, snr, ber, uncorrected_blocks); + } + has_lock = status & FE_HAS_LOCK ? 1 : 0; + if( verbose ) + printf( has_lock ? "lock\n" : "lost\n" ); + if( prev_lock != has_lock ) { + printf(" %s\n",has_lock ? "signal locked" : "signal lost"); + prev_lock = has_lock; + } + return has_lock; +} + +void lck_thread:: +Proc() +{ + dprintf("lck_thread::Proc()\n"); + while( Running() ) { + do_status(); + sleep(1); + } +} + +double tstart; + +double the_time() +{ + double time; + struct timeval tv; + gettimeofday(&tv,NULL); + time = tv.tv_sec + tv.tv_usec/1000000.0; + if( tstart < 0. ) tstart = time; + return time - tstart; +} + +void reset() +{ + frontend_fd = -1; + audio_fd = -1; + video_fd = -1; + dvr_fd = -1; + the_vid = 0; + the_lck = 0; + prev_lock = 0; + has_lock = 0; + tstart = -1.; + aud = 0; + vid = 0; + subchan = -1; +} + +int open_tuner(int dev_no,int chan,int vid_pid,int aud_pid) +{ + char frontend_path[512]; + char demux_path[512]; + char dvr_path[512]; + //dvr_fd = open("/tmp/dat7",O_RDONLY); + //return dvr_fd >= 0 ? 0 : 1; + + sprintf(frontend_path, "/dev/dvb/adapter%d/frontend%d", dev_no, 0); + sprintf(demux_path, "/dev/dvb/adapter%d/demux%d", dev_no, 0); + sprintf(dvr_path, "/dev/dvb/adapter%d/dvr%d", dev_no, 0); + if( (frontend_fd=::open(frontend_path, O_RDWR)) < 0 ) { + fprintf(stderr, "open_tuner %s: %s\n", frontend_path, strerror(errno)); + return 1; + } + + struct dvb_frontend_parameters frontend_param; + bzero(&frontend_param, sizeof(frontend_param)); + +// Set frequency + int index = chan; + int table = NETTUNE_AIR; + + switch(table) { + case NETTUNE_AIR: + frontend_param.frequency = ntsc_dvb[index] * 1000000; + frontend_param.u.vsb.modulation = VSB_8; + break; + case NETTUNE_CABLE: + frontend_param.frequency = catv_dvb[index] * 1000000; + frontend_param.u.vsb.modulation = QAM_AUTO; + break; + } + + if( ioctl(frontend_fd, FE_SET_FRONTEND, &frontend_param) < 0 ) { + fprintf(stderr, "open_tuner FE_SET_FRONTEND frequency=%d: %s", + frontend_param.frequency, strerror(errno)); + return 1; + } + + int retry = 5; + while( !do_status() && --retry>=0 ) sleep(1); + + if( retry < 0 ) { + fprintf(stderr, "open_tuner: no signal on channel %d\n",chan); + return 1; + } + + if( (video_fd=::open(demux_path, O_RDWR)) < 0 ) { + fprintf(stderr, "open_tuner %s for video: %s\n", + demux_path, strerror(errno)); + return 1; + } + +// Setting exactly one PES filter to 0x2000 dumps the entire +// transport stream. + struct dmx_pes_filter_params pesfilter; + if( !vid_pid && !aud_pid ) { + pesfilter.pid = 0x2000; + pesfilter.input = DMX_IN_FRONTEND; + pesfilter.output = DMX_OUT_TS_TAP; + pesfilter.pes_type = DMX_PES_OTHER; + pesfilter.flags = DMX_IMMEDIATE_START; + if( ioctl(video_fd, DMX_SET_PES_FILTER, &pesfilter) < 0 ) { + fprintf(stderr, "open_tuner DMX_SET_PES_FILTER for raw: %s\n", + strerror(errno)); + return 1; + } + } + + + if( vid_pid ) { + pesfilter.pid = vid_pid; + pesfilter.input = DMX_IN_FRONTEND; + pesfilter.output = DMX_OUT_TS_TAP; + pesfilter.pes_type = DMX_PES_VIDEO; + pesfilter.flags = DMX_IMMEDIATE_START; + if( ioctl(video_fd, DMX_SET_PES_FILTER, &pesfilter) < 0 ) { + fprintf(stderr, "open_tuner DMX_SET_PES_FILTER for video: %s\n", + strerror(errno)); + return 1; + } + } + + if( aud_pid ) { + if( (audio_fd=::open(demux_path,O_RDWR)) < 0 ) { + fprintf(stderr, "open_tuner %s for audio: %s\n", + demux_path, strerror(errno)); + return 1; + } + pesfilter.pid = aud_pid; + pesfilter.input = DMX_IN_FRONTEND; + pesfilter.output = DMX_OUT_TS_TAP; + pesfilter.pes_type = DMX_PES_AUDIO; + pesfilter.flags = DMX_IMMEDIATE_START; + if( ioctl(audio_fd, DMX_SET_PES_FILTER, &pesfilter) < 0 ) { + fprintf(stderr, "open_tuner DMX_SET_PES_FILTER for audio: %s\n", + strerror(errno)); + return 1; + } + } + +// Open transport stream for reading + if( (dvr_fd=::open(dvr_path, O_RDONLY)) < 0 ) { + fprintf(stderr, "open_tuner %s: %s\n", dvr_path, strerror(errno)); + return 1; + } + + return 0; +} + +void close_tuner() +{ + if( frontend_fd >= 0 ) close(frontend_fd); + if( audio_fd >= 0 ) close(audio_fd); + if( video_fd >= 0 ) close(video_fd); + if( dvr_fd >= 0 ) close(dvr_fd); +} + +int open_stream() +{ + if( zsrc == 0 && dvr_fd >= 0 ) { + int ret; + zsrc = new zmpeg3_t(dvr_fd, ret, ZIO_THREADED); + //zsrc = new zmpeg3_t(dvr_fd, ret); + zsrc->set_cpus(2); + if( ret ) { + fprintf(stderr,"mpeg3 open failed (%d)\n", ret); + return 1; + } + if( subchan >= 0 ) { + int nch = zsrc->dvb.channel_count(); + while( --nch >= 0 ) { + int mjr, mnr; + if( zsrc->dvb.get_channel(nch, mjr, mnr) ) continue; + if( mnr == subchan ) break; + } + if( nch >= 0 ) { + zsrc->dvb.vstream_number(nch, 0, vid); + zsrc->dvb.astream_number(nch, 0, aud, 0); + } + } + } + return 0; +} + +void close_stream() +{ + if( zsrc ) { delete zsrc; zsrc = 0; } +} + +int start_stream() +{ + if( !the_lck && frontend_fd >= 0 ) { + the_lck = new lck_thread(); + the_lck->Run(); + } + if( !the_vid && dvr_fd >= 0 ) { + the_vid = new vid_thread(); + the_vid->Run(); + } + if( !the_aud && dvr_fd >= 0 ) { + the_aud = new aud_thread(); + the_aud->Run(); + } + return 0; +} + +void stop_stream() +{ + if( the_lck ) { the_lck->Kill(); the_lck = 0; } + if( the_vid ) { the_vid->Kill(); the_vid = 0; } + if( the_aud ) { the_aud->Kill(); the_aud = 0; } +} + +double astart; + +double audio_time(int stream) +{ + double anow = zsrc->get_audio_time(stream); + if( astart < 0. ) astart = anow; + return anow - astart; +} + +void aud_thread:: +Proc() +{ + int audio_channels, sample_rate, more_data; + + audio_channels = zsrc->audio_channels(aud); + sample_rate = zsrc->sample_rate(aud); + alsa_open(audio_channels,sample_rate); + astart = -1.; + more_data = 1; + + while( done == 0 && more_data ) { + more_data = 0; + int ich; + int n = alsa_bfrsz(); + for( ich=0; ichread_audio(bfr, ich, n, aud) : + zsrc->reread_audio(bfr, ich, n, aud); + if( verbose ) + printf("read_audio(stream=%d,channel=%d) = %d\n", aud, ich, ret); + } + alsa_write(n); + //double atime = audio_time(aud); + //double ttime = the_time(); + //doule delay = atime - ttime; + //printf("delay = %f (%f-%f)\n",delay,atime,ttime); + //if( (delay-ahead) > 0. ) + // usleep((int)(delay*1000000.0/2.)); + more_data |= !zsrc->end_of_audio(aud); + } + + alsa_close(); + audio_done = 1; +} + +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() +{ + 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; } + 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, 0 /* 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 ) { + 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]; + 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; + short *bfrs[zpcm_channels]; + 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; ilength > 0) + printf("The key event's string is `%s'\n", event->string); + + printf("The name of this keysym is `%s'\n", + gdk_keyval_name(event->keyval)); + + switch (event->keyval) { + case GDK_Home: + printf("The Home key was pressed.\n"); + break; + case GDK_Up: + printf("The Up arrow key was pressed.\n"); + break; + default: + break; + } + + if( gdk_keyval_is_lower(event->keyval) ) { + printf("A non-uppercase key was pressed.\n"); + } + else if( gdk_keyval_is_upper(event->keyval) ) { + printf("An uppercase letter was pressed.\n"); + } +#endif + switch (event->keyval) { + case GDK_plus: + case GDK_equal: + nudge += 0.1; + printf("+nudge = %f\n",nudge); + break; + case GDK_minus: + case GDK_underscore: + nudge -= 0.1; + printf("-nudge = %f\n",nudge); + break; + case GDK_q: + printf("exit\n"); + dst_exit(widget,data); + break; + } + return TRUE; +} + + +double vstart; + +double video_time(int stream) +{ + double vnow = zsrc->get_video_time(stream); + if( vstart < 0. && vnow > 0. ) vstart = vnow; + vnow += nudge; + return vnow - vstart; +} + +void vid_thread:: +Proc() +{ + GtkWidget *window; + GtkWidget *panel_hbox; + GtkWidget *image; + GdkPixbuf *pbuf0, *pbuf1; + GdkImage *img0, *img1; + GdkVisual *visual; + float frame_rate, frame_delay; + unsigned char **rows, **row0, **row1, *cap, *cap0, *cap1; + int ret, row, frame, more_data; + int width, height, owidth, oheight; + const int frame_drop = 1; + int rheight = 1050; + int rwidth = 1680; + + frame_rate = zsrc->frame_rate(vid); + frame_delay = 2.0 / frame_rate; + height = zsrc->video_height(vid); + width = zsrc->video_width(vid); + //oheight = rheight-96; + //owidth = rwidth-64; + oheight = height; + owidth = width; + int fheight = rheight - 96; + int fwidth = rwidth - 64; + if( oheight > fheight || owidth > fwidth ) { + int mheight = (owidth * fheight) / fwidth; + int mwidth = (oheight * fwidth) / fheight; + if( mheight > fheight ) mheight = fheight; + if( mwidth > fwidth ) mwidth = fwidth; + oheight = mheight; + owidth = mwidth; + } + else if( oheight < 1050/2 && owidth < 1650/2 ) { + oheight = oheight * 2; + owidth = owidth * 2; + } + + visual = gdk_visual_get_system(); + /* toplevel window */ + window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_signal_connect(GTK_OBJECT(window),"destroy", + GTK_SIGNAL_FUNC(dst_exit),NULL); + gtk_signal_connect(GTK_OBJECT(window),"key_press_event", + GTK_SIGNAL_FUNC(key_press_cb),NULL); + gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_NONE); + /* try for shared image bfr, only seems to work with gtk_rgb */ + img0 = gdk_image_new(GDK_IMAGE_SHARED, visual, owidth, oheight); + pbuf0 = gdk_pixbuf_new_from_data((const guchar *)img0->mem, + GDK_COLORSPACE_RGB,RGBA,8,owidth,oheight,owidth*BPP,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,RGBA,8,owidth,oheight,owidth*BPP,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); + + + row0 = new unsigned char *[oheight]; + row1 = new unsigned char *[oheight]; + int cmdl = COLOR_MODEL; + for( row=0; row= frame_delay ) { + int nframes = (long)ceil(delay/frame_rate); + if( nframes > 2 ) nframes = 2; + dprintf(" d%d",nframes); + zsrc->drop_frames(nframes,vid); + } + } + delay = -delay; + if( delay > 0 ) { + dprintf(" D%5.3f",delay*1000.0); + int us = (int)(delay*1000000.0); + usleep(us); + } + ret = zsrc->read_frame(rows, 0, 0, width, height, + owidth, oheight, cmdl, vid); + //printf("%d %ld\n",frame,zsrc->vtrack[0]->demuxer->titles[0]->fs->current_byte); + //printf("%d %ld %ld %ld\n",frame,zsrc->vtrack[0]->demuxer->titles[0]->fs->current_byte, + // zsrc->vtrack[0]->demuxer->titles[0]->fs->buffer->file_pos, + // zsrc->vtrack[0]->demuxer->titles[0]->fs->buffer->file_pos - + // zsrc->vtrack[0]->demuxer->titles[0]->fs->current_byte); + if( verbose ) + printf("read_video(stream=%d, frame=%d) = %d\n", vid, frame, ret); + GdkGC *blk = image->style->black_gc; + gdk_draw_rgb_image(image->window,blk, 0,0,owidth,oheight, + GDK_RGB_DITHER_NONE,cap,owidth*BPP); +#if 0 +#if 0 + { static FILE *fp = 0; + int sz = owidth*oheight*BPP; + if( fp == 0 ) fp = fopen("/tmp/dat.raw","w"); + fwrite(cap,1,sz,fp); + } +#else + if( frame < 150 ) { static FILE *fp = 0; + int z, sz = owidth*oheight*BPP; + uint8_t zbfr[sz]; + if( fp == 0 ) fp = fopen("/tmp/dat.raw","r"); + fread(zbfr,1,sz,fp); + for( z=0; zend_of_video(vid); + ++frame; + } + else + gtk_main_iteration(); + } + video_done = 1; +} + +void stats() +{ + int has_audio = zsrc->has_audio(); + printf(" has_audio = %d\n", has_audio); + int total_astreams = zsrc->total_astreams(); + printf(" total_astreams = %d\n", total_astreams); + for( int astream=0; astreamaudio_channels(astream); + printf(" audio_channels = %d\n", audio_channels); + int sample_rate = zsrc->sample_rate(astream); + printf(" sample_rate = %d\n", sample_rate); + long audio_samples = zsrc->audio_samples(astream); + printf(" audio_samples = %ld\n", audio_samples); + } + printf("\n"); + int has_video = zsrc->has_video(); + printf(" has_video = %d\n", has_video); + int total_vstreams = zsrc->total_vstreams(); + printf(" total_vstreams = %d\n", total_vstreams); + for( int vstream=0; vstreamvideo_width(vstream); + printf(" video_width = %d\n", width); + int height = zsrc->video_height(vstream); + printf(" video_height = %d\n", height); + float frame_rate = zsrc->frame_rate(vstream); + printf(" frame_rate = %f\n", frame_rate); + long video_frames = zsrc->video_frames(vstream); + printf(" video_frames = %ld\n", video_frames); + int colormodel = zsrc->colormodel(vstream); + printf(" colormodel = %d\n", colormodel); + } + int channel_count = zsrc->dvb.channel_count(); + printf("\ndvb data: %d channels\n",channel_count); + for( int channel=0; channeldvb.get_channel(channel, major, minor); + zsrc->dvb.get_station_id(channel, &name[0]); + zsrc->dvb.total_astreams(channel, total_astreams); + zsrc->dvb.total_vstreams(channel, total_vstreams); + printf(" dvb channel %d.%d (%s) %d vstreams, %d astreams\n", + major, minor, name, total_vstreams, total_astreams); + for( int vstream=0; vstreamdvb.vstream_number(channel, vstream, stream); + printf(" video%-2d = %d\n",vstream,stream); + } + for(int astream=0; astreamdvb.astream_number(channel, astream, stream, &enc[0]); + printf(" audio%-2d = %d (%s)\n",astream,stream,&enc[0]); + } + } + printf("\n"); +} + +void sig_int(int n) +{ + done = 1; +} + +int ich[] = { /* June 14, 2009 */ + 7, // 7.1 (KMGH-DT) 1 vstreams, 1 astreams (eng) + // 7.27 (KZCO-SD) 1 vstreams, 1 astreams (spa) + 9, // 9.1 (KUSA-DT) 1 vstreams, 1 astreams (eng) + // 9.2 (WX-Plus) 1 vstreams, 1 astreams (eng) + // 9.3 (NBC Uni) 1 vstreams, 1 astreams (eng) + 13, // 12.1 (KBDI-DT) 1 vstreams, 1 astreams (eng) + // 12.2 (KBDI-DC) 1 vstreams, 1 astreams (eng) + // 12.3 (KBDI-WV) 1 vstreams, 1 astreams (eng) + 15, // 14.1 (KTFD-DT) 1 vstreams, 1 astreams (spa) + 19, // 20.1 (KTVD-DT) 1 vstreams, 1 astreams (eng) + 21, // 22.1 (KDVR DT) 1 vstreams, 2 astreams (eng) (spa) + 29, // 25.1 (KDEN-DT) 1 vstreams, 1 astreams (eng) + 32, // 31.1 (KDVR DT) 1 vstreams, 2 astreams (eng) (spa) + 34, // 2.1 (KWGN-DT) 1 vstreams, 2 astreams (eng) (eng) + 35, // 4.1 (KCNC-DT) 1 vstreams, 2 astreams (eng) (spa) + 38, // 38.1 (KPJR-1_) 1 vstreams, 1 astreams (eng) + // 38.2 (KPJR-2_) 1 vstreams, 1 astreams (eng) + // 38.3 (KPJR-3_) 1 vstreams, 1 astreams (eng) + // 38.4 (KPJR-4_) 1 vstreams, 1 astreams (eng) + // 38.5 (KPJR-5_) 1 vstreams, 1 astreams (eng) + 40, // 41.1 (KRMT 41) 1 vstreams, 1 astreams (eng) + 43, // 59.1 (ION____) 1 vstreams, 1 astreams (eng) + // 59.2 (qubo___) 1 vstreams, 2 astreams (eng) (eng) + // 59.3 (IONLife) 1 vstreams, 1 astreams (eng) + // 59.4 (Worship) 1 vstreams, 1 astreams (eng) + 46, // 53.1 (KWHD-DT) 1 vstreams, 1 astreams (eng) + 51, // 50.1 (Univisi) 1 vstreams, 1 astreams (spa) +}; + +int main(int ac, char **av) +{ + setbuf(stdout,NULL); + setbuf(stderr,NULL); + if( ac < 2 ) { + printf("channel ordinal required\n"); + return 1; + } + int ch_ord = atoi(av[1]); + if( ch_ord >= 0 ) { + gtk_set_locale(); + gtk_init(&ac, &av); + audio_done = 0; + video_done = 0; + reset(); + if( ac == 3 ) { + subchan = atoi(av[2]); + } + else if( ac == 4 ) { + vid = atoi(av[2]); + aud = atoi(av[3]); + } + if( !open_tuner(0,ch_ord,0,0) ) { + if( !open_stream() ) { + stats(); + zsrc->seek_byte(0); + // zsrc->show_subtitle(0); + start_stream(); + while( !done ) { + usleep(100000); + if( audio_done && video_done) break; + } + stop_stream(); + close_stream(); + } + } + close_tuner(); + } + else { + for( int ch=-ch_ord>2? -ch_ord : 2; ch<78; ++ch ) { + printf("\r %2d?\r",ch); + reset(); + /* extra open/close clears previous bfr data */ + if( !open_tuner(0,ch,0,0) ) close_tuner(); + usleep(100000); + if( !open_tuner(0,ch,0,0) && !open_stream() ) { + int nch = zsrc->dvb.channel_count(); + if( nch > 0 ) { + for( int ich=0, n=0; ichdvb.get_channel(ich, mjr, mnr); + int astrs, vstrs, stream; char name[8], enc[4]; + zsrc->dvb.get_station_id(ich, &name[0]); + zsrc->dvb.total_astreams(ich, astrs); + zsrc->dvb.total_vstreams(ich, vstrs); + if( n++ ) printf(" "); else printf(" %2d: ", ch); + printf(" %2d.%-2d (%s) %d vstreams, %d astreams", + mjr, mnr, name, vstrs, astrs); + for( int j=0; jdvb.astream_number(ich, j, stream, &enc[0]); + printf(" (%s)",&enc[0]); + } + printf("\n"); + } + } + close_stream(); + } + close_tuner(); + } + } + return 0; +} +