\input texinfo   @c -*-texinfo-*-
@afourpaper
@setfilename bino.info
@documentlanguage en
@documentencoding UTF-8
@include version.texi
@settitle Bino @value{VERSION}

@copying
This manual was last updated @value{UPDATED} for version
@value{VERSION} of Bino.

Copyright @copyright{} 2011
Martin Lambers (@email{marlam@@marlam.de}),
Stefan Eilemann (@email{eile@@eyescale.ch}),
Frédéric Devernay (@email{Frederic.Devernay@@inrialpes.fr})

@quotation
Copying and distribution of this file and the referenced image files, with or
without modification, are permitted in any medium without royalty provided the
copyright notice and this notice are preserved. These files are offered as-is,
without any warranty.
@end quotation
@end copying

@dircategory Individual utilities
@direntry
* bino: (bino).         A 3D video player with multi-display support.
@end direntry

@finalout
@titlepage
@title Bino
@subtitle A 3D video player with multi-display support.
@subtitle Version @value{VERSION}, @value{UPDATED}
@author The Bino developers
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage

@ifnothtml
@contents
@end ifnothtml

@ifnottex
@node Top
@top Bino
@insertcopying
@end ifnottex

@ifhtml
Table of Contents:
@end ifhtml
@menu
* Overview::
* Invocation::
* Input Layouts::
* Output Techniques::
* File Name Conventions::
* Interactive Control::
* Camera Devices::
* Crosstalk Ghostbusting::
* Advanced Multi Display Support::
@end menu

@node Overview
@chapter Overview

Bino is a 3D video player with multi-display support.

3D videos are more accurately called stereoscopic videos. Such videos have
separate views for the left and right eye and thus allow depth perception
through stereopsis.

