13 #include <gdk/gdkkeysyms.h>
14 #include <alsa/asoundlib.h>
15 #include <linux/dvb/dmx.h>
16 #include <linux/dvb/frontend.h>
18 /* c++ `pkg-config --cflags --libs gtk+-2.0` dmux.C thread.C ./x86_64/libzmpeg3.a -lpthread -lasound -lm */
20 #include "libzmpeg3.h"
25 int open_tuner(int dev_no,int chan,int vid_pid,int aud_pid);
27 double audio_time(int stream);
29 void alsa_open(int chs,int rate);
30 short *alsa_bfr(int ch);
32 int alsa_recovery(int ret);
33 int alsa_write(int len);
34 void dst_exit(GtkWidget *widget, gpointer data);
35 gint key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer data);
36 double video_time(int stream);
39 int main(int ac,char **av);
41 /* alpha currently is broken in gdk */
42 /* would render faster if alpha worked correctly */
47 #define COLOR_MODEL zmpeg3_t::cmdl_RGBA8888
50 #define COLOR_MODEL zmpeg3_t::cmdl_RGB888
54 double nudge = .5; // 3.5;
55 const double ahead = .5;
59 #define dprintf(s...) do{}while(0)
61 #define dprintf(s...) printf(s)
65 #define NETTUNE_CABLE 2
67 static unsigned long ntsc_dvb[ ] = {
68 0, 0, 57, 63, 69, 79, 85, 177, 183, 189 ,
69 195, 201, 207, 213, 473, 479, 485, 491, 497, 503 ,
70 509, 515, 521, 527, 533, 539, 545, 551, 557, 563 ,
71 569, 575, 581, 587, 593, 599, 605, 611, 617, 623 ,
72 629, 635, 641, 647, 653, 659, 665, 671, 677, 683 ,
73 689, 695, 701, 707, 713, 719, 725, 731, 737, 743 ,
74 749, 755, 761, 767, 773, 779, 785, 791, 797, 803 ,
75 809, 815, 821, 827, 833, 839, 845, 851, 857, 863 ,
76 869, 875, 881, 887, 893, 899, 905, 911, 917, 923 ,
77 929, 935, 941, 947, 953, 959, 965, 971, 977, 983 ,
78 989, 995, 1001, 1007, 1013, 1019, 1025, 1031, 1037, 1043
81 static unsigned long catv_dvb[] = {
82 0, 0, 57, 63, 69, 79, 85, 177, 183, 189,
83 195, 201, 207, 213, 123, 129, 135, 141, 147, 153,
84 159, 165, 171, 219, 225, 231, 237, 243, 249, 255,
85 261, 267, 273, 279, 285, 291, 297, 303, 309, 315,
86 321, 327, 333, 339, 345, 351, 357, 363, 369, 375,
87 381, 387, 393, 399, 405, 411, 417, 423, 429, 435,
88 441, 447, 453, 459, 465, 471, 477, 483, 489, 495,
89 501, 507, 513, 519, 525, 531, 537, 543, 549, 555,
90 561, 567, 573, 579, 585, 591, 597, 603, 609, 615,
91 621, 627, 633, 639, 645, 93, 99, 105, 111, 117,
92 651, 657, 663, 669, 675, 681, 687, 693, 699, 705,
93 711, 717, 723, 729, 735, 741, 747, 753, 759, 765,
94 771, 777, 783, 789, 795, 781, 807, 813, 819, 825,
95 831, 837, 843, 849, 855, 861, 867, 873, 879, 885,
96 891, 897, 903, 909, 915, 921, 927, 933, 939, 945,
97 951, 957, 963, 969, 975, 981, 987, 993, 999
113 class vid_thread : public Thread
118 class aud_thread : public Thread
123 class lck_thread : public Thread
131 uint16_t snr, signal;
132 uint32_t ber, uncorrected_blocks;
134 bzero(&status, sizeof(status));
135 ioctl(frontend_fd, FE_READ_STATUS, &status);
137 ioctl(frontend_fd, FE_READ_SIGNAL_STRENGTH, &signal);
138 ioctl(frontend_fd, FE_READ_SNR, &snr);
139 ioctl(frontend_fd, FE_READ_BER, &ber);
140 ioctl(frontend_fd, FE_READ_UNCORRECTED_BLOCKS, &uncorrected_blocks);
141 printf("lck:: %02x | signal %04x | snr %04x | ber %08x | unc %08x | ",
142 status, signal, snr, ber, uncorrected_blocks);
144 has_lock = status & FE_HAS_LOCK ? 1 : 0;
146 printf( has_lock ? "lock\n" : "lost\n" );
147 if( prev_lock != has_lock ) {
148 printf(" %s\n",has_lock ? "signal locked" : "signal lost");
149 prev_lock = has_lock;
157 dprintf("lck_thread::Proc()\n");
170 gettimeofday(&tv,NULL);
171 time = tv.tv_sec + tv.tv_usec/1000000.0;
172 if( tstart < 0. ) tstart = time;
173 return time - tstart;
192 int open_tuner(int dev_no,int chan,int vid_pid,int aud_pid)
194 char frontend_path[512];
195 char demux_path[512];
197 //dvr_fd = open("/tmp/dat7",O_RDONLY);
198 //return dvr_fd >= 0 ? 0 : 1;
200 sprintf(frontend_path, "/dev/dvb/adapter%d/frontend%d", dev_no, 0);
201 sprintf(demux_path, "/dev/dvb/adapter%d/demux%d", dev_no, 0);
202 sprintf(dvr_path, "/dev/dvb/adapter%d/dvr%d", dev_no, 0);
203 if( (frontend_fd=::open(frontend_path, O_RDWR)) < 0 ) {
204 fprintf(stderr, "open_tuner %s: %s\n", frontend_path, strerror(errno));
208 struct dvb_frontend_parameters frontend_param;
209 bzero(&frontend_param, sizeof(frontend_param));
213 int table = NETTUNE_AIR;
217 frontend_param.frequency = ntsc_dvb[index] * 1000000;
218 frontend_param.u.vsb.modulation = VSB_8;
221 frontend_param.frequency = catv_dvb[index] * 1000000;
222 frontend_param.u.vsb.modulation = QAM_AUTO;
226 if( ioctl(frontend_fd, FE_SET_FRONTEND, &frontend_param) < 0 ) {
227 fprintf(stderr, "open_tuner FE_SET_FRONTEND frequency=%d: %s",
228 frontend_param.frequency, strerror(errno));
233 while( !do_status() && --retry>=0 ) sleep(1);
236 fprintf(stderr, "open_tuner: no signal on channel %d\n",chan);
240 if( (video_fd=::open(demux_path, O_RDWR)) < 0 ) {
241 fprintf(stderr, "open_tuner %s for video: %s\n",
242 demux_path, strerror(errno));
246 // Setting exactly one PES filter to 0x2000 dumps the entire
248 struct dmx_pes_filter_params pesfilter;
249 if( !vid_pid && !aud_pid ) {
250 pesfilter.pid = 0x2000;
251 pesfilter.input = DMX_IN_FRONTEND;
252 pesfilter.output = DMX_OUT_TS_TAP;
253 pesfilter.pes_type = DMX_PES_OTHER;
254 pesfilter.flags = DMX_IMMEDIATE_START;
255 if( ioctl(video_fd, DMX_SET_PES_FILTER, &pesfilter) < 0 ) {
256 fprintf(stderr, "open_tuner DMX_SET_PES_FILTER for raw: %s\n",
264 pesfilter.pid = vid_pid;
265 pesfilter.input = DMX_IN_FRONTEND;
266 pesfilter.output = DMX_OUT_TS_TAP;
267 pesfilter.pes_type = DMX_PES_VIDEO;
268 pesfilter.flags = DMX_IMMEDIATE_START;
269 if( ioctl(video_fd, DMX_SET_PES_FILTER, &pesfilter) < 0 ) {
270 fprintf(stderr, "open_tuner DMX_SET_PES_FILTER for video: %s\n",
277 if( (audio_fd=::open(demux_path,O_RDWR)) < 0 ) {
278 fprintf(stderr, "open_tuner %s for audio: %s\n",
279 demux_path, strerror(errno));
282 pesfilter.pid = aud_pid;
283 pesfilter.input = DMX_IN_FRONTEND;
284 pesfilter.output = DMX_OUT_TS_TAP;
285 pesfilter.pes_type = DMX_PES_AUDIO;
286 pesfilter.flags = DMX_IMMEDIATE_START;
287 if( ioctl(audio_fd, DMX_SET_PES_FILTER, &pesfilter) < 0 ) {
288 fprintf(stderr, "open_tuner DMX_SET_PES_FILTER for audio: %s\n",
294 // Open transport stream for reading
295 if( (dvr_fd=::open(dvr_path, O_RDONLY)) < 0 ) {
296 fprintf(stderr, "open_tuner %s: %s\n", dvr_path, strerror(errno));
305 if( frontend_fd >= 0 ) close(frontend_fd);
306 if( audio_fd >= 0 ) close(audio_fd);
307 if( video_fd >= 0 ) close(video_fd);
308 if( dvr_fd >= 0 ) close(dvr_fd);
313 if( zsrc == 0 && dvr_fd >= 0 ) {
315 zsrc = new zmpeg3_t(dvr_fd, ret, ZIO_THREADED);
316 //zsrc = new zmpeg3_t(dvr_fd, ret);
319 fprintf(stderr,"mpeg3 open failed (%d)\n", ret);
323 int nch = zsrc->dvb.channel_count();
324 while( --nch >= 0 ) {
326 if( zsrc->dvb.get_channel(nch, mjr, mnr) ) continue;
327 if( mnr == subchan ) break;
330 zsrc->dvb.vstream_number(nch, 0, vid);
331 zsrc->dvb.astream_number(nch, 0, aud, 0);
340 if( zsrc ) { delete zsrc; zsrc = 0; }
345 if( !the_lck && frontend_fd >= 0 ) {
346 the_lck = new lck_thread();
349 if( !the_vid && dvr_fd >= 0 ) {
350 the_vid = new vid_thread();
353 if( !the_aud && dvr_fd >= 0 ) {
354 the_aud = new aud_thread();
362 if( the_lck ) { the_lck->Kill(); the_lck = 0; }
363 if( the_vid ) { the_vid->Kill(); the_vid = 0; }
364 if( the_aud ) { the_aud->Kill(); the_aud = 0; }
369 double audio_time(int stream)
371 double anow = zsrc->get_audio_time(stream);
372 if( astart < 0. ) astart = anow;
373 return anow - astart;
379 int audio_channels, sample_rate, more_data;
381 audio_channels = zsrc->audio_channels(aud);
382 sample_rate = zsrc->sample_rate(aud);
383 alsa_open(audio_channels,sample_rate);
387 while( done == 0 && more_data ) {
390 int n = alsa_bfrsz();
391 for( ich=0; ich<audio_channels; ++ich ) {
392 short *bfr = alsa_bfr(ich);
394 zsrc->read_audio(bfr, ich, n, aud) :
395 zsrc->reread_audio(bfr, ich, n, aud);
397 printf("read_audio(stream=%d,channel=%d) = %d\n", aud, ich, ret);
400 //double atime = audio_time(aud);
401 //double ttime = the_time();
402 //doule delay = atime - ttime;
403 //printf("delay = %f (%f-%f)\n",delay,atime,ttime);
404 //if( (delay-ahead) > 0. )
405 // usleep((int)(delay*1000000.0/2.));
406 more_data |= !zsrc->end_of_audio(aud);
414 snd_pcm_uframes_t zpcm_ufrm_size;
415 snd_pcm_sframes_t zpcm_sbfr_size;
416 snd_pcm_sframes_t zpcm_sper_size;
417 unsigned int zpcm_rate;
418 static const char *zpcm_device = "plughw:0,0";
419 static unsigned int zpcm_bfr_time_us = 500000;
420 static unsigned int zpcm_per_time_us = 200000;
421 static snd_pcm_channel_area_t *zpcm_areas = 0;
422 static int zpcm_channels = 0;
423 static short **zpcm_buffers = 0;
424 static short *zpcm_samples = 0;
428 if( zpcm_buffers != 0 ) { delete [] zpcm_buffers; zpcm_buffers = 0; }
429 if( zpcm_areas != 0 ) { delete [] zpcm_areas; zpcm_areas = 0; }
430 if( zpcm_samples != 0 ) { delete [] zpcm_samples; zpcm_samples = 0; }
431 if( zpcm != 0 ) { snd_pcm_close(zpcm); zpcm = 0; }
434 void alsa_open(int chs,int rate)
436 int ich, bits, byts, dir, ret;
437 snd_pcm_format_t fmt = SND_PCM_FORMAT_S16;
438 snd_pcm_hw_params_t *phw;
439 snd_pcm_sw_params_t *psw;
440 snd_pcm_hw_params_alloca(&phw);
441 snd_pcm_sw_params_alloca(&psw);
444 ret = snd_pcm_open(&zpcm, zpcm_device,
445 SND_PCM_STREAM_PLAYBACK, 0 /* SND_PCM_NONBLOCK */);
447 ret = snd_pcm_hw_params_any(zpcm, phw);
449 ret = snd_pcm_hw_params_set_rate_resample(zpcm, phw, 1);
451 ret = snd_pcm_hw_params_set_access(zpcm, phw,
452 SND_PCM_ACCESS_RW_NONINTERLEAVED);
454 ret = snd_pcm_hw_params_set_format(zpcm, phw, fmt);
457 ret = snd_pcm_hw_params_set_channels(zpcm, phw, chs);
461 ret = snd_pcm_hw_params_set_rate_near(zpcm, phw, &zpcm_rate, 0);
462 if( (int)zpcm_rate != rate )
463 printf("nearest audio_rate for %d is %u\n",rate,zpcm_rate);
466 ret = snd_pcm_hw_params_set_buffer_time_near(zpcm, phw,
467 &zpcm_bfr_time_us, &dir);
469 ret = snd_pcm_hw_params_get_buffer_size(phw, &zpcm_ufrm_size);
471 zpcm_sbfr_size = zpcm_ufrm_size;
472 ret = snd_pcm_hw_params_set_period_time_near(zpcm, phw,
473 &zpcm_per_time_us, &dir);
476 ret = snd_pcm_hw_params_get_period_size(phw, &zpcm_ufrm_size, &dir);
478 zpcm_sper_size = zpcm_ufrm_size;
479 ret = snd_pcm_hw_params(zpcm, phw);
482 ret = snd_pcm_sw_params_current(zpcm, psw);
484 ret = snd_pcm_sw_params_set_start_threshold(zpcm, psw,
485 (zpcm_sbfr_size / zpcm_sper_size) * zpcm_sper_size);
487 ret = snd_pcm_sw_params_set_avail_min(zpcm, psw, zpcm_sper_size);
489 ret = snd_pcm_sw_params(zpcm, psw);
490 /* snd_pcm_dump(zpcm, stdout); */
493 zpcm_areas = new snd_pcm_channel_area_t[chs];
494 byts = snd_pcm_format_physical_width(fmt) / 8;
495 zpcm_samples = new short[zpcm_sper_size * chs * byts/2];
496 zpcm_buffers = new short *[chs];
498 for( ich = 0; ich < chs; ++ich ) {
499 zpcm_areas[ich].addr = zpcm_samples;
500 zpcm_areas[ich].first = ich * zpcm_sper_size * bits;
501 zpcm_areas[ich].step = bits;
502 zpcm_buffers[ich] = zpcm_samples + ich*zpcm_sper_size;
506 fprintf(stderr,"alsa sample buffer allocation failure.\n");
512 printf("audio error: %s\n", snd_strerror(ret));
517 short *alsa_bfr(int ch)
519 return zpcm_buffers[ch];
524 return zpcm_sper_size;
527 int alsa_recovery(int ret)
529 printf("alsa recovery\n");
532 /* wait until the suspend flag is released, then fall through */
533 while( (ret=snd_pcm_resume(zpcm)) == -EAGAIN ) usleep(100000);
535 ret = snd_pcm_prepare(zpcm);
537 printf("underrun, prepare failed: %s\n", snd_strerror(ret));
540 printf("unhandled error: %s\n",snd_strerror(ret));
546 int alsa_write(int len)
549 short *bfrs[zpcm_channels];
551 for( i=0; i<zpcm_channels; ++i ) bfrs[i] = zpcm_buffers[i];
554 ret = snd_pcm_writen(zpcm,(void **)bfrs, len);
555 if( ret == -EAGAIN ) continue;
560 for( i=0; i<zpcm_channels; ++i ) bfrs[i] += ret;
563 return ret < 0 ? ret : 0;
566 void dst_exit(GtkWidget *widget, gpointer data)
572 key_press_cb(GtkWidget* widget, GdkEventKey* event, gpointer data)
575 if (event->length > 0)
576 printf("The key event's string is `%s'\n", event->string);
578 printf("The name of this keysym is `%s'\n",
579 gdk_keyval_name(event->keyval));
581 switch (event->keyval) {
583 printf("The Home key was pressed.\n");
586 printf("The Up arrow key was pressed.\n");
592 if( gdk_keyval_is_lower(event->keyval) ) {
593 printf("A non-uppercase key was pressed.\n");
595 else if( gdk_keyval_is_upper(event->keyval) ) {
596 printf("An uppercase letter was pressed.\n");
599 switch (event->keyval) {
603 printf("+nudge = %f\n",nudge);
608 printf("-nudge = %f\n",nudge);
612 dst_exit(widget,data);
621 double video_time(int stream)
623 double vnow = zsrc->get_video_time(stream);
624 if( vstart < 0. && vnow > 0. ) vstart = vnow;
626 return vnow - vstart;
633 GtkWidget *panel_hbox;
635 GdkPixbuf *pbuf0, *pbuf1;
636 GdkImage *img0, *img1;
638 float frame_rate, frame_delay;
639 unsigned char **rows, **row0, **row1, *cap, *cap0, *cap1;
640 int ret, row, frame, more_data;
641 int width, height, owidth, oheight;
642 const int frame_drop = 1;
646 frame_rate = zsrc->frame_rate(vid);
647 frame_delay = 2.0 / frame_rate;
648 height = zsrc->video_height(vid);
649 width = zsrc->video_width(vid);
650 //oheight = rheight-96;
651 //owidth = rwidth-64;
654 int fheight = rheight - 96;
655 int fwidth = rwidth - 64;
656 if( oheight > fheight || owidth > fwidth ) {
657 int mheight = (owidth * fheight) / fwidth;
658 int mwidth = (oheight * fwidth) / fheight;
659 if( mheight > fheight ) mheight = fheight;
660 if( mwidth > fwidth ) mwidth = fwidth;
664 else if( oheight < 1050/2 && owidth < 1650/2 ) {
665 oheight = oheight * 2;
669 visual = gdk_visual_get_system();
670 /* toplevel window */
671 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
672 gtk_signal_connect(GTK_OBJECT(window),"destroy",
673 GTK_SIGNAL_FUNC(dst_exit),NULL);
674 gtk_signal_connect(GTK_OBJECT(window),"key_press_event",
675 GTK_SIGNAL_FUNC(key_press_cb),NULL);
676 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_NONE);
677 /* try for shared image bfr, only seems to work with gtk_rgb */
678 img0 = gdk_image_new(GDK_IMAGE_SHARED, visual, owidth, oheight);
679 pbuf0 = gdk_pixbuf_new_from_data((const guchar *)img0->mem,
680 GDK_COLORSPACE_RGB,RGBA,8,owidth,oheight,owidth*BPP,NULL,NULL);
681 cap0 = gdk_pixbuf_get_pixels(pbuf0);
682 image = gtk_image_new_from_pixbuf(pbuf0);
683 /* double buffered */
684 img1 = gdk_image_new(GDK_IMAGE_SHARED, visual, owidth, oheight);
685 pbuf1 = gdk_pixbuf_new_from_data((const guchar *)img1->mem,
686 GDK_COLORSPACE_RGB,RGBA,8,owidth,oheight,owidth*BPP,NULL,NULL);
687 cap1 = gdk_pixbuf_get_pixels(pbuf1);
689 panel_hbox = gtk_hbox_new(FALSE,0);
690 gtk_container_add(GTK_CONTAINER(window), panel_hbox);
691 /* pack image into panel */
692 gtk_box_pack_start(GTK_BOX(panel_hbox), image, TRUE, TRUE, 0);
695 row0 = new unsigned char *[oheight];
696 row1 = new unsigned char *[oheight];
697 int cmdl = COLOR_MODEL;
698 for( row=0; row<oheight; ++row ) {
699 row0[row] = cap0 + row*owidth*BPP;
700 row1[row] = cap1 + row*owidth*BPP;
703 gtk_widget_show_all(window);
710 while( done == 0 && more_data ) {
711 if( !gtk_events_pending() ) {
713 double delay = the_time() - video_time(vid);
715 if( delay >= frame_delay ) {
716 int nframes = (long)ceil(delay/frame_rate);
717 if( nframes > 2 ) nframes = 2;
718 dprintf(" d%d",nframes);
719 zsrc->drop_frames(nframes,vid);
724 dprintf(" D%5.3f",delay*1000.0);
725 int us = (int)(delay*1000000.0);
728 ret = zsrc->read_frame(rows, 0, 0, width, height,
729 owidth, oheight, cmdl, vid);
730 //printf("%d %ld\n",frame,zsrc->vtrack[0]->demuxer->titles[0]->fs->current_byte);
731 //printf("%d %ld %ld %ld\n",frame,zsrc->vtrack[0]->demuxer->titles[0]->fs->current_byte,
732 // zsrc->vtrack[0]->demuxer->titles[0]->fs->buffer->file_pos,
733 // zsrc->vtrack[0]->demuxer->titles[0]->fs->buffer->file_pos -
734 // zsrc->vtrack[0]->demuxer->titles[0]->fs->current_byte);
736 printf("read_video(stream=%d, frame=%d) = %d\n", vid, frame, ret);
737 GdkGC *blk = image->style->black_gc;
738 gdk_draw_rgb_image(image->window,blk, 0,0,owidth,oheight,
739 GDK_RGB_DITHER_NONE,cap,owidth*BPP);
742 { static FILE *fp = 0;
743 int sz = owidth*oheight*BPP;
744 if( fp == 0 ) fp = fopen("/tmp/dat.raw","w");
748 if( frame < 150 ) { static FILE *fp = 0;
749 int z, sz = owidth*oheight*BPP;
751 if( fp == 0 ) fp = fopen("/tmp/dat.raw","r");
753 for( z=0; z<sz && abs(zbfr[z]-cap[z])<=1; ++z );
754 //for( z=0; z<sz && zbfr[z]==cap[z]; ++z );
756 printf("bug %d\n",z);
760 *(unsigned long *)&cap ^= ((unsigned long)cap0 ^ (unsigned long)cap1);
761 *(unsigned long *)&rows ^= ((unsigned long)row0 ^ (unsigned long)row1);
762 more_data |= !zsrc->end_of_video(vid);
766 gtk_main_iteration();
773 int has_audio = zsrc->has_audio();
774 printf(" has_audio = %d\n", has_audio);
775 int total_astreams = zsrc->total_astreams();
776 printf(" total_astreams = %d\n", total_astreams);
777 for( int astream=0; astream<total_astreams; ++astream ) {
778 int audio_channels = zsrc->audio_channels(astream);
779 printf(" audio_channels = %d\n", audio_channels);
780 int sample_rate = zsrc->sample_rate(astream);
781 printf(" sample_rate = %d\n", sample_rate);
782 long audio_samples = zsrc->audio_samples(astream);
783 printf(" audio_samples = %ld\n", audio_samples);
786 int has_video = zsrc->has_video();
787 printf(" has_video = %d\n", has_video);
788 int total_vstreams = zsrc->total_vstreams();
789 printf(" total_vstreams = %d\n", total_vstreams);
790 for( int vstream=0; vstream<total_vstreams; ++vstream ) {
791 int width = zsrc->video_width(vstream);
792 printf(" video_width = %d\n", width);
793 int height = zsrc->video_height(vstream);
794 printf(" video_height = %d\n", height);
795 float frame_rate = zsrc->frame_rate(vstream);
796 printf(" frame_rate = %f\n", frame_rate);
797 long video_frames = zsrc->video_frames(vstream);
798 printf(" video_frames = %ld\n", video_frames);
799 int colormodel = zsrc->colormodel(vstream);
800 printf(" colormodel = %d\n", colormodel);
802 int channel_count = zsrc->dvb.channel_count();
803 printf("\ndvb data: %d channels\n",channel_count);
804 for( int channel=0; channel<channel_count; ++channel ) {
805 int major, minor, stream; char name[8], enc[4];
806 zsrc->dvb.get_channel(channel, major, minor);
807 zsrc->dvb.get_station_id(channel, &name[0]);
808 zsrc->dvb.total_astreams(channel, total_astreams);
809 zsrc->dvb.total_vstreams(channel, total_vstreams);
810 printf(" dvb channel %d.%d (%s) %d vstreams, %d astreams\n",
811 major, minor, name, total_vstreams, total_astreams);
812 for( int vstream=0; vstream<total_vstreams; ++vstream ) {
813 zsrc->dvb.vstream_number(channel, vstream, stream);
814 printf(" video%-2d = %d\n",vstream,stream);
816 for(int astream=0; astream<total_astreams; ++astream ) {
817 zsrc->dvb.astream_number(channel, astream, stream, &enc[0]);
818 printf(" audio%-2d = %d (%s)\n",astream,stream,&enc[0]);
829 int ich[] = { /* June 14, 2009 */
830 7, // 7.1 (KMGH-DT) 1 vstreams, 1 astreams (eng)
831 // 7.27 (KZCO-SD) 1 vstreams, 1 astreams (spa)
832 9, // 9.1 (KUSA-DT) 1 vstreams, 1 astreams (eng)
833 // 9.2 (WX-Plus) 1 vstreams, 1 astreams (eng)
834 // 9.3 (NBC Uni) 1 vstreams, 1 astreams (eng)
835 13, // 12.1 (KBDI-DT) 1 vstreams, 1 astreams (eng)
836 // 12.2 (KBDI-DC) 1 vstreams, 1 astreams (eng)
837 // 12.3 (KBDI-WV) 1 vstreams, 1 astreams (eng)
838 15, // 14.1 (KTFD-DT) 1 vstreams, 1 astreams (spa)
839 19, // 20.1 (KTVD-DT) 1 vstreams, 1 astreams (eng)
840 21, // 22.1 (KDVR DT) 1 vstreams, 2 astreams (eng) (spa)
841 29, // 25.1 (KDEN-DT) 1 vstreams, 1 astreams (eng)
842 32, // 31.1 (KDVR DT) 1 vstreams, 2 astreams (eng) (spa)
843 34, // 2.1 (KWGN-DT) 1 vstreams, 2 astreams (eng) (eng)
844 35, // 4.1 (KCNC-DT) 1 vstreams, 2 astreams (eng) (spa)
845 38, // 38.1 (KPJR-1_) 1 vstreams, 1 astreams (eng)
846 // 38.2 (KPJR-2_) 1 vstreams, 1 astreams (eng)
847 // 38.3 (KPJR-3_) 1 vstreams, 1 astreams (eng)
848 // 38.4 (KPJR-4_) 1 vstreams, 1 astreams (eng)
849 // 38.5 (KPJR-5_) 1 vstreams, 1 astreams (eng)
850 40, // 41.1 (KRMT 41) 1 vstreams, 1 astreams (eng)
851 43, // 59.1 (ION____) 1 vstreams, 1 astreams (eng)
852 // 59.2 (qubo___) 1 vstreams, 2 astreams (eng) (eng)
853 // 59.3 (IONLife) 1 vstreams, 1 astreams (eng)
854 // 59.4 (Worship) 1 vstreams, 1 astreams (eng)
855 46, // 53.1 (KWHD-DT) 1 vstreams, 1 astreams (eng)
856 51, // 50.1 (Univisi) 1 vstreams, 1 astreams (spa)
859 int main(int ac, char **av)
864 printf("channel ordinal required\n");
867 int ch_ord = atoi(av[1]);
875 subchan = atoi(av[2]);
881 if( !open_tuner(0,ch_ord,0,0) ) {
882 if( !open_stream() ) {
885 // zsrc->show_subtitle(0);
889 if( audio_done && video_done) break;
898 for( int ch=-ch_ord>2? -ch_ord : 2; ch<78; ++ch ) {
899 printf("\r %2d?\r",ch);
901 /* extra open/close clears previous bfr data */
902 if( !open_tuner(0,ch,0,0) ) close_tuner();
904 if( !open_tuner(0,ch,0,0) && !open_stream() ) {
905 int nch = zsrc->dvb.channel_count();
907 for( int ich=0, n=0; ich<nch; ++ich ) {
909 zsrc->dvb.get_channel(ich, mjr, mnr);
910 int astrs, vstrs, stream; char name[8], enc[4];
911 zsrc->dvb.get_station_id(ich, &name[0]);
912 zsrc->dvb.total_astreams(ich, astrs);
913 zsrc->dvb.total_vstreams(ich, vstrs);
914 if( n++ ) printf(" "); else printf(" %2d: ", ch);
915 printf(" %2d.%-2d (%s) %d vstreams, %d astreams",
916 mjr, mnr, name, vstrs, astrs);
917 for( int j=0; j<astrs; ++j ) {
918 zsrc->dvb.astream_number(ich, j, stream, &enc[0]);
919 printf(" (%s)",&enc[0]);