View Single Post
Old 07-16-2012, 07:52 PM   #149
geekmaster
Carpe diem, c'est la vie.
geekmaster ought to be getting tired of karma fortunes by now.geekmaster ought to be getting tired of karma fortunes by now.geekmaster ought to be getting tired of karma fortunes by now.geekmaster ought to be getting tired of karma fortunes by now.geekmaster ought to be getting tired of karma fortunes by now.geekmaster ought to be getting tired of karma fortunes by now.geekmaster ought to be getting tired of karma fortunes by now.geekmaster ought to be getting tired of karma fortunes by now.geekmaster ought to be getting tired of karma fortunes by now.geekmaster ought to be getting tired of karma fortunes by now.geekmaster ought to be getting tired of karma fortunes by now.
 
geekmaster's Avatar
 
Posts: 6,433
Karma: 10773668
Join Date: Nov 2011
Location: Multiverse 6627A
Device: K1 to PW3
Arrow Movies with sound, coming soon to a kindle near you!

This is a "Work In Progress". It is gmplay 2.0 (now with sound). This is just a demo showing multithreaded sound and video. The main thread is where future GUI stuff will go. The video thread exits after the video is done playing. The audio continues indefinately, until killed when the main program exits.

The sound in this demo is synthesized, as described in the "noisy rhythms" demo in the "geekmaster's sound demos" thread).

The next step is to add sound to the .gmv.gz movie files, and replace synthesized sound with recorded sound.