All input files are combined into one media source, so you can have video,
audio, and subtitle streams in separate files. The files are decoded with the
@url{http://ffmpeg.org/,FFmpeg}  libraries, so URLs and other special
constructs are supported.

Bino supports a wide variety of stereoscopic input layouts and display
techniques.

@node Invocation
@chapter Invocation

Synopsis:
@code{bino [@var{option}@dots{}] [@var{file}@dots{}]}

@table @samp
@item --help
Print help.
@item --version
Print version.
@item -n
@itemx --no-gui
Do not use the GUI, just play the given input in a plain window using the
parameters given on the command line.
@item -L
@itemx --log-level=@var{LEVEL}
Select log level: @var{debug}, @var{info}, @var{warning}, @var{error}, or
@var{quiet}.
@item --device-type=@var{TYPE}
Type of input device: @var{default}, @var{firewire}, or @var{x11}.
@item --device-frame-size=@var{W}x@var{H}
If the input is a device, request the given frame size, e.g. 640x480.
@item --device-frame-rate=@var{N}/@var{D}
If the input is a device, request the given frame rate, e.g. 25/1.
@item --lirc-config=@var{FILE}
Use the given LIRC configuration file. This option can be used more than once.
@item -v
@itemx --video=@var{STREAM}
Select video stream (1-n, depending on the input).
@item -a
@itemx --audio=@var{STREAM}
Select audio stream (1-n, depending on the input).
@item -s
@itemx --subtitle=@var{STREAM}
Select subtitle stream (1-n, depending on the input).
@item -i
@itemx --input=@var{TYPE}
Select input type. @xref{Input Layouts}.
@item -o
@itemx --output=@var{TYPE}
Select output type. @xref{Output Techniques}.
@item -S
@itemx --swap-eyes
Swap left/right view.
@item -f
@itemx --fullscreen
Fullscreen.
@item --fullscreen-screens=[@var{S0}[,@var{S1}[,@dots{}]]]
Use the listed screens @var{S0}, @dots{}, @var{Sn} in fullscreen mode. Screen
numbers start with 1. If the list is empty, the primary screen will be used
(this is the default).
@item --fullscreen-flip-left
Flip left view vertically when in fullscreen mode.
@item --fullscreen-flop-left
Flop left view horizontally when in fullscreen mode.
@item --fullscreen-flip-right
Flip right view vertically when in fullscreen mode.
@item --fullscreen-flop-right
Flop right view horizontally when in fullscreen mode.
@item -c
@itemx --center
Center window on screen.
@item --subtitle-encoding=@var{ENC}
Set subtitle encoding.
@item --subtitle-font=@var{FONT}
Set subtitle font name.
@item --subtitle-size=@var{N}
Set subtitle font size.
@item --subtitle-scale=@var{S}
Set subtitle scale factor.
@item --subtitle-color=@var{COLOR}
Set subtitle color, in [AA]RRGGBB format.
@item --subtitle-parallax=@var{VAL}
Subtitle parallax adjustment (-1 to +1).
@item -P
@itemx --parallax=@var{VAL}
Parallax adjustment (-1 to +1).
@item -C
@itemx --crosstalk=@var{VAL}
Crosstalk leak level (0 to 1). Comma-separated values for the R,G,B channels.
@item -G
@itemx --ghostbust=@var{VAL}
Amount of crosstalk ghostbusting to apply (0 to 1).
@item -b
@itemx --benchmark
Benchmark mode: no audio, no time synchronization, output of frames-per-second
measurements.
@item -l
@itemx --loop
Loop the input media.
@end table

@node Input Layouts
@chapter Input Layouts

Bino supports the following stereoscopic input layouts:
@table @var
@item mono
Single view (2D).
@item separate-left-right
Left/right view in separate streams, left first.
@item separate-right-left
Left/right view in separate streams, right first.
@item top-bottom
Left view top, right view bottom.
@item top-bottom-half
Left view top, right view bottom, half height.
@item bottom-top
Left view bottom, right view top.
@item bottom-top-half
Left view bottom, right view top, half height.
@item left-right
Left view left, right view right.
@item left-right-half
Left view left, right view right, half width.
@item right-left
Left view right, right view left.
@item right-left-half
Left view right, right view left, half width.
@item even-odd-rows
Left view even rows, right view odd rows.
@item odd-even-rows
Left view odd rows, right view even rows.
@end table

The default is to autodetect the input type from meta data stored in the file.
If this fails, Bino tries to autodetect the input type based on the file name.
@xref{File Name Conventions}.  If that fails, too, Bino guesses based on the
resolution of the input.

@node Output Techniques
@chapter Output Techniques

Bino supports the following stereoscopic display techniques:
@table @var
@item mono-left
Left view only.
@item mono-right
Right view only.
@item top-bottom
Left view top, right view bottom.
@item top-bottom-half
Left view top, right view bottom, half height.
@item left-right
Left view left, right view right.
@item left-right-half
Left view left, right view right, half width.
@item even-odd-rows
Left view even rows, right view odd rows.
@item even-odd-columns
Left view even columns, right view odd columns.
@item checkerboard
Left and right view in checkerboard pattern.
@item hdmi-frame-pack
HDMI frame packing mode (left top, right bottom, plus extra blank lines
separating the two views). This mode is only necessary if you are forcing your
display into the corresponding HDMI 3D mode. A description how to do this on
GNU/Linux can be found in
@url{http://lists.nongnu.org/archive/html/bino-list/2011-03/msg00033.html,this post to the Bino mailing list}.
@item red-cyan-monochrome
Red/cyan anaglyph, monochrome method.
@item red-cyan-half-color
Red/cyan anaglyph, half color method.
@item red-cyan-full-color
Red/cyan anaglyph, full color method.
@item red-cyan-dubois
Red/cyan anaglyph, high-quality Dubois method.
@item green-magenta-monochrome
Green/magenta anaglyph, monochrome method.
@item green-magenta-half-color
Green/magenta anaglyph, half color method.
@item green-magenta-full-color
Green/magenta anaglyph, full color method.
@item green-magenta-dubois
Green/magenta anaglyph, high-quality Dubois method.
@item amber-blue-monochrome
Amber/blue anaglyph, monochrome method.
@item amber-blue-half-color
Amber/blue anaglyph, half color method.
@item amber-blue-full-color
Amber/blue anaglyph, full color method.
@item amber-blue-dubois
Amber/blue anaglyph, high-quality Dubois method.
@item red-green-monochrome
Red/green anaglyph, monochrome method.
@item red-blue-monochrome
Red/blue anaglyph, monochrome method.
@item stereo
OpenGL quad-buffer stereo.
@item equalizer
Multi-display OpenGL via Equalizer with a 2D canvas setup.
@item equalizer-3d
Multi-display OpenGL via Equalizer with a 3D screen setup.
@end table

For stereo input, the default is @var{stereo} if the display supports it,
otherwise @var{red-cyan-dubois}. The default for mono input is @var{mono-left}.

@node File Name Conventions
@chapter File Name Conventions

If the meta data stored in a file does not indicate its stereoscopic layout,
Bino tries to guess it by looking at the last part of the file name before
the file name extension (@file{.ext}).

The following file name forms are recognized:
@table @file
@item *-lr.ext
@var{left-right}
@item *-lrh.ext
@itemx *-lrq.ext
@var{left-right-half}
@item *-rl.ext
@var{right-left}
@item *-rlh.ext
@itemx *-rlq.ext
@var{right-left-half}
@item *-tb.ext
@itemx *-ab.ext
@var{top-bottom}
@item *-tbh.ext
@itemx *-abq.ext
@var{top-bottom-half}
@item *-bt.ext
@itemx *-ba.ext
@var{bottom-top}
@item *-bth.ext
@itemx *-baq.ext
@var{bottom-top-half}
@item *-eo.ext
@itemx *-eoq.ext
@itemx *-3dir.ext
@var{even-odd-rows}
@item *-oe.ext
@itemx *-oeq.ext
@itemx *-3di.ext
@var{odd-even-rows}
@item *-2d.ext
@var{mono}
@end table

@node Interactive Control
@chapter Interactive Control

@section Keyboard Shortcuts

Bino reacts on a number of keyboard shortcuts during playback.

Make sure that the video area has the keyboard focus before using these
shortcuts, e.g. by clicking into it.

The following shortcuts are recognized:
@table @kbd
@item ESC
Leave fullscreen mode, or quit when in window mode.
@item q
Quit.
@item p
@item SPACE
Pause / unpause.
@item f
Toggle fullscreen.
@item c
Center window.
@item e
Swap left/right eye.
@item v
Cycle through available video streams.
@item a
Cycle through available audio streams.
@item a
Cycle through available subtitle streams.
@item 1
@item 2
Adjust contrast.
@item 3
@item 4
Adjust brightness.
@item 5
@item 6
Adjust hue.
@item 7
@item 8
Adjust saturation.
@item <
@item >
Adjust parallax.
@item (
@item )
Adjust ghostbusting.
@item LEFT
@item RIGHT
Seek 10 seconds backward / forward.
@item UP
@item DOWN
Seek 1 minute backward / forward.
@item PAGE UP
@item PAGE DOWN
Seek 10 minutes backward / forward.
@item Mouse click
Seek according to the horizontal click position.
@end table

@section Remote Controls

Bino supports remote controls via @url{http://www.lirc.org/,LIRC}.

Use the client name @samp{bino} in your LIRC configuration. The default LIRC
configuration file usually is @code{~/.lircrc}. You can use the
@samp{--lirc-config} option to use one or more custom LIRC configuration files
instead.

The following commands are available:

@table @samp
@item play
Start playback, or switch of pause mode.
@item pause
When playing, go into pause mode.
@item stop
Stop playback.
@item cycle-video-stream
Cycle through available video streams.
@item cycle-audio-stream
Cycle through available audio streams.
@item cycle-subtitle-stream
Cycle through available subtitle streams.
@item toggle-stereo-mode-swap
Swap left/right eye.
@item toggle-fullscreen
Toggle fullscreen.
@item center
Center window.
@item adjust-contrast @var{delta}
Adjust contrast by adding @var{delta}, e.g. -0.05 or +0.05.
@item adjust-brightness @var{delta}
Adjust brightness by adding @var{delta}, e.g. -0.05 or +0.05.
@item adjust-hue @var{delta}
Adjust hue by adding @var{delta}, e.g. -0.05 or +0.05.
@item adjust-saturation @var{delta}
Adjust saturation by adding @var{delta}, e.g. -0.05 or +0.05.
@item adjust-parallax @var{delta}
Adjust parallax by adding @var{delta}, e.g. -0.01 or +0.01.
@item adjust-subtitle-parallax @var{delta}
Adjust contrast by adding @var{delta}, e.g. -0.01 or +0.01.
@item seek @var{delta}
Seek by the given number of seconds relative to the current position.  For
example -60.0 seeks backwards one minute, and +60.0 seeks forward one minute.
@item set-pos @var{pos}
Seek by setting an absolute position in the stream, with @var{pos} between 0 and
1. For example, to seek to the middle of the video, use 0.5.
@end table

Example LIRC configuration file excerpt:
@example
begin
  remote = ...
  button = ...
  prog   = bino
  config = adjust-brightness +0.05
end
@end example


@node Camera Devices
@chapter Camera Devices

Bino supports the following types of camera devices:
@itemize
@item @var{default}: the system-specific default device type.@*
This is video4linux2 on GNU/Linux, bktr on BSD and Mac OS, and VfW on Windows.
This should work for all webcams and similar camera devices.
@item @var{firewire}: Firewire devices.
@item @var{x11}: X11-grabber pseudo devices.@*
This device type allows to capture part of an X11 screen as a video. It
requires the user to select a specific frame size and frame rate. The device
name is of the form
@code{[@var{hostname}]:@var{display}.@var{screen}[+@var{x},@var{y}]}. For example,
@code{smith:0.0+160,120} would capture from X11 display @code{:0.0} on host
@code{smith}, starting at position @code{160,120}.
@end itemize

Note: for @var{firewire} and @var{x11} devices to work, your FFmpeg libraries
must have @var{libdc1394} and @var{x11grab} enabled, which is not the default.

@node Crosstalk Ghostbusting
@chapter Crosstalk Ghostbusting

Many stereoscopic display devices suffer from crosstalk between the left and
right view. This results in ghosting artifacts that can degrade the viewing
quality, depending on the video content.

Bino can optionally reduce the ghosting artifacts. For this, it needs two know
@enumerate
@item the amount of crosstalk of your display device and
@item the amount of ghostbusting that is adequate for the video you want to
watch.
@end enumerate

Please note that ghostbusting does not work with anaglyph glasses.

To measure the display crosstalk, do the following:

@enumerate
@item Display the @uref{gamma-pattern-tb.png,@code{gamma-pattern-tb.png}} image
and correct the display gamma settings according to the included instructions.
You need to have correct gamma settings before measuring crosstalk.
@item Display the
@uref{crosstalk-pattern-tb.png,@code{crosstalk-pattern-tb.png}} image and
determine the crosstalk levels using the included instructions.
@end enumerate

You now have three crosstalk values for the red, green, and blue channels. You
can now tell Bino about this using the @option{--crosstalk} option. For example,
if you have measured 8% of crosstalk for red, 12% for green, and 10% for blue,
use
@example
$ bino --crosstalk 0.08,0.12,0.10
@end example

Once you know the crosstalk levels of your display device, you can set the
amount of ghostbusting that Bino should apply using the @option{--ghostbust}
option. This will vary depending on the content you want to watch. Movies with
very dark scenes should be viewed with at least 50% ghostbusting
(@option{--ghostbust 0.5}), whereas overall bright movies, where crosstalk is
less disturbing, could be viewed with a lower level (e.g.
@option{--ghostbust 0.1}).

To check if you crosstalk calibration is correct, display the crosstalk patterns
with full ghostbusting, like this:
@example
$ bino --crosstalk 0.08,0.12,0.10 --ghostbust 1.0 crosstalk-pattern-tb.png
@end example
The remaining crosstalk should optimally be 0%.

@node Advanced Multi Display Support
@chapter Advanced Multi Display Support

Bino supports distributed multi-display output via the Equalizer framework.

This is how it works:

@section Building Bino with Equalizer Support

First, install Equalizer 0.9.3 (also known as 1.0-beta) or later. See
@url{http://www.equalizergraphics.com/}.  Verify that it works by running the
included eqHello example.

Then, build Bino with Equalizer support. The output of configure should contain
the following line:
@example
Equalizer: yes
@end example

Now you need an Equalizer configuration file for your display setup.

@section Configuring Equalizer and Starting Bino

Bino needs a two-dimensional Equalizer canvas (= combined screen area),
subdivided into segments (= single display areas). For example, if you have
two projectors that project onto a 2m x 1m screen side-by-side, then your
canvas is 2m x 1m large, and you have two segments: the first segment fills
the left half of the canvas, and the second segment fills the right half.

Next, Equalizer needs to know how to render into each segment. For this
purpose, you define several hierarchical objects: nodes (= processes, possibly
on different systems), pipes (= graphics cards), windows (= output windows
with OpenGL contexts), and channels (= parts of windows). The video output
happens at the channel level: each channel is assigned to one segment of the
canvas. Most probably you just have one fullscreen window per pipe, and a
single output channel per window.

Note that one node is special: the application node, which is the node that
you initially start (the other nodes are started automatically by Equalizer).
The application node is called 'appNode' in the Equalizer configuration, and
Bino will play audio only on the application node. All video output is then
synchronized to this audio output.

Once you have your configuration file (examples are given below), you can
check if it works correctly using the @command{eqHello} example:
@example
$ eqHello --eq-config configuration.eqc
@end example

Once you made sure that this works, you can start Bino using this command:
@example
$ bino -o equalizer --eq-config configuration.eqc video.mp4
@end example

Note that all your nodes need access to the video file using the same name, so
a shared filesystem is helpful if you use multiple systems.

To play live video from a webcam or TV card, you can set up a streaming server
using ffserver (part of FFmpeg) or vlc, and then give the appropriate URL to
Bino. You can use multicast to stream the video to multiple systems
efficiently.

The output mode @option{-o equalizer-3d} allows to configure non-planar projections.
Bino projects the video onto a virtual screen in 3D space. The screen is
located in the distance of the biggest front-facing segment, and sized to fill
the wall optimally. By configuring the output segments accordingly, various
advanced display configurations can be used, e.g. displays rotated around the
Z axis by an arbitrary angle or non-planar screens.

@section Example Configurations

@subsection Simple 2D video output

In this example, you have a 2m x 1m screen and two projectors: one for the
left half of the screen, and one for the right half. The two projectors are
connected to two graphics cards on the same system.

In this situation, you have one node with two pipes, and each pipe has a
fullscreen window with a single output channel. The first output channel is
assigned to the left segment, and the second output channel is assigned to the
right channel. The resulting configuration looks like this:

@example
@verbatim
server
{
    config
    {
        appNode
        {
            pipe { device 0 window { attributes { hint_fullscreen ON } channel { name "left" }}}
            pipe { device 1 window { attributes { hint_fullscreen ON } channel { name "right" }}}
        }
        observer {}
        layout { view { observer 0 }}
        canvas
        {
            layout 0
            wall
            {
                bottom_left  [ 0.0  0.0 -1 ]
                bottom_right [ 2.0  0.0 -1 ]
                top_left     [ 0.0  1.0 -1 ]
            }
            segment { channel "left" viewport [ 0.0 0.0 0.5 1.0 ] }
            segment { channel "right" viewport [ 0.5 0.0 0.5 1.0 ] }
        }
        compound
        {
            compound { channel ( view 0 segment 0 ) swapbarrier {} }
            compound { channel ( view 0 segment 1 ) swapbarrier {} }
        }
    }
}
@end verbatim
@end example

@subsection 3D video output across multiple systems

In the following example, you have a 4m x 3m screen for 3D projection via
passive stereo (e.g. polarization). You have two systems, "render1" and
"render2", each equipped with two graphics cards. The two cards on "render1"
generate two images for the left half of the screen: one for the left eye view
and one for the right eye view. The two cards on "render2" generate left and
right view for the right half of the screen. Additionally, you have a system
called "master" which has a sound card and should display a small control
window.

This setup is very similar to the situation shown in
@uref{multi-display-vrlab.jpg,@code{multi-display-vrlab.jpg}}.

The configuration looks like this:

@example
@verbatim
server
{
    connection { hostname "master" }
    config
    {
        appNode
        {
            connection { hostname "master" }
            pipe { window { viewport [ 100 100 400 300 ] channel { name "control" }}}
        }
        node
        {
            connection { hostname "render1" }
            pipe { device 0 window { attributes { hint_fullscreen ON } channel { name "render1left" }}}
            pipe { device 1 window { attributes { hint_fullscreen ON } channel { name "render1right" }}}
        }
        node
        {
            connection { hostname "render2" }
            pipe { device 0 window { attributes { hint_fullscreen ON } channel { name "render2left" }}}
            pipe { device 1 window { attributes { hint_fullscreen ON } channel { name "render2right" }}}
        }
        observer {}
        layout { view { observer 0 }}
        canvas
        {
            layout 0
            wall
            {
                bottom_left  [ 0.0 0.0 -1 ]
                bottom_right [ 4.0 0.0 -1 ]
                top_left     [ 0.0 3.0 -1 ]
            }
            segment { channel "render1left"  viewport [ 0.0 0.0 0.5 1.0 ] }
            segment { channel "render1right" viewport [ 0.0 0.0 0.5 1.0 ] }
            segment { channel "render2left"  viewport [ 0.5 0.0 0.5 1.0 ] }
            segment { channel "render2right" viewport [ 0.5 0.0 0.5 1.0 ] }
            segment { channel "control"      viewport [ 0.0 0.0 1.0 1.0 ] }
        }
        compound
        {
            compound { eye [ LEFT  ] channel ( view 0 segment 0 ) swapbarrier {} }
            compound { eye [ RIGHT ] channel ( view 0 segment 1 ) swapbarrier {} }
            compound { eye [ LEFT  ] channel ( view 0 segment 2 ) swapbarrier {} }
            compound { eye [ RIGHT ] channel ( view 0 segment 3 ) swapbarrier {} }
            compound {               channel ( view 0 segment 4 ) swapbarrier {} }
        }
    }
}
@end verbatim
@end example

@subsection Non-planar Displays

The @option{-o equalizer-3d} mode allows to set up arbitrary-oriented screens
using either the wall-based or projection-based 3D frustum descriptions.

In this example we set up two 16:10 displays side-by-side which have been
rotated around their Z axis by 1.3 degrees radians (~74 degrees).  The image
@uref{multi-display-rotated.jpg,@code{multi-display-rotated.jpg}} illustrates
this setup. Other setups include distortion-correct projection for curved
screens, or arbitrarily-placed screens in a 3D space.

First, we rotate a normally-aligned screen by 1.3 degrees and output the
result:

@example
eq::Matrix4f matrix(eq::Matrix4f::IDENTITY);
matrix.rotate(1.3f, eq::Vector3f::FORWARD);
wall.bottomLeft = matrix * wall.bottomLeft;
wall.bottomRight = matrix * wall.bottomRight;
wall.topLeft = matrix * wall.topLeft;
std::cout << wall << std::endl;
@end example

yields a rotated screen centered on the origin:

@example
bottom_left  [   -0.69578     0.6371         -1 ]
bottom_right [   -0.26778    -0.9046         -1 ]
top_left     [    0.26778     0.9046         -1 ]
@end example

This screen has to be moved along the X-axis for the left and right screen by
0.5195m, which places the edges of the screen on the origin. The resulting
wall descriptions are used for the left and right segment, as shown in the
configuration below.

The configuration references two GPUs full-screen output. By changing the node
resource section, the outputs may be mapped to two computers. When disabling
the fullscreen mode and setting 'device 0' for the second pipe, two windows
simulate this setup on a single machine.

@example
@verbatim
global
{
    EQ_WINDOW_IATTR_HINT_FULLSCREEN ON
}

server
{
    config
    {
        appNode
        {
            pipe
            {
                device 0
                window
                {
                    viewport [ .215 .5 .4 .4 ]
                    channel { name "channel1" }
                }
            }
            pipe
            {
                device 1
                window
                {
                    viewport [ .285 .1 .4 .4 ]
                    attributes{ hint_drawable window }
                    channel { name "channel2" }
                }
            }
        }

        layout { view{ }}
        canvas
        {
            layout   0

            segment
            {
                channel  "channel1"
                wall
                {
                    bottom_left  [   -1.21528     0.6371         -1 ]
                    bottom_right [   -0.78728    -0.9046         -1 ]
                    top_left     [   -0.25172     0.9046         -1 ]
                }
            }
            segment
            {
                channel  "channel2"
                wall
                {
                    bottom_left  [   -0.17628     0.6371         -1 ]
                    bottom_right [    0.25172    -0.9046         -1 ]
                    top_left     [    0.78728     0.9046         -1 ]
                }
            }
        }

        compound
        {
            compound
            {
                channel ( segment 0 )
                swapbarrier{}
            }
            compound
            {
                channel ( segment 1 )
                swapbarrier{}
            }
        }
    }
}
@end verbatim
@end example

@bye
