NPB 1.2 README -------------- Contact information: Paul Rajlich prajlich@ncsa.uiuc.edu http://brighton.ncsa.uiuc.edu/~prajlich/ Intro ----- Welcome to the NCSA Pixel Blaster! NPB, not to be confused with the "National Pork Board", is an easy to use tiled wall movieplayer that works with Chromium or WireGL 1.2.1. It is able to optimize movie playback by distributing and caching textures across the cluster. To enable texture caching with Chromium make sure that you add a dist_texture spu before each render spu. This spu is based on my distributed texture modifications that are part of WireGL 1.2.1. When compiling NPB, make sure that the USE_CHROMIUM flag is set. To enable texture caching with WireGL make sure that you are using WireGL 1.2.1. After installing WireGL 1.2.1, copy the texture.c file in the wgl directory to the pipe_server directory in the WireGL source tree and recompile. When running the pipeservers, make sure that distributed textures are enabled: % pipeserver -dtex By enabling texture caching, NPB will be able to cache textures on the disks across the cluster, allowing fast playback. NPB can still be used in the "simple mode" using regular OpenGL. What's new in NPB 1.2 --------------------- - GUI (optional, implemented with FLTK) - Large image support (pan and zoom images that exceed the display resolution) - Can specify tile resolution (code changes contributed by Frank Summers) - Centering option for letterboxing (e.g. npb -AC ...) - video-in support from capture card (npb -V /dev/video0) Getting started --------------- Edit the Makefile. Set the "WALL_COLS" and "WALL_ROWS" flags to match the dimensions of your wall and "TILE_RES_X" and "TILE_RES_Y" to match the resolution of your tiles. Compile the source (type "make"). Displaying a single image ------------------------- display on client only: npb intro.jpg display on entire wall: wgl npb intro.jpg NOTE: NPB uses the PPM image format. If an image is not a PPM, NPB will attempt to convert it on the fly to a PPM using the "convert" program. NPB can also handle compressed PPM images of the form.ppm.gz or .ppm.Z Playing movies -------------- Playing movies is very simple. Here are the basic steps: 1) Play your movie in "simple mode" to see if the frames are good. Try the example: wgl npb example/small/%04d.jpg 1 1701 2 You can also play the movie locally without WireGL: npb example/small/%04d.jpg 1 1701 2 In this mode, frames are loaded on the client and displayed across the wall. However, given that large frames have to be loaded from disk, broken up, and sent across the network as textures, this mode typically has poor performance and is not scalable. 2) If the movie looks ok and you want to optimize playback, play it in "write mode" to distribute it across the cluster: First, create the directory /usr/local/frames/example/small across the cluster. If you have cexec, that would be: cexec -c "mkdir /usr/local/frames/example/small" NOTE: the wiregl pipeserver on each cluster node should be running from /usr/local/frames. The WireGL texture mods DO NOT allow absolute paths for security reasons (WireGL pipeservers are typically run by root). NOTE: The Chromium dist_texture spu DOES allow absolute paths (Chromium servers are typically not run by root). Now you are ready to distribute the movie: wgl npb -W example/small/%04d.jpg 1 1701 2 This mode is similar to the "simple mode" except that as the movie is playing, frame "chunks" are being cached to disk across the cluster. In future playbacks (step 4), the movie will already be distributed across the cluster, resulting in much better performance than the "simple mode". This solution is also scalable. During this mode, the frame "chunks" may be seperated by blank spaces. This is normal. In fact, this signals that a further optimization is possible and is indeed happening. During final playback (step 3), these gaps will disappear. 3) Now play the movie in "distributed mode" at full speed! wgl npb -D example/small/%04d.jpg 1 1701 2 if it plays too fast :-), you can adjust the rate (fps): wgl npb -D -r 24 example/small/%04d.jpg 1 1701 2 NOTE: npb reads the first full frame on the head node in order to determine the size of the original frames. Because of this, you need to keep the first frame from each movie. To get around this (and to decrease startup time), use the -X option: wgl npb -D -X 2048x1536 -r 24 example/small/%04d.jpg 1 1701 2 4) That's it! From now on, your movie is ready to play in distributed mode at full speed (step 3)! You may want to make a script for each movie so that you don't need to remember the commandline arguments. Displaying Very Large Images ---------------------------- To enable panning and zooming on very large images, use the -P option. For this feature to work properly, each tile will have to cache all of the image data. To accomplish this, make sure that the Chromium or WireGL tilesort is in "broadcast" mode when you do the WRITE step. An alternative is to play the image(s) to a single display node in write mode and then copy the files from that display node to the other display nodes. Of course, make sure that you turn off the "broadcast" flag when running in the DISTRIBUTED mode. Resolution ---------- NPB can display frames of any resolution. However, if the resolution of the frames is higher than the wall resolution, you will want to resize the frames for improved performance. Aspect Ratio ------------ By default, NPB scales the frame (by texturing) to fit the entire wall. To preserve the aspect ratio of the frames, use the -A option: wgl npb -A intro.jpg Of course, this may introduce "letterboxing". Another option is to use a subset of your wall (don't run a wiregl pipesever on each node). Troubleshooting --------------- If movies are not being optimized (distributed) properly. Here are a couple of things to consider: 1) Are your wall dimensions correctly specified? Type "npb" and at the bottom of the output it will tell you what the compiled dimensions are. You can override this with the -S commandline option or you can edit the Makefile and recompile. 2) Do the pipeservers across the cluster have write permission to the directory where you are writing (caching) frame chunks? Does the directory exist across the cluster?! You may want to run the pipeservers as root. NOTE: Each pipeserver caches frame chunks locally based on the fileSpec that was specified on the npb commandline on the client. For security reasons, only relative paths are allowed. As a result, it is good to run the pipeservers from a specific location (ie. /usr/local/frames/). Advanced Topics --------------- During playback, you can hit the 'w' key to see wireframe mode. This will show you how frame "chunks" are being distributed. In general, during the optimized modes (write and distributed) NPB tries to break up your frames into chunks such that there is one chunk per wall tile (up to a limit of 1024x1024 sized chunks). However, you can override this by specifying the frame "chunk" size explicitly using the -T option. In general, you want the "chunk" size to be such that no chunk spans across tiles. If that is the case, NPB can do a further optimization such that each "chunk" will be sent to only one tile. If this is the case, then during the write mode you will see that chunks are "shrunken" such that there are gaps between them. This means that this optimization is happening. During playback, the chunks will be shown at regular size and there will be no gaps. During distributed playback, another optimization is the use of a so-called "prefetch daemon". This daemon was written by Stuart Levy. The daemon is a seperate process running on each node that is reading ahead a frame or two. As a result, frame chunks are cached in the system disk-read buffer. Using the prefetch daemon typically does not improve framerate, but does make the framerate more stable and reduces jitter. Prefetch daemons may already be running across the cluster. NPB communicates with these daemons based on the setting in the NPB_PREFETCH environment variable. However, you can override this setting using the -F commandline option. For a full list of commandline options and their usage, run npb with no commandline arguments. Playlists --------- Playlists allow you to play multiple movies without interruption. To make a playlist, create a text file. Each movie is specified with two lines of text. The first line is the title and the second line is the npb commandline. An example playlist is provided (PLAYLIST-example.txt). NOTE: playlist files must have a .txt filename extension! WireGL modifications -------------------- In case you are curious, here is a brief description of the changes made to WireGL to support NPB: In order to support distributed textures, I made some modifications to WireGL. The idea for this came from an email conversation with Ian Buck of the WireGL team. Essentially, I added two new features to glTexImage2D to support caching of textures across the cluster. The spec for glTexImage2D is: void glTexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels ) Normally, type is one of GL_UNSIGNED_BYTE, GL_BYTE, GL_BITMAP, etc. I added two more options for type that are normally invalid. The two options are GL_TRUE and GL_FALSE. If the type is set to GL_TRUE then the pixels data is interpreted as a filename followed by the texture data. On the unpacking side, the filename is extracted and the texture data is saved to local disk. If the type is set to GL_FALSE then the pixels data is interpreted as a filename only. On the unpacking side, the filename is extracted and the texture is loaded from local disk. With these two simple modifications to WireGL, I was able to write a distributed movieplayer with good performance. Since the new calls to glTexImage2D are invalid in regular OpenGL, they do not interfere with other users of the system. However, I made sure to have modes so that the movieplayer can also be used with regular WireGL or OpenGL.