usb_direct fix for rev2 shuttle, playbackengine locks again, viewer cursor fix
[goodguy/cinelerra.git] / cinelerra-5.1 / libzmpeg3 / y.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <alsa/asoundlib.h>
5 #include <sys/time.h>
6 #include <gtk/gtk.h>
7 #include <gdk/gdk.h>
8
9 const double nudge = 3.5;
10 const double ahead = .5;
11
12 #ifdef __cplusplus
13 #include "libzmpeg3.h"
14 #else
15 #include "../libmpeg3/libmpeg3.h"
16 #define zmpeg3_t mpeg3_t
17 #endif
18
19 zmpeg3_t *ysrc;
20
21 /* alpha currently is broken in gdk */
22 /*   would render faster if alpha worked correctly */
23 #define RGBA FALSE
24
25 #if RGBA
26 #define BPP 4
27 #ifdef __cplusplus
28 #define COLOR_MODEL zmpeg3_t::cmdl_RGBA8888
29 #else
30 #define COLOR_MODEL MPEG3_RGBA8888
31 #endif
32
33 #else
34 #define BPP 3
35 #ifdef __cplusplus
36 #define COLOR_MODEL zmpeg3_t::cmdl_RGB888
37 #else
38 #define COLOR_MODEL MPEG3_RGB888
39 #endif
40 #endif
41
42
43 #define AUDIO
44 //#define VIDEO
45 static int verbose = 0;
46
47 /* c++ `pkg-config --cflags --libs gtk+-2.0` y.C ./x86_64/libzmpeg3.a -lpthread -lasound -lm */
48
49 #ifdef AUDIO
50 snd_pcm_t *zpcm = 0;
51 snd_pcm_uframes_t zpcm_ufrm_size = 0;
52 snd_pcm_sframes_t zpcm_sbfr_size = 0;
53 snd_pcm_sframes_t zpcm_sper_size = 0;
54 snd_pcm_sframes_t zpcm_total_samples = 0;
55 double zpcm_play_time = 0.;
56 pthread_mutex_t zpcm_lock;
57 unsigned int zpcm_rate = 0;
58 static const char *zpcm_device = "plughw:0,0";
59 static unsigned int zpcm_bfr_time_us = 500000; 
60 static unsigned int zpcm_per_time_us = 200000;
61 static snd_pcm_channel_area_t *zpcm_areas = 0;
62 static int zpcm_channels = 0;
63 static short **zpcm_buffers = 0;
64 static short *zpcm_samples = 0;
65
66 void alsa_close()
67 {
68 #ifdef __cplusplus
69   if( zpcm_buffers != 0 ) { delete [] zpcm_buffers; zpcm_buffers = 0; }
70   if( zpcm_areas != 0 ) { delete [] zpcm_areas; zpcm_areas = 0; }
71   if( zpcm_samples != 0 ) { delete [] zpcm_samples; zpcm_samples = 0; }
72 #else
73   if( zpcm_buffers != 0 ) { free(zpcm_buffers); zpcm_buffers = 0; }
74   if( zpcm_areas != 0 ) { free(zpcm_areas); zpcm_areas = 0; }
75   if( zpcm_samples != 0 ) { free(zpcm_samples); zpcm_samples = 0; }
76 #endif
77   if( zpcm != 0 ) { snd_pcm_close(zpcm);  zpcm = 0; }
78   pthread_mutex_destroy(&zpcm_lock);
79 }
80
81 void alsa_open(int chs,int rate)
82 {
83   int ich, bits, byts, dir, ret;
84   pthread_mutex_init(&zpcm_lock,0);
85   snd_pcm_format_t fmt = SND_PCM_FORMAT_S16;
86   snd_pcm_hw_params_t *phw;
87   snd_pcm_sw_params_t *psw;
88   snd_pcm_hw_params_alloca(&phw);
89   snd_pcm_sw_params_alloca(&psw);
90
91   zpcm = 0;
92   zpcm_total_samples = 0;
93   zpcm_play_time = 0.;
94   ret = snd_pcm_open(&zpcm, zpcm_device,
95      SND_PCM_STREAM_PLAYBACK, 0 /* SND_PCM_NONBLOCK */);
96   if( ret >= 0 )
97     ret = snd_pcm_hw_params_any(zpcm, phw);
98   if( ret >= 0 )
99     ret = snd_pcm_hw_params_set_rate_resample(zpcm, phw, 1);
100   if( ret >= 0 )
101     ret = snd_pcm_hw_params_set_access(zpcm, phw,
102       SND_PCM_ACCESS_RW_NONINTERLEAVED);
103   if( ret >= 0 )
104     ret = snd_pcm_hw_params_set_format(zpcm, phw, fmt);
105   if( ret >= 0 ) {
106     zpcm_channels = chs;
107     ret = snd_pcm_hw_params_set_channels(zpcm, phw, chs);
108   }
109   if( ret >= 0 ) {
110     zpcm_rate = rate;
111     ret = snd_pcm_hw_params_set_rate_near(zpcm, phw, &zpcm_rate, 0);
112     if( (int)zpcm_rate != rate )
113       printf("nearest audio_rate for %d is %u\n",rate,zpcm_rate);
114   }
115   if( ret >= 0 )
116     ret = snd_pcm_hw_params_set_buffer_time_near(zpcm, phw,
117       &zpcm_bfr_time_us, &dir);
118   if( ret >= 0 )
119     ret = snd_pcm_hw_params_get_buffer_size(phw, &zpcm_ufrm_size);
120   if( ret >= 0 ) {
121     zpcm_sbfr_size = zpcm_ufrm_size;
122     ret = snd_pcm_hw_params_set_period_time_near(zpcm, phw,
123       &zpcm_per_time_us, &dir);
124   }
125   if( ret >= 0 )
126     ret = snd_pcm_hw_params_get_period_size(phw, &zpcm_ufrm_size, &dir);
127   if( ret >= 0 ) {
128     zpcm_sper_size = zpcm_ufrm_size;
129     ret = snd_pcm_hw_params(zpcm, phw);
130   }
131   if( ret >= 0 )
132     ret = snd_pcm_sw_params_current(zpcm, psw);
133   if( ret >= 0 )
134     ret = snd_pcm_sw_params_set_start_threshold(zpcm, psw,
135       (zpcm_sbfr_size / zpcm_sper_size) * zpcm_sper_size);
136   if( ret >= 0 )
137     ret = snd_pcm_sw_params_set_avail_min(zpcm, psw, zpcm_sper_size);
138   if( ret >= 0 )
139     ret = snd_pcm_sw_params(zpcm, psw);
140   /* snd_pcm_dump(zpcm, stdout); */
141
142   if( ret >= 0 ) {
143 #ifdef __cplusplus
144      zpcm_areas = new snd_pcm_channel_area_t[chs];
145      byts = snd_pcm_format_physical_width(fmt) / 8;
146      zpcm_samples = new short[zpcm_sper_size * chs * byts/2];
147      zpcm_buffers = new short *[chs];
148 #else
149      zpcm_areas = calloc(chs, sizeof(snd_pcm_channel_area_t));
150      bits = snd_pcm_format_physical_width(fmt);
151      byts = bits / 8;
152      zpcm_samples = malloc(zpcm_sper_size * chs * byts);
153      zpcm_buffers = malloc(chs * sizeof(short*));
154 #endif
155      if( zpcm_samples ) {
156        for( ich = 0; ich < chs; ++ich ) {
157          zpcm_areas[ich].addr = zpcm_samples;
158          zpcm_areas[ich].first = ich * zpcm_sper_size * bits;
159          zpcm_areas[ich].step = bits;
160          zpcm_buffers[ich] = zpcm_samples + ich*zpcm_sper_size;
161        }
162      }
163      else {
164        fprintf(stderr,"alsa sample buffer allocation failure.\n");
165        ret = -999;
166      }
167   }
168   if( ret < 0 ) {
169     if( ret > -999 )
170       printf("audio error: %s\n", snd_strerror(ret));
171     alsa_close();
172   }
173 }
174
175 short *alsa_bfr(int ch)
176 {
177   return zpcm_buffers[ch];
178 }
179
180 int alsa_bfrsz()
181 {
182   return zpcm_sper_size;
183 }
184
185 int alsa_recovery(int ret)
186 {
187   printf("alsa recovery\n");
188   switch( ret ) {
189   case -ESTRPIPE:
190     /* wait until the suspend flag is released, then fall through */
191     while( (ret=snd_pcm_resume(zpcm)) == -EAGAIN ) usleep(100000);
192   case -EPIPE:
193     ret = snd_pcm_prepare(zpcm);
194     if( ret < 0 )
195       printf("underrun, prepare failed: %s\n", snd_strerror(ret));
196     break;
197   default:
198     printf("unhandled error: %s\n",snd_strerror(ret));
199     break;
200   }
201   return ret;
202 }
203
204 int alsa_write(int length)
205 {
206   struct timeval tv;
207   int i, ret, count, retry;
208   snd_pcm_sframes_t sample_delay;
209   double play_time, time;
210 #ifdef __cplusplus
211   short *bfrs[zpcm_channels];
212 #else
213   short **bfrs = alloca(zpcm_channels*sizeof(short *));
214 #endif
215   retry = 3;
216   ret = count = 0;
217   for( i=0; i<zpcm_channels; ++i ) bfrs[i] = zpcm_buffers[i];
218
219   while( count < length ) {
220     ret = snd_pcm_writen(zpcm,(void **)bfrs, length-count);
221     if( ret == -EAGAIN ) continue;
222     if ( ret < 0 ) {
223       if( --retry < 0 ) return ret;
224       alsa_recovery(ret);
225       ret = 0;
226       continue;
227     }
228     for( i=0; i<zpcm_channels; ++i ) bfrs[i] += ret;
229     count += ret;
230   }
231   pthread_mutex_lock(&zpcm_lock);
232   zpcm_total_samples += count;
233   snd_pcm_delay(zpcm,&sample_delay);
234   if( sample_delay > zpcm_total_samples )
235     sample_delay = zpcm_total_samples;
236   gettimeofday(&tv,NULL);
237   time = tv.tv_sec + tv.tv_usec/1000000.0;
238   play_time = (zpcm_total_samples - sample_delay) / (double)zpcm_rate;
239   zpcm_play_time = time - play_time;
240   pthread_mutex_unlock(&zpcm_lock);
241   return ret < 0 ? ret : 0;
242 }
243
244 double alsa_time()
245 {
246   double time, play_time;
247   struct timeval tv;
248   pthread_mutex_lock(&zpcm_lock);
249   gettimeofday(&tv,NULL);
250   time = tv.tv_sec + tv.tv_usec/1000000.0;
251   play_time = time - zpcm_play_time;
252   pthread_mutex_unlock(&zpcm_lock);
253   return play_time;
254 }
255
256 #endif
257
258 int done = 0;
259
260 void sigint(int n)
261 {
262   done = 1;
263 }
264
265
266 void dst_exit(GtkWidget *widget, gpointer data)
267 {
268    exit(0);
269 }
270
271 double tstart;
272
273 double the_time()
274 {
275   double time;
276   struct timeval tv;
277   gettimeofday(&tv,NULL);
278   time = tv.tv_sec + tv.tv_usec/1000000.0;
279   if( tstart < 0. ) tstart = time;
280   return time - tstart;
281 }
282
283
284 void mpeg3_stats(zmpeg3_t *zsrc)
285 {
286   int astream, vstream;
287   int has_audio, total_astreams, audio_channels, sample_rate;
288   int has_video, total_vstreams, width, height, colormodel;
289   long audio_samples, video_frames;
290   float frame_rate;
291
292   has_audio = mpeg3_has_audio(zsrc);
293   printf(" has_audio = %d\n", has_audio);
294   total_astreams = mpeg3_total_astreams(zsrc);
295   printf(" total_astreams = %d\n", total_astreams);
296   for( astream=0; astream<total_astreams; ++astream ) {
297     audio_channels = mpeg3_audio_channels(zsrc, astream);
298     printf("   audio_channels = %d\n", audio_channels);
299     sample_rate = mpeg3_sample_rate(zsrc, astream);
300     printf("   sample_rate = %d\n", sample_rate);
301     audio_samples = mpeg3_audio_samples(zsrc, astream);
302     printf("   audio_samples = %ld\n", audio_samples);
303   }
304   printf("\n");
305   has_video = mpeg3_has_video(zsrc);
306   printf(" has_video = %d\n", has_video);
307   total_vstreams = mpeg3_total_vstreams(zsrc);
308   printf(" total_vstreams = %d\n", total_vstreams);
309   for( vstream=0; vstream<total_vstreams; ++vstream ) {
310     width = mpeg3_video_width(zsrc, vstream);
311     printf("   video_width = %d\n", width);
312     height = mpeg3_video_height(zsrc, vstream);
313     printf("   video_height = %d\n", height);
314     frame_rate = mpeg3_frame_rate(zsrc, vstream);
315     printf("   frame_rate = %f\n", frame_rate);
316     video_frames = mpeg3_video_frames(zsrc, vstream);
317     printf("   video_frames = %ld\n", video_frames);
318     colormodel = mpeg3_colormodel(zsrc, vstream);
319     printf("   colormodel = %d\n", colormodel);
320   }
321 }
322
323 #ifdef VIDEO
324 double vstart;
325 double last_vtime;
326
327 double video_time(zmpeg3_t *zsrc,int stream)
328 {
329 #ifdef __cplusplus
330   double vtime = mpeg3_get_video_time(zsrc,stream);
331 #else
332   double vtime = mpeg3_get_time(zsrc);
333 #endif
334   double vnow = vtime;
335   if( vstart == 0. ) vstart = vnow;
336   if( vtime < last_vtime )
337     vstart -= last_vtime;
338   last_vtime = vtime;
339   return vnow - vstart + nudge;
340 }
341
342 pthread_t the_video;
343
344 void *video_thread(void *the_zsrc)
345 {
346   GtkWidget *window;
347   GtkWidget *panel_hbox;
348   GtkWidget *image;
349   GdkPixbuf *pbuf0, *pbuf1;
350   GdkImage  *img0, *img1;
351   GdkVisual *visual;
352   double delay;
353   float frame_rate, frame_delay;
354   unsigned char **rows, **row0, **row1, *cap, *cap0, *cap1;
355   int ret, row, frame, dropped, more_data;
356   int width, height, owidth, oheight;
357   const int frame_drop = 1;
358   zmpeg3_t *zsrc = (zmpeg3_t *)the_zsrc;
359
360   frame_rate = mpeg3_frame_rate(zsrc, 0);
361   frame_delay = 2.0 / frame_rate;
362   height = mpeg3_video_height(zsrc, 0);
363   width = mpeg3_video_width(zsrc, 0);
364   //oheight = 2*height / 3;
365   //owidth = 2*width / 3;
366   //oheight = 1050-96;
367   //owidth = 1680-64;
368   //oheight = height;
369   //owidth = width;
370   oheight = 720;
371   owidth = 1280;
372
373   visual = gdk_visual_get_system();
374   /* toplevel window */
375   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
376   gtk_signal_connect(GTK_OBJECT(window),"destroy",
377      GTK_SIGNAL_FUNC(dst_exit),NULL);
378   gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_NONE);
379   /* try for shared image bfr, only seems to work with gtk_rgb */
380   img0 = gdk_image_new(GDK_IMAGE_SHARED, visual, owidth, oheight);
381   pbuf0 = gdk_pixbuf_new_from_data((const guchar *)img0->mem,
382              GDK_COLORSPACE_RGB,RGBA,8,owidth,oheight,owidth*BPP,NULL,NULL);
383   cap0 = gdk_pixbuf_get_pixels(pbuf0);
384   image = gtk_image_new_from_pixbuf(pbuf0);
385   /* double buffered */
386   img1 = gdk_image_new(GDK_IMAGE_SHARED, visual, owidth, oheight);
387   pbuf1 = gdk_pixbuf_new_from_data((const guchar *)img1->mem,
388              GDK_COLORSPACE_RGB,RGBA,8,owidth,oheight,owidth*BPP,NULL,NULL);
389   cap1 = gdk_pixbuf_get_pixels(pbuf1);
390
391   panel_hbox = gtk_hbox_new(FALSE,0);
392   gtk_container_add(GTK_CONTAINER(window), panel_hbox);
393   /* pack image into panel */
394   gtk_box_pack_start(GTK_BOX(panel_hbox), image, TRUE, TRUE, 0);
395
396
397 #ifdef __cplusplus
398   row0 = new unsigned char *[oheight];
399   row1 = new unsigned char *[oheight];
400   int cmdl = COLOR_MODEL;
401 #else
402   row0 = malloc(oheight*sizeof(unsigned char *));
403   row1 = malloc(oheight*sizeof(unsigned char *));
404   int cmdl = COLOR_MODEL;
405 #endif
406   for( row=0; row<oheight; ++row ) {
407     row0[row] = cap0 + row*owidth*BPP;
408     row1[row] = cap1 + row*owidth*BPP;
409   }
410
411   gtk_widget_show_all(window);
412   cap = cap0;
413   rows = row0;
414   frame = dropped = 0;
415   vstart = last_vtime = 0.;
416   more_data = 1;
417
418   while( done == 0 && more_data ) {
419     if( !gtk_events_pending() ) {
420       more_data = 0;
421 //      delay = (frame+dropped)/frame_rate - alsa_time();
422 //      delay = the_time() - video_time(zsrc,0);
423       if( frame_drop ) {
424         if( -delay >= frame_delay ) {
425           int nframes = (long)ceil(-delay/frame_rate);
426           if( nframes > 2 ) nframes = 2;
427           mpeg3_drop_frames(zsrc,nframes,0);
428           dropped += nframes;
429         }
430       }
431       //if( delay > 0 )
432       //  usleep((int)(delay*1000000.0));
433       ret = mpeg3_read_frame(zsrc, rows, 0, 0, width, height,
434                owidth, oheight, cmdl, 0);
435       //printf("%d %ld\n",frame,zsrc->vtrack[0]->demuxer->titles[0]->fs->current_byte);
436       if( verbose )
437         printf("read_video(stream=%d, frame=%d) = %d\n", 0, frame, ret);
438       //if( frame > 500 && frame < 800 ) {
439       //  mpeg3_previous_frame(zsrc,0);
440       //  mpeg3_previous_frame(zsrc,0);
441       //}
442       GdkGC *blk = image->style->black_gc;
443       gdk_draw_rgb_image(image->window,blk, 0,0,owidth,oheight,
444          GDK_RGB_DITHER_NONE,cap,owidth*BPP);
445 #if 0
446 #if 0
447       { static FILE *fp = 0;
448         int sz = owidth*oheight*BPP;
449         if( fp == 0 ) fp = fopen("/tmp/dat.raw","w");
450         fwrite(cap,1,sz,fp);
451       }
452 #else
453       { static FILE *fp = 0;
454         int z, sz = owidth*oheight*BPP;
455         uint8_t zbfr[sz];
456         if( fp == 0 ) fp = fopen("/tmp/dat.raw","r");
457         fread(zbfr,1,sz,fp);
458         for( z=0; z<sz && abs(zbfr[z]-cap[z])<=1; ++z );
459         //for( z=0; z<sz && zbfr[z]==cap[z]; ++z );
460         if( z < sz )
461           printf("bug %d\n",z);
462       }
463 #endif
464       if( frame > 250 ) exit(0);
465 #endif
466       *(unsigned long *)&cap ^= ((unsigned long)cap0 ^ (unsigned long)cap1);
467       *(unsigned long *)&rows ^= ((unsigned long)row0 ^ (unsigned long)row1);
468       //printf(" %d/%d  %f  %f  %f\n",frame,dropped,(frame+dropped)/frame_rate,
469       //  video_time(zsrc,0),mpeg3_get_video_time(zsrc,0));
470       ++frame;
471       more_data |= !mpeg3_end_of_video(zsrc,0);
472     }
473     else
474       gtk_main_iteration();
475   }
476
477   return (void*)0;
478 }
479
480 #endif
481
482 #ifdef AUDIO
483 double astart;
484
485 double audio_time(zmpeg3_t *zsrc, int stream)
486 {
487 #ifdef __cplusplus
488   double anow = mpeg3_get_audio_time(zsrc,stream);
489 #else
490   double anow = mpeg3_get_time(zsrc);
491 #endif
492   if( astart < 0. ) astart = anow;
493   return anow - astart;
494 }
495
496 pthread_t the_audio;
497
498 void *audio_thread(void *the_zsrc)
499 {
500   double delay;
501   int audio_channels, sample_rate, more_data;
502   zmpeg3_t *zsrc = (zmpeg3_t *)the_zsrc;
503   int stream = 0;
504
505   audio_channels = mpeg3_audio_channels(zsrc, stream);
506   sample_rate = mpeg3_sample_rate(zsrc, stream);
507   alsa_open(audio_channels,sample_rate);
508   astart = -1.;
509   more_data = 1;
510
511   while( done == 0 && more_data ) {
512     more_data = 0;
513     int ich;
514     int n = alsa_bfrsz();
515     for( ich=0; ich<audio_channels; ++ich) {
516       short *bfr = alsa_bfr(ich);
517       int ret = ich == 0 ?
518         mpeg3_read_audio(zsrc, 0, bfr, ich, n, stream) :
519         mpeg3_reread_audio(zsrc, 0, bfr, ich, n, stream);
520       if( verbose )
521         printf("read_audio(stream=%d,channel=%d) = %d\n", stream, ich, ret);
522     }
523
524     alsa_write(n);
525     delay = audio_time(zsrc,stream) - the_time();
526     if( (delay-ahead) > 0. )
527       usleep((int)(delay*1000000.0/2.));
528     more_data |= !mpeg3_end_of_audio(zsrc,0);
529   }
530
531   alsa_close();
532   return (void*)0;
533 }
534
535 #endif
536
537
538 int main(int ac, char **av)
539 {
540   int ret;
541   setbuf(stdout,NULL);
542   tstart = -1.;
543
544 #ifdef VIDEO
545   gtk_set_locale();
546   gtk_init(&ac, &av);
547 #endif
548
549   //zmpeg3_t* zsrc = mpeg3_open("/tmp/dat",&ret);
550   //zmpeg3_t* zsrc = mpeg3_zopen(0,"/tmp/dat",&ret,ZIO_UNBUFFERED+ZIO_SINGLE_ACCESS+ZIO_SEQUENTIAL);
551   //zmpeg3_t* zsrc = mpeg3_open("/tmp/dat.toc",&ret);
552   //zmpeg3_t* zsrc = mpeg3_open("/root/LimeWire/Shared/Britney Spears - Pepsi Commercial with Bob Dole.mpeg",&ret);
553   //zmpeg3_t* zsrc = mpeg3_open("/tmp/dat.mp3",&ret);
554   //zmpeg3_t* zsrc = mpeg3_open("/dvd/VIDEO_TS/VTS_01_0.IFO",&ret);
555   //zmpeg3_t* zsrc = mpeg3_open("/home/dat2.vts",&ret);
556   //zmpeg3_t* zsrc = mpeg3_open("/dvd/BDMV/STREAM/00000.m2ts",&ret);
557   zmpeg3_t* zsrc = mpeg3_open(av[1],&ret);
558   ysrc = zsrc;
559   printf(" ret = %d\n",ret);
560   if( ret != 0 ) exit(1);
561   mpeg3_stats(zsrc);
562
563 #ifdef AUDIO
564 #ifdef __cplusplus
565   zmpeg3_t* zsrc1 = zsrc;
566 #else
567   zmpeg3_t* zsrc1 = mpeg3_open_copy(zsrc->fs->path, zsrc, &ret);
568 #endif
569 #endif
570
571   mpeg3_set_cpus(zsrc,3);
572   mpeg3_seek_byte(zsrc,0);
573   mpeg3_show_subtitle(zsrc, 0);
574   signal(SIGINT,sigint);
575
576 #ifdef AUDIO
577   pthread_create(&the_audio, NULL, audio_thread, (void*)zsrc1);
578 #endif
579 #ifdef VIDEO
580   pthread_create(&the_video, NULL, video_thread, (void*)zsrc);
581 #endif
582 #ifdef VIDEO
583   pthread_join(the_video,NULL);
584 #endif
585 #ifdef AUDIO
586   pthread_join(the_audio,NULL);
587 #endif
588
589   mpeg3_close(zsrc);
590   return 0;
591 }
592