source: trunk/src/testing/app/bitplay/bplay.c @ 4

Revision 4, 33.2 KB checked in by ajaworski, 13 years ago (diff)

Added modified SAGE sources

Line 
1/******************************************************************************
2 * SAGE - Scalable Adaptive Graphics Environment
3 *
4 * Copyright (C) 2004 Electronic Visualization Laboratory,
5 * University of Illinois at Chicago
6 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above
15 *    copyright notice, this list of conditions and the following disclaimer
16 *    in the documentation and/or other materials provided with the distribution.
17 *  * Neither the name of the University of Illinois at Chicago nor
18 *    the names of its contributors may be used to endorse or promote
19 *    products derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Direct questions, comments etc about SAGE to http://www.evl.uic.edu/cavern/forum/
34 *
35 *****************************************************************************/
36
37/*
38 * Bulk movieplayer.  Plays uncompressed movies as encoded by "img2bmv",
39 * using bpio threaded I/O library and OpenGL texturing.
40 *
41 * Stuart Levy, NCSA, University of Illinois Urbana-Champaign, June, 2004.
42 */
43
44#include "bpio.h"       /* Need this first since it #defines some large-file options */
45
46#include <stdlib.h>
47#include <stdio.h>
48#include <string.h>
49#include <math.h>
50#include <time.h>
51#include <signal.h>
52#include <errno.h>
53#include <sys/time.h>
54#include <getopt.h>
55
56#include "bpmovie.h"
57
58// headers for SAGE
59#include "sail.h"
60#include "misc.h"
61sail sageInf; // sail object
62unsigned char *rgbBuffer = 0;
63float pixelSize = 3.0;
64
65
66/*
67struct txcodes {
68    int internalfmt;
69    int format;
70    int type;
71} txcode[] = {
72    { 0,0,0 },
73    { GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE },
74    { GL_RGB,       GL_RGB,       GL_UNSIGNED_SHORT_5_6_5 },
75    { GL_RGB,       GL_RGB,       GL_UNSIGNED_BYTE },
76    { GL_RGBA,      GL_RGBA,      GL_UNSIGNED_BYTE }
77};
78*/
79
80int nfillers = 4;
81int nbufseach = 5;
82int readsize = 8388608;    // 8MB
83int port = 0;
84
85char *prog;
86
87char *controlfname;
88
89enum stereomode { MONO, CROSSEYED, QUADBUFFERED };
90
91enum stereomode stereo = CROSSEYED;
92
93
94        /* State variables */
95int winx, winy;         /* current window size */
96int newtex = 1;         /* newly minted textures? (need full init rather than subload) */
97
98int paused = 1;         /* Movie paused? */
99int doloop = 0;
100int majorloop = 1;
101int playfwd = 1;
102int quitnow = 0;
103int rateoverride = 0;   /* Should defaultrate override preferred-rate setting in movie? */
104int defaultrate = 10;   /* default target frames/sec */
105int framems = 100;      /* target milliseconds per frame */
106int msfudge = 35;       /* framems = 1000/rate - msfudge */
107int verbose = 0;
108int skipby = 1;         /* skip -- show every Nth frame */
109int preloadms = 0;      /* After switching movies, wait this long for startup */
110int shiftoverride = 0;
111int defaultshift = 0;
112int relshift = 0;
113int nwID = 1;
114
115static int swapinterval = -1;
116
117bpio_t     *playlist;
118bpmvhead_t *mvlist;
119int        nplay;
120int        curplay;
121
122float accumdt = 0, accumweight = 0;
123
124void resumemovie( int loop );
125void pausemovie();
126int openmovie( bpio_t *bpio, char *fname, bpmvhead_t *bpmv );
127
128off_t bpstartpos( bpio_t *bpio )
129{
130    return bpio==NULL ? 0 : bpio->bpb[0].wrappos;
131}
132
133off_t bpendpos( bpio_t *bpio )
134{
135    return bpio==NULL ? 0 : bpio->bpb[0].eofpos;
136}
137
138off_t bpincrpos( bpio_t *bpio )
139{
140    return bpio==NULL ? 0 : bpio->bufsize;
141}
142
143
144int bpawaitone( bpio_t *bpio )
145{
146    bpbuf_t *bpb = &playlist[curplay].bpb[ bpio->drain ];
147
148    pthread_mutex_lock( &bpb->bmut );
149    while(bpbempty( bpb ) && bpb->filling) {
150        bpb->drainwaiting = 1;
151        pthread_cond_wait( &bpb->bdrainwait, &bpb->bmut );
152        bpb->drainwaiting = 0;
153    }
154    pthread_mutex_unlock( &bpb->bmut );
155
156    return !bpbempty(bpb);
157}
158
159int bpconsume1( bpio_t *bpio )
160{
161    bpbuf_t *bpb =  &bpio->bpb[ bpio->drain ];
162
163    if(!bpb->filling)   /* if EOF or bpstop() or etc. */
164        return 0;
165
166    pthread_mutex_lock( &bpb->bmut );
167    bpb->wp = (bpb->wp + 1) % bpb->nbufs;
168
169    if(bpb->fillwaiting)
170        pthread_cond_signal( &bpb->bfillwait );
171    pthread_mutex_unlock( &bpb->bmut );
172
173    bpio->drain = (bpio->drain+1) % bpio->nfillers;
174
175    return bpawaitone( bpio );
176}
177
178int bpframeof( bpio_t *bpio, off_t pos )
179{
180    off_t incr = bpio->bpb[0].incrpos;
181    return incr > 0 ? (pos - bpstartpos(bpio)) / incr :
182           incr < 0 ? (pos - bpstartpos(bpio)) / (-incr) :
183           -1;
184}
185
186int defaultratefor( int curplay )
187{
188    return rateoverride
189         || !(mvlist[curplay].flags & BPF_PREFRATE)
190         || mvlist[curplay].prefrate == -1  /* bug in some versions of img2bmv */
191         ? defaultrate : mvlist[curplay].prefrate;
192}
193
194int defaultshiftfor( int curplay )
195{
196    return shiftoverride || !(mvlist[curplay].flags & BPF_PREFSHIFT)
197                ? defaultshift : mvlist[curplay].prefshift;
198}
199
200int lasttimems;
201
202int timems()
203{
204    static struct timeval then;
205    struct timeval now;
206
207    gettimeofday( &now, NULL );
208    if(then.tv_sec == 0)
209        then = now;
210    return (now.tv_sec - then.tv_sec) * 1000 + (now.tv_usec - then.tv_usec) / 1000;
211}
212
213int playlistadvance( int sign )
214{
215    bpio_t *bpio;
216    int waspaused = paused;
217    int oldplay = curplay;
218
219    if(curplay >= 0)
220        pausemovie();
221
222    curplay += sign;
223
224    if(majorloop)
225        curplay = (curplay + nplay) % nplay;
226
227    if(curplay < 0 || curplay >= nplay) {
228        pausemovie();
229        return 0;
230    }
231
232    if(oldplay != curplay) {
233        int rate = defaultratefor( curplay );
234
235        framems = (rate > 0) ? 1000 / rate - msfudge: -rate;
236
237        relshift = defaultshiftfor( curplay );
238    }
239
240    bpio = &playlist[curplay];
241
242    bpforward( bpio, playfwd * skipby );
243    bpsync( bpio );
244    bpseek( bpio, playfwd>0 ? bpstartpos( bpio )
245            : bpendpos( bpio ) - bpio->bufsize * skipby );
246
247    if(verbose >= 2)
248        fprintf(stderr, "advance %d  framems %d\n", sign, framems);
249
250    if(!waspaused)
251        resumemovie( doloop );
252
253    if(preloadms)
254        usleep( preloadms * 1000 );
255
256    return 1;
257}
258
259void idler(void);
260
261void showlater( int junk )
262{
263        //glutPostRedisplay();
264        //glutIdleFunc( paused ? NULL : idler );
265}
266
267
268void idler()
269{
270    if(quitnow) {
271        exit(1);
272    }
273    if(verbose>=3) { printf("I"); fflush(stdout); }
274
275    if(bpconsume1( &playlist[curplay] )) {
276            /* Got a buffer ready.  Should we show it now? */
277        if(swapinterval >= 0) {
278                /* Rather than timing here, we'll depend on glXSwapIntervalSGI() */
279                //glutPostRedisplay();
280        } else {
281                /* Nope, we do our own timing */
282            int now = timems();
283            if(now >= lasttimems + framems) {
284                    //glutPostRedisplay();
285            } else {
286                    // glutTimerFunc( (lasttimems + framems) - now, showlater,
287                    //           (lasttimems+framems) - now );
288                    // glutIdleFunc( NULL );
289            }
290        }
291    } else {
292        if( ! playlistadvance( playfwd ) )
293        {
294                // glutIdleFunc( NULL );
295        }
296    }
297}
298
299void catch_quit(int sig) {
300    quitnow = 1;
301}
302
303int ntimes = 50;
304
305void resumemovie( int loop )
306{
307    if(verbose>=3) printf("resume %d p%d\n", loop, paused);
308    bpstart( &playlist[curplay], loop );
309    if(bpawaitone( &playlist[curplay] )) {
310            // glutPostRedisplay();
311        if(paused)
312        {
313                // glutIdleFunc( idler );
314        }
315    } else {
316        printf("resume: bpawaitone -> 0?\n");
317    }
318    paused = 0;
319}
320
321void startmovie( int loop )
322{
323    if(verbose>=2) printf("start %d\n", loop);
324    bpseek( &playlist[curplay], bpstartpos( &playlist[curplay] ) );
325    bpsync( &playlist[curplay] );
326    resumemovie( loop );
327}
328
329void pausemovie()
330{
331        //glutIdleFunc( NULL );
332    paused = 1;
333}
334
335static int val, hasnum;
336
337int getval( int def ) {
338    return hasnum < 0 ? -val : hasnum > 0 ? val : def;
339}
340
341void kb( unsigned char key, int x, int y );
342
343void specialkb( int skey, int x, int y )
344{
345    bpio_t *bpio = &playlist[curplay];
346
347        /*
348    switch(skey) {
349        case GLUT_KEY_PAGE_UP:
350            playlistadvance( -1 );
351            break;
352
353        case GLUT_KEY_PAGE_DOWN:
354            playlistadvance( 1 );
355            break;
356
357        case GLUT_KEY_UP:
358            skipby++;
359            bpforward( bpio, skipby * playfwd );
360            break;
361
362        case GLUT_KEY_DOWN:
363            if(skipby>1)
364                skipby--;
365            bpforward( bpio, skipby * playfwd );
366            break;
367
368        case GLUT_KEY_LEFT:
369            if(glutGetModifiers() & GLUT_ACTIVE_CTRL)
370                kb( 'L', x, y );
371            else
372                kb( '<', x, y );
373            break;
374
375        case GLUT_KEY_RIGHT:
376            if(glutGetModifiers() & GLUT_ACTIVE_CTRL)
377                kb( 'R', x, y );
378            else
379                kb( '>', x, y );
380            break;
381
382        case GLUT_KEY_HOME:
383            startmovie( doloop );
384            break;
385    }
386        */
387    hasnum = val = 0;
388}
389
390void kb( unsigned char key, int x, int y )
391{
392    int isdigit = 0;
393    bpio_t *bpio = &playlist[curplay];
394
395    switch(key) {
396        case '\033':
397            exit(0);
398
399        case ' ':
400            paused = !paused;
401            if(paused)
402                pausemovie();
403            else
404                resumemovie( doloop );
405            break;
406
407        case 'p':
408            pausemovie();
409            break;
410
411        case '.': case '<':
412            bpstop( bpio );
413            bpsync( bpio );
414            bpforward( bpio, skipby );
415            resumemovie( doloop );
416            bpconsume1( bpio );
417            pausemovie();
418            break;
419
420        case ',': case '>':
421            bpstop( bpio );
422            bpsync( bpio );
423            bpforward( bpio, -skipby );
424            resumemovie( doloop );
425            bpconsume1( bpio );
426            pausemovie();
427            break;
428
429        case '-':
430            hasnum = -1;
431            isdigit = 1;
432            break;
433
434        case 'n':
435            if(hasnum)
436                curplay = getval(0) - 1;
437            playlistadvance( 1 );
438            break;
439
440        case 'N':
441            playlistadvance( -1 );
442            break;
443
444        case 'P':
445            preloadms = getval( 500 );
446            break;
447
448        case 'f':
449            playfwd = 1;
450            bpforward( bpio, playfwd * skipby );
451            bpsync( bpio );
452            resumemovie( doloop );
453            break;
454
455        case 'b':
456            playfwd = -1;
457            bpforward( bpio, playfwd * skipby );
458            bpsync( bpio );
459            resumemovie( doloop );
460            break;
461
462        case 'l':
463            doloop = hasnum ? val : !doloop;
464            if(doloop != 0)
465                playfwd = doloop;
466            pausemovie();
467            resumemovie( doloop );
468            break;
469
470        case 'R':
471            relshift = getval( relshift+1 );
472                // glutPostRedisplay();
473            if(verbose>=2) printf("relshift %d\n", relshift);
474            break;
475
476        case 'L':
477            relshift = -getval( -(relshift-1) );
478                // glutPostRedisplay();
479            if(verbose>=2) printf("relshift %d\n", relshift);
480            break;
481
482
483        case 'z':
484            playfwd = 1;
485            skipby = 1;
486            bpforward( bpio, playfwd * skipby );
487            bpsync( bpio );
488            startmovie( doloop );       /* schedule first frame */
489            pausemovie();
490            break;
491
492        case 'v':
493            verbose = getval( !verbose );
494            break;
495
496        case 'g': {
497            int frameno = getval(0);
498            int nframes = mvlist[curplay].nframes;
499            if(frameno >= nframes-1)
500                frameno = nframes-1;
501            else if(frameno < 0)
502                frameno = 0;
503
504            bpseek( bpio, bpstartpos( bpio ) + frameno * (off_t) bpio->bufsize );
505            bpsync( bpio );
506            resumemovie( doloop );
507            bpawaitone( bpio );
508            pausemovie();
509            }
510            break;
511
512        case '0': case '1': case '2': case '3': case '4':
513        case '5': case '6': case '7': case '8': case '9':
514            val = val*10 + key - '0';
515            hasnum = 1;
516            isdigit = 1;
517            break;
518
519
520        case 's': {
521            int rate = getval( defaultratefor(curplay) );
522            framems = (int) ( rate>0 ? 1000.0/rate - msfudge : -rate );
523            }
524            if(verbose>=2)
525                fprintf(stderr, "%d fps -> allot %d ms/frame with 10ms fudge\n", val, framems);
526            break;
527
528        case 't':
529            framems = getval( framems );
530            break;
531
532        case 'S':
533            skipby = getval( 1 );
534            bpforward( bpio, playfwd * skipby );
535            break;
536
537        case '=': {
538            int frameno = ( bptell( bpio ) - bpstartpos( bpio ) ) / bpincrpos( bpio );
539            float fps = accumdt==0 ? 0 : 1000 * accumweight / accumdt;
540            fprintf(stderr, "frame %04d   %5.1f fps\n", frameno, fps);
541        }
542            break;
543
544        case 'h':
545            fprintf(stderr, "bplay keyboard commands:\n\
546  <NNN>s   aim for NNN frames/sec\n\
547  <NNN>S   skip -- show every NNN'th frame\n\
548  <NNN>g   go to NNN'th frame and pause (first = 0)\n\
549   .       one frame forward\n\
550   ,       one frame backward\n\
551   f       run forward\n\
552   b       run backward\n\
553   v       toggle verbose (on-screen framenumber & fps counter)\n\
554   p       pause\n\
555   l       toggle loop/stop-at-end\n\
556  SPACE    toggle run/pause\n\
557  HOME     go to beginning of movie and play (like \"0gf\")\n");
558            break;
559
560
561    }
562    if(!isdigit) {
563        if(verbose>=2) {
564            if(hasnum)  printf("\"%d%c\"\n", getval(0), key);
565            else        printf("\"%c\"", key);
566        }
567        val = hasnum = 0;
568    }
569}
570
571void swab32( void *ap, int nbytes )
572{
573    unsigned int *p = (unsigned int *)ap;
574    while((nbytes -= 4) >= 0) {
575        unsigned int v = *p;
576        *p++ = ((v>>24)&0xFF) | ((v>>8)&0xFF00) | ((v&0xFF00)<<8) | ((v&0xFF)<<24);
577    }
578}
579
580void swabbpmv( bpmvhead_t *bpmv )
581{
582    swab32( bpmv, (char *)&bpmv->extfname - (char *)bpmv );
583
584        /* bpmv->start is a 64-bit quantity and needs its words swapped */
585    bpmv->start = ((bpmv->start & 0xFFFFFFFFLL) << 32)
586                | ((bpmv->start >> 32) & 0xFFFFFFFFLL);
587}
588
589
590int openmovie( bpio_t *bpio, char *fname, bpmvhead_t *bpmv )
591{
592    int fd;
593    int n;
594    bpmvhead_t head;
595
596    if(fname == NULL)
597        return -1;
598
599    fd = open(fname, O_RDONLY);
600
601    if(fd < 0) {
602        fprintf(stderr, "%s: %s: can't open: %s\n",
603                prog, fname, strerror(errno));
604        return -1;
605    }
606
607    n = read( fd, &head, sizeof(head) );
608    if(n <= &head.extfname[0] - (char *)&head) {
609        fprintf(stderr, "%s: %s: can't read header: %s\n",
610                prog, fname, strerror(errno));
611        return -1;
612    }
613
614    if(head.magic != BPMV3_MAGIC)
615        swabbpmv( &head );
616    if(head.magic != BPMV3_MAGIC) {
617        fprintf(stderr, "%s: %s doesn't look like a bpmovie file (as made by img2bpmv).\n",
618                prog, fname);
619        return -2;
620    }
621
622    close(fd);
623
624        /* OK then. */
625
626    newtex = 1;
627
628    if(bpio->nfillers == 0)
629        bpinit( bpio, nfillers, head.imagestride, readsize, nbufseach );
630
631    if(head.flags & BPF_EXTDATA) {
632        if(bpopen( bpio, head.extfname ) < 0) {
633            fprintf(stderr, "%s: %s refers to movie data in \"%s\": %s\n",
634                    prog, fname, head.extfname, strerror(errno));
635            return -1;
636        }
637    } else {
638        if(bpopen( bpio, fname ) < 0)
639            return -1;
640    }
641
642    if(bpmv)
643        *bpmv = head;
644
645    if(head.flags & BPF_EXTDATA) {
646        off_t end = head.start + (long long)head.imagestride * (long long)head.nframes;
647        bprange( bpio, head.start, end );
648    } else {
649        bprange( bpio, head.start, -1LL );
650    }
651    bpseek( bpio, head.start );
652    bpsync( bpio );
653
654    return head.nframes;
655}
656
657void draweye( bpmvhead_t *bpmv, unsigned int *txs, unsigned char *tilebuf,
658              float scl, float imxsz, float xoff, float yoff, int x0, int x1, float *xagain )
659{
660        //struct txcodes *txc = &txcode[ bpmv->format ];
661    int i,j,k, ii;
662
663    for(i = k = 0; i < bpmv->nytile; i++) {
664        for(j = x0; j < x1; j++, k++) {
665
666            float xx0 = xoff + scl * j * bpmv->xtile;
667            float xx1 = xoff + scl * (j+1) * bpmv->xtile;
668            float yy0 = yoff + scl * i * bpmv->ytile;
669            float yy1 = yoff + scl * (i+1) * bpmv->ytile;
670
671                /*
672                  fprintf(stderr, "%d %d %d %d - stride %d %d %d\n",
673                  j * bpmv->xtile,
674                  (j+1) * bpmv->xtile,
675                  i * bpmv->ytile,
676                  (i+1) * bpmv->ytile,
677                  bpmv->xtilestride,
678                  bpmv->ytilestride, bpmv->tilerowstride);
679                */
680
681            unsigned char *ptr = tilebuf + j*bpmv->xtilestride + i*bpmv->ytilestride;
682            unsigned char *dst = rgbBuffer + int(i*bpmv->xtile*x1*bpmv->ytile*pixelSize) + int(j*bpmv->xtile*pixelSize);
683            for (ii=0;ii<bpmv->ytile;ii++)
684            {
685                memcpy(dst, ptr, int(bpmv->xtile * pixelSize));
686                dst += int(bpmv->xtile * x1 * pixelSize);
687                ptr += int(bpmv->xtile * pixelSize);
688            }
689
690
691                //glBindTexture( GL_TEXTURE_2D, txs[k] );
692
693            if (newtex) {
694
695/*                 glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); */
696/*                 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); */
697/*                 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); */
698
699/*                 glTexImage2D( GL_TEXTURE_2D, 0, */
700/*                               txc->internalfmt, bpmv->xtile, bpmv->ytile, 0, */
701/*                               txc->format, txc->type,  */
702/*                               tilebuf + j*bpmv->xtilestride + i*bpmv->ytilestride ); */
703            } else {
704/*                 glTexSubImage2D( GL_TEXTURE_2D, 0,  0,0, */
705/*                                  bpmv->xtile, bpmv->ytile, txc->format, txc->type, */
706/*                                  tilebuf + j*bpmv->xtilestride + i*bpmv->ytilestride ); */
707
708            }
709
710/*             glBegin( GL_QUADS ); */
711
712/*             glTexCoord2f( 0, 0 ); */
713/*             glVertex3f( xx0, yy0, 0 ); */
714
715/*             glTexCoord2f( 0, 1 ); */
716/*             glVertex3f( xx0, yy1, 0 ); */
717
718/*             glTexCoord2f( 1, 1 ); */
719/*             glVertex3f( xx1, yy1, 0 ); */
720
721/*             glTexCoord2f( 1, 0 ); */
722/*             glVertex3f( xx1, yy0, 0 ); */
723
724                /* If it's a mono movie and we're in stereo,
725                 * we need to draw this tile twice.
726                 */
727            if(xagain != NULL) {
728/*                 glTexCoord2f( 0, 0 ); */
729/*                 glVertex3f( xx0 + *xagain, yy0, 0 ); */
730
731/*                 glTexCoord2f( 0, 1 ); */
732/*                 glVertex3f( xx0 + *xagain, yy1, 0 ); */
733
734/*                 glTexCoord2f( 1, 1 ); */
735/*                 glVertex3f( xx1 + *xagain, yy1, 0 ); */
736
737/*                 glTexCoord2f( 1, 0 ); */
738/*                 glVertex3f( xx1 + *xagain, yy0, 0 ); */
739            }
740
741/*             glEnd(); */
742
743            {
744/*                 GLuint e = glGetError(); */
745/*                 if(e != 0) fprintf(stderr, "E%d ", e); */
746            }
747        }
748    }
749
750#if 0
751    static int count = 1;
752    char fn[256];
753    sprintf(fn, "out%d.raw", count++);
754    FILE *ff = fopen(fn, "w+");
755    fwrite(rgbBuffer, 1, x1*bpmv->xtile*bpmv->nytile*bpmv->ytile*3, ff);
756    fclose(ff);
757#else
758
759    sageInf.swapBuffer();
760    rgbBuffer = (unsigned char *)sageInf.getBuffer();
761
762#endif
763}
764
765void redraw()
766{
767    static unsigned int *txs;
768    static int ntxs = 0;
769
770    bpmvhead_t *bpmv = &mvlist[curplay];
771    float xscl, yscl, scl, eyex, imxsz, xoff, yoff;
772    float xright;
773
774    unsigned char *tilebuf;
775    int now;
776
777    float dt, decay;
778
779    tilebuf = bpcurbuf( &playlist[curplay] );
780
781    if(tilebuf == NULL) {
782/*         glClearColor( 0, 0, 0.3, 1 ); */
783/*         glClear( GL_COLOR_BUFFER_BIT ); */
784/*         glutSwapBuffers(); */
785        return;
786    }
787
788        /* fprintf(stderr, "<%d:%d> ", playlist[curplay].drain, *(int *)tilebuf); */
789
790    if(playlist[curplay].bufsize != bpmv->imagestride) {
791            /* I/O mismatch */
792/*         glClearColor( 0.5, 0, 0, 1 ); */
793/*         glClear( GL_COLOR_BUFFER_BIT ); */
794/*         glutSwapBuffers(); */
795        return;
796    }
797
798    if(verbose < 4) {
799/*         glClearColor( 0, 0, 0, 1 ); */
800/*         if(stereo != QUADBUFFERED) */
801/*             glClear( GL_COLOR_BUFFER_BIT ); */
802    }
803
804/*     glMatrixMode( GL_MODELVIEW ); */
805/*     glLoadIdentity(); */
806
807        /* OK, use textures from current bpio buffer */
808
809    if(bpmv->nxtile * bpmv->nytile != ntxs) {
810        if(ntxs > 0) {
811                //glDeleteTextures( ntxs, txs );
812            free( txs );
813        }
814
815        ntxs = bpmv->nxtile * bpmv->nytile;
816        txs = (unsigned int *) malloc( ntxs * sizeof(unsigned int) );
817            //glGenTextures( ntxs, txs );
818        newtex = 1;
819    }
820
821        // glEnable( GL_TEXTURE_2D );
822
823        /*
824         * How big should this image be drawn?
825         * Scale to fit the available area, centered.
826         * If image is stereo and we're in crosseyed-stereo mode,
827         * translate to keep center of image on center of display.
828         */
829
830    eyex = (stereo==CROSSEYED) ? winx/2 : winx;
831    imxsz = (bpmv->flags&BPF_STEREO) ? bpmv->xsize/2 : bpmv->xsize;
832    xscl = eyex / (float)imxsz;
833    yscl = winy / (float)bpmv->ysize;
834    scl = (xscl < yscl) ? xscl : yscl;
835    xoff = 0.5f * (eyex - scl * imxsz);
836    yoff = 0.5f * (winy - scl * bpmv->ysize);
837    xright = winx / 2;
838    if(verbose >= 5)
839        fprintf(stderr, "s%.3g xo%g yo%g\n", scl, xoff, yoff);
840
841    if(verbose<4) {
842        int stereomovie = bpmv->flags & BPF_STEREO;
843        float xoff = 0.5f * (eyex - scl * imxsz);
844        float yoff = 0.5f * (winy - scl * bpmv->ysize);
845        int nxtile = bpmv->nxtile;
846
847        switch(stereo) {
848            case MONO:
849                    /*
850                     * If it's a stereo movie and we're in mono mode,
851                     * just display the left half.
852                     */
853                draweye( bpmv, txs, tilebuf, scl, imxsz, xoff, yoff,
854                         0, stereomovie ? nxtile/2 : nxtile, NULL );
855                break;
856
857            case CROSSEYED:
858                if(stereomovie) {
859                    if(relshift == 0) {
860                        draweye( bpmv, txs, tilebuf, scl, imxsz, xoff, yoff, 0, nxtile, NULL );
861                    } else {
862                        draweye( bpmv, txs, tilebuf, scl, imxsz, xoff+relshift, yoff, 0, nxtile/2, NULL );
863                        draweye( bpmv, txs, tilebuf, scl, imxsz, xoff-relshift, yoff, nxtile/2, nxtile, NULL );
864                    }
865                } else {
866                        /* mono movie in stereo mode -- draw twice */
867                    draweye( bpmv, txs, tilebuf, scl, imxsz, xoff, yoff, 0, nxtile, &xright );
868                }
869                break;
870
871            case QUADBUFFERED:
872/*                 if(stereomovie) { */
873/*                     glDrawBuffer( GL_BACK_RIGHT ); */
874/*                     glClear( GL_COLOR_BUFFER_BIT ); */
875/*                     draweye( bpmv, txs, tilebuf, scl, imxsz, xoff-relshift, yoff, nxtile/2, nxtile, NULL ); */
876/*                     glDrawBuffer( GL_BACK_LEFT ); */
877/*                     glClear( GL_COLOR_BUFFER_BIT ); */
878/*                     draweye( bpmv, txs, tilebuf, scl, imxsz, xoff+relshift, yoff, 0, nxtile/2, NULL ); */
879/*                 } else { */
880/*                     glDrawBuffer( GL_BACK ); */
881/*                     glClear( GL_COLOR_BUFFER_BIT ); */
882/*                     draweye( bpmv, txs, tilebuf, scl, imxsz, xoff+relshift, yoff, 0, nxtile, NULL ); */
883/*                 } */
884                break;
885        }
886    }
887
888    if(verbose) {
889        char leg[80];
890        int frameno = *(int *)( tilebuf + bpmv->imagestride - 4); /* img2bmv easter egg */
891        float fps = accumdt==0 ? 0 : 1000 * accumweight / accumdt;
892        bpio_t *bpio = &playlist[curplay];
893        int slotno  = (int) ( (   bptell(bpio) - bpstartpos(bpio) ) / bpincrpos(bpio) );
894        int howmany = (int) ( ( bpendpos(bpio) - bpstartpos(bpio) ) / bpincrpos(bpio) );
895        int i;
896
897        if(frameno > 0 && frameno < 20000)
898            sprintf(leg, "%5d of 0..%-5d  %4.1f fps  frame %04d", slotno, howmany-1, fps, frameno);
899        else
900            sprintf(leg, "%5d of 0..%-5d  %4.1f fps", slotno, howmany-1, fps);
901
902/*         glMatrixMode( GL_MODELVIEW ); */
903/*         glPushMatrix(); */
904
905/*         glTranslatef( 18, winy-20, 0 ); */
906/*         glScalef( 0.1, 0.1, 0.1 ); */
907
908/*         glDisable( GL_TEXTURE_2D ); */
909/*         glColor3f( 1, 1, 0.5 ); */
910
911/*         for(i = 0; leg[i] != '\0'; i++) */
912/*             glutStrokeCharacter( GLUT_STROKE_ROMAN, leg[i] ); */
913
914/*         glPopMatrix(); */
915    }
916
917    if(swapinterval < 0) {
918            /* if we can't depend on glXSwapIntervalSGI() for timing */
919        now = timems();
920    }
921
922        // glutSwapBuffers();
923
924
925    now = timems();
926    dt = (now - lasttimems);
927    decay = exp( - dt / 100 );
928    accumdt =     (accumdt * decay)     + dt;
929    accumweight = (accumweight * decay) + 1;
930
931    lasttimems = now;
932
933    if(verbose >= 2) {
934        bpio_t *bpio = &playlist[curplay];
935        bpbuf_t *bpb = &bpio->bpb[ bpio->drain ];
936        int frameno = tilebuf ? *(int *)( tilebuf + bpmv->imagestride - 4) : -9999; /* img2bmv easter egg */
937        printf("<%02d:%02d~%02d> f%d fw%d r%d dw%d w%d %d..%d  %.0fms\n",
938               bpio->drain,
939               bpb->curpos[bpb->wp] < 0 ? -1 : (int) (bpb->curpos[bpb->wp] / bpio->bufsize),
940               frameno,
941               bpb->filling,
942               bpb->fillwaiting, bpb->rp, bpb->drainwaiting, bpb->wp,
943               (int) (bpb->wrappos / bpio->bufsize),
944               (int) (bpb->eofpos / bpio->bufsize),
945               dt);
946    }
947
948    newtex = 0;
949
950}
951
952void visible( int yes )
953{
954    static int first = 1;
955    if(yes && first)
956        startmovie( doloop );
957    else
958        pausemovie();
959    first = 0;
960}
961
962
963int main(int argc, char *argv[])
964{
965    int c, i;
966    char *hostIP;
967
968    static char Usage[] = "Usage: %s [options] file.bmv ...\n\
969   Plays uncompressed bulk movies in the format created by img2bmv.\n\
970   Options:\n\
971   -f NNN       target NNN frames/sec or -f NNNm milliseconds/frame\n\
972   -t NTHREADS  number of reader threads\n\
973   -r READSIZE  size of each read() in bytes (default = image size)\n\
974   -M msfudge   fudge factor for ms/frame timing estimates (default %d)\n\
975   -v           verbose\n\
976        -n nwID network ID for SAGE\n";
977
978    prog = argv[0];
979
980    signal(SIGINT, catch_quit);
981
982    hostIP = NULL;
983
984    while((c = getopt(argc, argv, "t:b:r:p:S:F:f:P:L:R:vsmqM:c:n:")) != EOF) {
985        switch(c) {
986        case 'c':
987            hostIP = strdup(optarg);
988            break;
989
990        case 't':
991            nfillers = atoi(optarg);
992            if(nfillers < 1) {
993                fprintf(stderr, "%s: Need at least 1 reader thread\n",
994                        prog);
995                exit(1);
996            }
997            break;
998
999        case 'b':
1000            nbufseach = atoi(optarg);
1001            if(nbufseach < 2) {
1002                fprintf(stderr, "%s: Need at least 2 buffers per reader thread\n",
1003                        prog);
1004                exit(1);
1005            }
1006            break;
1007
1008        case 'r':
1009            readsize = atoi(optarg);
1010            if(readsize <= 0 || readsize % getpagesize() != 0) {
1011                fprintf(stderr, "%s: readsize must be a multiple of pagesize (%d)\n",
1012                        prog, getpagesize());
1013                exit(1);
1014            }
1015            break;
1016
1017        case 'p':
1018            port = atoi(optarg);        /* Not implemented yet */
1019            break;
1020
1021        case 'P':
1022            preloadms = atoi(optarg);
1023            break;
1024
1025        case 'M':
1026            msfudge = atoi(optarg);
1027            break;
1028
1029        case 'S':
1030            skipby = atoi(optarg);
1031            if(skipby <= 0) skipby = 1;
1032            break;
1033
1034        case 'F':
1035            rateoverride = 1;   /* and fall into ... */
1036        case 'f':
1037        {
1038            double v = atof(optarg);
1039            if(strchr(optarg, '!'))
1040                rateoverride = 1;
1041            if(strchr(optarg, 'm'))
1042                defaultrate = (int) -v;
1043            else if(v>0)
1044                defaultrate = (int) v;
1045            else {
1046                fprintf(stderr, "%s: -f %s: expected frame rate (frames/sec) or frame time in milliseconds (with \"m\" suffix).\n",
1047                        prog, optarg);
1048                exit(1);
1049            }
1050        }
1051        break;
1052
1053        case 's':
1054            stereo = CROSSEYED;
1055            break;
1056
1057        case 'm':
1058            stereo = MONO;
1059            break;
1060
1061        case 'q':
1062            stereo = QUADBUFFERED;      /* Not implemented yet! */
1063            break;
1064
1065        case 'R':
1066            defaultshift = atoi(optarg);
1067            shiftoverride = (strchr(optarg, '!') != NULL);
1068            break;
1069
1070        case 'L':
1071            defaultshift = -atoi(optarg);
1072            shiftoverride = (strchr(optarg, '!') != NULL);
1073            break;
1074
1075        case 'v':
1076            verbose++;
1077            break;
1078
1079        case 'n':
1080            nwID = atoi(optarg);
1081            break;
1082
1083        default:
1084            fprintf(stderr, "%s: unknown option -%c\n", prog, c);
1085            argc=1;
1086            break;
1087        }
1088    }
1089
1090
1091    nplay = argc - optind;
1092    playlist = (bpio_t *) calloc( nplay, sizeof(bpio_t) );
1093    mvlist = (bpmvhead_t *) calloc( nplay, sizeof(bpmvhead_t) );
1094
1095    int totalframes=0, frames;
1096    for(i = 0; i < nplay; i++) {
1097
1098        frames =  openmovie( &playlist[i], argv[i+optind], &mvlist[i] );
1099        if( frames < 0 ) {
1100            fprintf(stderr, "%s: %s: cannot open: %s\n",
1101                    prog, argv[i+optind], strerror(errno));
1102            exit(1);
1103        }
1104        totalframes +=  frames;
1105    }
1106
1107    if(nplay <= 0 && port == 0) {
1108        fprintf(stderr, Usage, prog, msfudge);
1109        exit(1);
1110    }
1111
1112    // ----------------------------
1113
1114    sageRect hdmovieImageMap;
1115    hdmovieImageMap.left = 0.0;
1116    hdmovieImageMap.right = 1.0;
1117    hdmovieImageMap.bottom = 0.0;
1118    hdmovieImageMap.top = 1.0;
1119
1120    sailConfig scfg;
1121    scfg.init("bitplayer.conf");
1122    scfg.setAppName("bitplayer");
1123    scfg.rank = 0;
1124    scfg.totalFrames = totalframes;
1125    scfg.asyncUpdate = true;
1126
1127    int stereomovie = mvlist[0].flags & BPF_STEREO;
1128    if (stereomovie)
1129        fprintf(stderr, "It's a Stereo Movie !!!\n");
1130
1131    if (stereomovie && (stereo == MONO))
1132        scfg.resX = mvlist[0].nxtile*mvlist[0].xtile/2; // always in mono
1133    else
1134    scfg.resX = mvlist[0].nxtile*mvlist[0].xtile;
1135
1136    scfg.resY = mvlist[0].nytile*mvlist[0].ytile;
1137    scfg.imageMap = hdmovieImageMap;
1138    scfg.rowOrd = BOTTOM_TO_TOP;
1139    scfg.nwID = nwID;
1140
1141    if (stereomovie && (stereo == CROSSEYED)) {
1142        scfg.winWidth *= 2; // display it twice as wide as a mono movie
1143    }
1144
1145    if (mvlist[0].format == RGB565)
1146    {
1147        scfg.pixFmt = PIXFMT_565;
1148        pixelSize = 2;
1149    }
1150    else
1151        if (mvlist[0].format == RGB888)
1152        {
1153            scfg.pixFmt = PIXFMT_888;
1154            pixelSize = 3;
1155        }
1156        else
1157            if (mvlist[0].format == ABGR8888)
1158            {
1159                scfg.pixFmt = PIXFMT_8888;
1160                pixelSize = 4;
1161            }
1162            else
1163                if (mvlist[0].format == COMPRESSDXT1)
1164                {
1165                    scfg.pixFmt = PIXFMT_DXT;
1166                    pixelSize = 0.5;
1167                }
1168                else {
1169                    fprintf(stderr, "format not supported\n");
1170                    exit(1);
1171                }
1172
1173
1174    sageInf.init(scfg);
1175
1176    rgbBuffer = (unsigned char *)sageInf.getBuffer();
1177    memset(rgbBuffer, 0, int(scfg.resX*scfg.resY*pixelSize));
1178
1179    std::cout << "sail initialized :" << scfg.resX << "x" << scfg.resY << std::endl;
1180    // ----------------------------
1181
1182    curplay = -1;
1183    playlistadvance(1);
1184
1185    startmovie( doloop );
1186    sageMessage msg;
1187    int firstClickTime = 0, dir=0;
1188    double fps, t1, t2;
1189
1190    while (1)
1191    {
1192        t1 = sage::getTime();
1193
1194        if(!paused)
1195        {
1196            redraw();
1197            idler();
1198        }
1199
1200        if (sageInf.checkMsg(msg, false) > 0) {
1201            char* data = (char*) msg.getData();
1202
1203            switch (msg.getCode()) {
1204            case APP_QUIT : {
1205                std::cout << "Quit by SAGE" << std::endl;
1206                exit(1);
1207                break;
1208            }
1209            case SAGE_EVT_CLICK: {
1210                float clickX, clickY;
1211                int clickDeviceId, clickButtonId, clickIsDown, clickEvent;
1212
1213                // Parse message
1214                sscanf(data, "%d %f %f %d %d %d",
1215                       &clickDeviceId, &clickX, &clickY,
1216                       &clickButtonId, &clickIsDown, &clickEvent);
1217
1218                if(clickIsDown && clickButtonId==1)
1219                {
1220                    if(!paused)
1221                        pausemovie();
1222                    else
1223                        resumemovie(doloop);
1224                }
1225
1226                // stop the ff or rewind
1227                /*else if(!clickIsDown && clickButtonId==1 && dir!=0)
1228                  {
1229                  dir = 0;
1230                  bpio_t *bpio = &playlist[curplay];
1231                  bpforward( bpio, playfwd * skipby );
1232                  bpsync( bpio );
1233                  resumemovie( doloop );
1234                  }*/
1235
1236                break;
1237            }
1238                /*case SAGE_EVT_PAN: {
1239                  int panDeviceId;
1240                  float panX, panY, panDX, panDY, panDZ;
1241                  sscanf(data, "%d %f %f %f %f %f",
1242                  &panDeviceId, &panX, &panY, &panDX, &panDY, &panDZ);
1243
1244                  bpio_t *bpio = &playlist[curplay];
1245
1246                  // if we weren't ff or rewinding OR the direction changed...
1247                  if (dir == 0 || (panDX < 0 && dir > 0) || (panDX > 0 && dir < 0))
1248                  {
1249                  if(panDX < 0)
1250                  dir = -1;
1251                  else
1252                  dir = 1;
1253
1254                  bpforward( bpio, dir * 15 );
1255                  bpsync( bpio );
1256                  resumemovie( doloop );
1257                  }
1258
1259                  break;
1260                  }*/
1261            }
1262        }
1263
1264        //sage::usleep( (1000/defaultrate)*1000 );
1265        t2 = sage::getTime();
1266        fps = (1000000.0/(t2-t1));
1267        if (fps > defaultrate) {
1268            sage::usleep( (1000000.0/defaultrate) - (t2-t1)  );
1269        }
1270
1271    }
1272
1273
1274    return 0;
1275}
Note: See TracBrowser for help on using the repository browser.