On a K3, if you get periodic sound dropouts, turn down your sound a bit with the Vol- button.
PHP Code:
//====================================================
// gmplay 2.0 - geekmaster's kindle video player
// Copyright (C) 2012 by geekmaster, with MIT license:
// http://www.opensource.org/licenses/mit-license.php
// This version has algorithmically synthesized sound!
//----------------------------------------------------
// Tested on DX,DXG,K3,K4main,K4diags,K5main,K5diags.
//----------------------------------------------------
#include <pthread.h>         // pthread_
#include <asoundlib.h>      // snd_pcm_
#include <sys/ioctl.h>     // ioctl
#include <sys/mman.h>     // mmap, munmap
#include <stdio.h>       // printf
#include <stdlib.h>     // malloc, free
#include <linux/fb.h>  // screeninfo
#include <sys/time.h> // gettimeofday
#include <unistd.h>  // usleep
#include <string.h> // memset, memcpy
#include <fcntl.h> // open, close, write
#include <time.h> // time
typedef unsigned long u64;
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
u32 __invalid_size_argument_for_IOC// ioctl.h bug fix for tcc
//----- eink definitions from eink_fb.h and mxcfb.h -----
#define EU3 0x46dd
#define EU50 0x4040462e
#define EU51 0x4048462e
struct update_area_t {int x1,y1,x2,y2,which_fx;u8 *buffer;};
struct mxcfb_rect {u32 top,left,width,height;};
struct mxcfb_alt_buffer_data {u32 phys_addr,width,height;
    
struct mxcfb_rect alt_update_region;};
struct mxcfb_update_data {struct mxcfb_rect update_region;
    
u32 waveform_mode,update_mode,update_marker;int temp;uint flags;
    
struct mxcfb_alt_buffer_data alt_buffer_data;};
struct mxcfb_update_data51 {struct mxcfb_rect update_region;
   
u32 waveform_mode,update_mode,update_marker;
   
u32 hist_bw_waveform_mode,hist_gray_waveform_mode;
   
int temp;uint flags;struct mxcfb_alt_buffer_data alt_buffer_data;};
//----- function prototypes -----
void sndplay(void);
void gmplay4(void);
void gmplay8(void);
int getmsec(void);
int gmlib(int);
//----- gmlib global vars -----
enum GMLIB_op {GMLIB_INIT,GMLIB_CLOSE,GMLIB_UPDATE,GMLIB_VSYNC};
snd_pcm_t *hp;     // sound play handle
u8 *fb0=NULL;     // framebuffer pointer
int fdFB=0;      // fb0 file descriptor
int teu=0;      // eink update time
u32 fs=0;      // fb0 stride
u32 MX=0;     // xres (visible)
u32 MY=0;    // yres (visible)
u32 VY=0;   // (VY>MY): mxcfb driver
u8 ppb=0;  // pixels per byte
u32 fc=0// frame counter
#define FBSIZE (600/8*800)
//============================
// sndplay - play sound buffer
// this plays until we kill it
//----------------------------
void sndplay(void) {
    
unsigned char buf[1024]; // play buffer
    
snd_pcm_sframes_t fc;   // frame count
    
unsigned int i,j;
    for (
i=0;;i++) { // forever
        
for (j=0;j<sizeof(buf);j++) buf[j]=(random()&3)*i*350;
        
fc=snd_pcm_writei(hp,buf,sizeof(buf));  // play buffer
        
if (fc<0fc=snd_pcm_recover(hp,fc,0); // error recovery
    
}
}  
//==================================
// gmplay4 - play video on 4-bit fb0
//----------------------------------
void gmplay4(void) {
    
u32 i,x,y,b,p,off=(MY/2-400)*fs+MX/4-150,fbsize=FBSIZEu8 fbt[FBSIZE];
    while (
fread(fbt,fbsize,1,stdin)) { teu+=130// teu: next update time
        
if (getmsec()>teu+1000) continue; // drop frame if > 1 sec behind
        
gmlib(GMLIB_VSYNC); // wait for fb0 ready
        
for (y=0;y<800;y++) for (x=0;x<600;x+=8) {
            
b=fbt[600/8*y+x/8]; i=y*fs+x/2+off;
            
p=(b&1)*240b>>=1fb0[i]=p|(b&1)*15b>>=1;
            
p=(b&1)*240b>>=1fb0[i+1]=p|(b&1)*15b>>=1;
            
p=(b&1)*240b>>=1fb0[i+2]=p|(b&1)*15b>>=1;
            
p=(b&1)*240b>>=1fb0[i+3]=p|(b&1)*15;
        } 
fc++; gmlib(GMLIB_UPDATE);
    }
}
//==================================
// gmplay8 - play video on 8-bit fb0
//----------------------------------
void gmplay8(void) {
    
u32 i,x,y,b,fbsize=FBSIZEu8 fbt[FBSIZE];
    while (
fread(fbt,fbsize,1,stdin)) { teu+=130// teu: next update time
        
if (getmsec()>teu+1000) continue; // drop frame if > 1 sec behind
        
gmlib(GMLIB_VSYNC); // wait for fb0 ready
        
for (y=0;y<800;y++) for (x=0;x<600;x+=8) {
            
b=fbt[600/8*y+x/8]; i=y*fs+x;
            
fb0[i]=(b&1)*255b>>=1fb0[i+1]=(b&1)*255b>>=1;
            
fb0[i+2]=(b&1)*255b>>=1fb0[i+3]=(b&1)*255b>>=1;
            
fb0[i+4]=(b&1)*255b>>=1fb0[i+5]=(b&1)*255b>>=1;
            
fb0[i+6]=(b&1)*255b>>=1fb0[i+7]=(b&1)*255;
        } 
fc++; gmlib(GMLIB_UPDATE);
    }
}
//====================================
// gmlib - geekmaster function library
// op (init, update, vsync, close)
//------------------------------------
int gmlib(int op) {
    static 
struct update_area_t ua={0,0,600,800,21,NULL};
    static 
struct mxcfb_update_data ur={
        {
0,0,600,800},257,0,1,0x1001,0,{0,0,0,{0,0,0,0}}};
    static 
struct mxcfb_update_data51 ur51={
        {
0,0,600,800},257,0,1,0,0,0x1001,0,{0,0,0,{0,0,0,0}}};
    static 
int eupcode; static void *eupdata=NULL;
    
struct fb_var_screeninfo screeninfo;
    if (
GMLIB_INIT==op) { teu=getmsec(); fdFB=open("/dev/fb0",O_RDWR);
        
snd_pcm_open(&hp,"default",SND_PCM_STREAM_PLAYBACK,0);
        
snd_pcm_set_params(hp,SND_PCM_FORMAT_U8,
            
SND_PCM_ACCESS_RW_INTERLEAVED,1,8000,1,500000); // 0.5 sec latency
        
ioctl(fdFB,FBIOGET_VSCREENINFO,&screeninfo);
        
ppb=8/screeninfo.bits_per_pixelfs=screeninfo.xres_virtual/ppb;
        
VY=screeninfo.yres_virtualMX=screeninfo.xresMY=screeninfo.yres;
        
ua.x2=MXua.y2=MYur.update_region.width=MXur.update_region.height=MY;
        
fb0=(u8 *)mmap(0,MY*fs,PROT_READ|PROT_WRITE,MAP_SHARED,fdFB,0); // map fb0
        
if (VY>MY) { eupcode=EU50eupdata=&urur.update_mode=0;
            if (
ioctl(fdFB,eupcode,eupdata)<0) { eupcode=EU51eupdata=&ur51; }
        } else { 
eupcode=EU3eupdata=&ua; }
        
system("eips -f -c;eips -c"); sleep(1);
    } else if (
GMLIB_UPDATE==op) {
        if (
ioctl(fdFB,eupcode,eupdata)<0system("eips ''");  // 5.1.0 fallback
    
} else if (GMLIB_VSYNC==op) { while (teu>getmsec()) usleep(1000); // fb0 busy
    
} else if (GMLIB_CLOSE==op) { gmlib(GMLIB_UPDATE); sleep(1); // last screen
        
system("eips -f -c;eips -c"); munmap(fb0,MY*fs); close(fdFB);
        
snd_pcm_close(hp);
    } else { return -
1; }
    return 
0;
}
//====================================
// getmsec - get msec since first call
// (tick counter wraps every 12 days)
//------------------------------------
int getmsec(void) {
    
int tc; static int ts=0struct timeval tv;
    
gettimeofday(&tv,NULL); tc=tv.tv_usec/1000+1000*(0xFFFFF&tv.tv_sec);
    if (
0==tsts=tc;
    return 
tc-ts;
}
//==================
// main - start here
//------------------
int main(void) {
    
pthread_t athread,vthreadint i;
    
gmlib(GMLIB_INIT);
    
pthread_create(&athread,NULL,(void *)sndplay,NULL);
    
pthread_create(&vthread,NULL,(void *)(ppb-1?gmplay4:gmplay8),NULL);
    
pthread_join(vthread,NULL); // wait vthread done
    
i=getmsec()/100printf("%d frames in %0.1f secs = %2.1f FPS\n",
        
fc,(double)i/10.0,(double)fc*10.0/i);
    
gmlib(GMLIB_CLOSE);
    return 
0;


Last edited by geekmaster; 07-17-2012 at 10:31 PM.
geekmaster is offline   Reply With Quote