version update
[goodguy/cinelerra.git] / cinelerra-5.1 / libzmpeg3 / yy.C
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <alsa/asoundlib.h>
4 #include <sys/time.h>
5 #include <gtk/gtk.h>
6 #include <gdk/gdk.h>
7
8 #ifdef __cplusplus
9 #include "libzmpeg3.h"
10 #else
11 #include "../libmpeg3/libmpeg3.h"
12 #define zmpeg3_t mpeg3_t
13 #endif
14
15 #define AUDIO
16 #define VIDEO
17
18 /* c++ `pkg-config --cflags --libs gtk+-2.0` y.C ./x86_64/libzmpeg3.a -lpthread -lasound -lm */
19
20 #ifdef AUDIO
21 snd_pcm_t *zpcm;
22 snd_pcm_uframes_t zpcm_ufrm_size;
23 snd_pcm_sframes_t zpcm_sbfr_size;
24 snd_pcm_sframes_t zpcm_sper_size;
25 unsigned int zpcm_rate;
26 static const char *zpcm_device = "plughw:0,0";
27 static unsigned int zpcm_bfr_time_us = 500000; 
28 static unsigned int zpcm_per_time_us = 200000;
29 static snd_pcm_channel_area_t *zpcm_areas = 0;
30 static int zpcm_channels = 0;
31 static short **zpcm_buffers = 0;
32 static short *zpcm_samples = 0;
33
34 void alsa_close()
35 {
36 #ifdef __cplusplus
37   if( zpcm_buffers != 0 ) { delete [] zpcm_buffers; zpcm_buffers = 0; }
38   if( zpcm_areas != 0 ) { delete [] zpcm_areas; zpcm_areas = 0; }
39   if( zpcm_samples != 0 ) { delete [] zpcm_samples; zpcm_samples = 0; }
40 #else
41   if( zpcm_buffers != 0 ) { free(zpcm_buffers); zpcm_buffers = 0; }
42   if( zpcm_areas != 0 ) { free(zpcm_areas); zpcm_areas = 0; }
43   if( zpcm_samples != 0 ) { free(zpcm_samples); zpcm_samples = 0; }
44 #endif
45   if( zpcm != 0 ) { snd_pcm_close(zpcm);  zpcm = 0; }
46 }
47
48 void alsa_open(int chs,int rate)
49 {
50   int ich, bits, byts, dir, ret;
51   snd_pcm_format_t fmt = SND_PCM_FORMAT_S16;
52   snd_pcm_hw_params_t *phw;
53   snd_pcm_sw_params_t *psw;
54   snd_pcm_hw_params_alloca(&phw);
55   snd_pcm_sw_params_alloca(&psw);
56
57   zpcm = 0;
58   ret = snd_pcm_open(&zpcm, zpcm_device,
59      SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
60   if( ret >= 0 )
61     ret = snd_pcm_hw_params_any(zpcm, phw);
62   if( ret >= 0 )
63     ret = snd_pcm_hw_params_set_rate_resample(zpcm, phw, 1);
64   if( ret >= 0 )
65     ret = snd_pcm_hw_params_set_access(zpcm, phw,
66       SND_PCM_ACCESS_RW_NONINTERLEAVED);
67   if( ret >= 0 )
68     ret = snd_pcm_hw_params_set_format(zpcm, phw, fmt);
69   if( ret >= 0 ) {
70     zpcm_channels = chs;
71     ret = snd_pcm_hw_params_set_channels(zpcm, phw, chs);
72   }
73   if( ret >= 0 ) {
74     zpcm_rate = rate;
75     ret = snd_pcm_hw_params_set_rate_near(zpcm, phw, &zpcm_rate, 0);
76     if( (int)zpcm_rate != rate )
77       printf("nearest audio_rate for %d is %u\n",rate,zpcm_rate);
78   }
79   if( ret >= 0 )
80     ret = snd_pcm_hw_params_set_buffer_time_near(zpcm, phw,
81       &zpcm_bfr_time_us, &dir);
82   if( ret >= 0 )
83     ret = snd_pcm_hw_params_get_buffer_size(phw, &zpcm_ufrm_size);
84   if( ret >= 0 ) {
85     zpcm_sbfr_size = zpcm_ufrm_size;
86     ret = snd_pcm_hw_params_set_period_time_near(zpcm, phw,
87       &zpcm_per_time_us, &dir);
88   }
89   if( ret >= 0 )
90     ret = snd_pcm_hw_params_get_period_size(phw, &zpcm_ufrm_size, &dir);
91   if( ret >= 0 ) {
92     zpcm_sper_size = zpcm_ufrm_size;
93     ret = snd_pcm_hw_params(zpcm, phw);
94   }
95   if( ret >= 0 )
96     ret = snd_pcm_sw_params_current(zpcm, psw);
97   if( ret >= 0 )
98     ret = snd_pcm_sw_params_set_start_threshold(zpcm, psw,
99       (zpcm_sbfr_size / zpcm_sper_size) * zpcm_sper_size);
100   if( ret >= 0 )
101     ret = snd_pcm_sw_params_set_avail_min(zpcm, psw, zpcm_sper_size);
102   if( ret >= 0 )
103     ret = snd_pcm_sw_params(zpcm, psw);
104   /* snd_pcm_dump(zpcm, stdout); */
105
106   if( ret >= 0 ) {
107 #ifdef __cplusplus
108      zpcm_areas = new snd_pcm_channel_area_t[chs];
109      byts = snd_pcm_format_physical_width(fmt) / 8;
110      zpcm_samples = new short[zpcm_sper_size * chs * byts/2];
111      zpcm_buffers = new short *[chs];
112 #else
113      zpcm_areas = calloc(chs, sizeof(snd_pcm_channel_area_t));
114      bits = snd_pcm_format_physical_width(fmt);
115      byts = bits / 8;
116      zpcm_samples = malloc(zpcm_sper_size * chs * byts);
117      zpcm_buffers = malloc(chs * sizeof(short*));
118 #endif
119      if( zpcm_samples ) {
120        for( ich = 0; ich < chs; ++ich ) {
121          zpcm_areas[ich].addr = zpcm_samples;
122          zpcm_areas[ich].first = ich * zpcm_sper_size * bits;
123          zpcm_areas[ich].step = bits;
124          zpcm_buffers[ich] = zpcm_samples + ich*zpcm_sper_size;
125        }
126      }
127      else {
128        fprintf(stderr,"alsa sample buffer allocation failure.\n");
129        ret = -999;
130      }
131   }
132   if( ret < 0 ) {
133     if( ret > -999 )
134       printf("audio error: %s\n", snd_strerror(ret));
135     alsa_close();
136   }
137 }
138
139 short *alsa_bfr(int ch)
140 {
141   return zpcm_buffers[ch];
142 }
143
144 int alsa_bfrsz()
145 {
146   return zpcm_sper_size;
147 }
148
149 int alsa_recovery(int ret)
150 {
151   printf("alsa recovery\n");
152   switch( ret ) {
153   case -ESTRPIPE:
154     /* wait until the suspend flag is released, then fall through */
155     while( (ret=snd_pcm_resume(zpcm)) == -EAGAIN ) usleep(100000);
156   case -EPIPE:
157     ret = snd_pcm_prepare(zpcm);
158     if( ret < 0 )
159       printf("underrun, prepare failed: %s\n", snd_strerror(ret));
160     break;
161   default:
162     printf("unhandled error: %s\n",snd_strerror(ret));
163     break;
164   }
165   return ret;
166 }
167
168 int alsa_write(int len)
169 {
170   int i, ret;
171 #ifdef __cplusplus
172   short *bfrs[zpcm_channels];
173 #else
174   short **bfrs = alloca(zpcm_channels*sizeof(short *));
175 #endif
176   ret = 0;
177   for( i=0; i<zpcm_channels; ++i ) bfrs[i] = zpcm_buffers[i];
178
179   while( len > 0 ) {
180     ret = snd_pcm_writen(zpcm,(void **)bfrs, len);
181     if( ret == -EAGAIN ) continue;
182     if ( ret < 0 ) {
183       alsa_recovery(ret);
184       break;
185     }
186     for( i=0; i<zpcm_channels; ++i ) bfrs[i] += ret;
187     len -= ret;
188   }
189   return ret < 0 ? ret : 0;
190 }
191
192 #endif
193
194 int done = 0;
195
196 void sigint(int n)
197 {
198   done = 1;
199 }
200
201
202 void dst_exit(GtkWidget *widget, gpointer data)
203 {
204    exit(0);
205 }
206
207 double the_time()
208 {
209   struct timeval tv;
210   gettimeofday(&tv,NULL);
211   return tv.tv_sec + tv.tv_usec/1000000.0;
212 }
213
214 int main(int ac, char **av)
215 {
216   int ret, more_data, frame, astream, vstream;
217   int has_audio, total_astreams, audio_channels, sample_rate;
218   int has_video, total_vstreams, width, height, colormodel;
219   int owidth, oheight;
220   long audio_samples, video_frames;
221   float frame_rate;
222
223 #ifdef VIDEO
224   GtkWidget *window;
225   GtkWidget *panel_hbox;
226   GtkWidget *image;
227   GdkPixbuf *pbuf0, *pbuf1;
228   GdkImage  *img0, *img1;
229   GdkVisual *visual;
230   double start, zstart, now, znow, delay;
231   unsigned char **rows, **row0, **row1, *cap, *cap0, *cap1;
232   int row;
233
234   start = the_time();
235   zstart = -1;
236 #endif
237
238   setbuf(stdout,NULL);
239
240   zmpeg3_t* zsrc = mpeg3_open("/tmp/dat",&ret);
241   //zmpeg3_t* zsrc = mpeg3_open("/root/LimeWire/Shared/Britney Spears - Pepsi Commercial with Bob Dole.mpeg",&ret);
242   //zmpeg3_t* zsrc = mpeg3_open("/tmp/dat.mp3",&ret);
243   //zmpeg3_t* zsrc = mpeg3_open("/dvd/VIDEO_TS/VIDEO_TS.IFO",&ret);
244   printf(" ret = %d\n",ret);
245   if( ret != 0 ) exit(1);
246   has_audio = mpeg3_has_audio(zsrc);
247   printf(" has_audio = %d\n", has_audio);
248   total_astreams = mpeg3_total_astreams(zsrc);
249   printf(" total_astreams = %d\n", total_astreams);
250   for( astream=0; astream<total_astreams; ++astream ) {
251     audio_channels = mpeg3_audio_channels(zsrc, astream);
252     printf("   audio_channels = %d\n", audio_channels);
253     sample_rate = mpeg3_sample_rate(zsrc, astream);
254     printf("   sample_rate = %d\n", sample_rate);
255     audio_samples = mpeg3_audio_samples(zsrc, astream);
256     printf("   audio_samples = %ld\n", audio_samples);
257   }
258   printf("\n");
259   has_video = mpeg3_has_video(zsrc);
260   printf(" has_video = %d\n", has_video);
261   total_vstreams = mpeg3_total_vstreams(zsrc);
262   printf(" total_vstreams = %d\n", total_vstreams);
263   for( vstream=0; vstream<total_vstreams; ++vstream ) {
264     width = mpeg3_video_width(zsrc, vstream);
265     printf("   video_width = %d\n", width);
266     height = mpeg3_video_height(zsrc, vstream);
267     printf("   video_height = %d\n", height);
268     frame_rate = mpeg3_frame_rate(zsrc, vstream);
269     printf("   frame_rate = %f\n", frame_rate);
270     video_frames = mpeg3_video_frames(zsrc, vstream);
271     printf("   video_frames = %ld\n", video_frames);
272     colormodel = mpeg3_colormodel(zsrc, vstream);
273     printf("   colormodel = %d\n", colormodel);
274   }
275
276   //mpeg3_set_cpus(zsrc,2);
277   mpeg3_seek_byte(zsrc,0);
278   //oheight = 1050-96;
279   //owidth = 1680-64;
280   oheight = height;
281   owidth = width;
282
283 #ifdef AUDIO
284   alsa_open(audio_channels,sample_rate);
285 #endif
286 #ifdef VIDEO
287   gtk_set_locale();
288   gtk_init(&ac, &av);
289   visual = gdk_visual_get_system();
290   /* toplevel window */
291   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
292   gtk_signal_connect(GTK_OBJECT(window),"destroy",
293      GTK_SIGNAL_FUNC(dst_exit),NULL);
294   gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_NONE);
295   /* try for shared image bfr, only seems to work with gtk_rgb */
296   img0 = gdk_image_new(GDK_IMAGE_SHARED, visual, owidth, oheight);
297   pbuf0 = gdk_pixbuf_new_from_data((const guchar *)img0->mem,
298              GDK_COLORSPACE_RGB,FALSE,8,owidth,oheight,owidth*3,NULL,NULL);
299   cap0 = gdk_pixbuf_get_pixels(pbuf0);
300   image = gtk_image_new_from_pixbuf(pbuf0);
301   /* double buffered */
302   img1 = gdk_image_new(GDK_IMAGE_SHARED, visual, owidth, oheight);
303   pbuf1 = gdk_pixbuf_new_from_data((const guchar *)img1->mem,
304              GDK_COLORSPACE_RGB,FALSE,8,owidth,oheight,owidth*3,NULL,NULL);
305   cap1 = gdk_pixbuf_get_pixels(pbuf1);
306
307   panel_hbox = gtk_hbox_new(FALSE,0);
308   gtk_container_add(GTK_CONTAINER(window), panel_hbox);
309   /* pack image into panel */
310   gtk_box_pack_start(GTK_BOX(panel_hbox), image, TRUE, TRUE, 0);
311
312
313 #ifdef __cplusplus
314   row0 = new unsigned char *[oheight];
315   row1 = new unsigned char *[oheight];
316   int cmdl = zmpeg3_t::cmdl_RGB888;
317 #else
318   row0 = malloc(oheight*sizeof(unsigned char *));
319   row1 = malloc(oheight*sizeof(unsigned char *));
320   int cmdl = MPEG3_RGB888;
321 #endif
322   for( row=0; row<oheight; ++row ) {
323     row0[row] = cap0 + row*owidth*3;
324     row1[row] = cap1 + row*owidth*3;
325   }
326
327   gtk_widget_show_all(window);
328   cap = cap0;
329   rows = row0;
330 #endif
331
332   signal(SIGINT,sigint);
333   frame = 0;
334   more_data = 1;
335
336   while( done == 0 && more_data ) {
337 #ifdef VIDEO
338     if( !gtk_events_pending() ) {
339 #endif
340       more_data = 0;
341 #ifdef AUDIO
342       int ich;
343       int n = alsa_bfrsz();
344       for( ich=0; ich<audio_channels; ++ich) {
345         short *bfr = alsa_bfr(ich);
346         ret = ich == 0 ?
347           mpeg3_read_audio(zsrc, 0, bfr, ich, n, 0) :
348           mpeg3_reread_audio(zsrc, 0, bfr, ich, n, 0);
349         printf("read_audio(stream=%d,channel=%d) = %d\n", 0, ich, ret);
350       }
351       alsa_write(n);
352       more_data |= !mpeg3_end_of_audio(zsrc,0);
353 #endif
354 #ifdef VIDEO
355       ret = mpeg3_read_frame(zsrc, rows, 0, 0, width, height,
356                owidth, oheight, cmdl, 0);
357       printf("read_video(stream=%d, frame=%d) = %d\n", 0, frame, ret);
358       GdkGC *blk = image->style->black_gc;
359       gdk_draw_rgb_image(image->window,blk, 0,0,owidth,oheight,
360          GDK_RGB_DITHER_NONE,cap,owidth*3);
361       *(unsigned long *)&cap ^= ((unsigned long)cap0 ^ (unsigned long)cap1);
362       *(unsigned long *)&rows ^= ((unsigned long)row0 ^ (unsigned long)row1);
363       now = the_time();
364       znow = mpeg3_get_time(zsrc);
365       if( zstart < 0. ) zstart = znow;
366       delay = (znow-zstart) - (now-start);
367       if( delay > 0 ) usleep((int)(delay*100000.0));
368       more_data |= !mpeg3_end_of_video(zsrc,0);
369 #endif
370       ++frame;
371 #ifdef VIDEO
372     }
373     else
374       gtk_main_iteration();
375 #endif
376   }
377
378 #ifdef AUDIO
379   alsa_close();
380 #endif
381   mpeg3_close(zsrc);
382   return 0;
383 }
384