MlRawViewer 1.3.3 (CDNG/MLV/RAW Viewer & Encoder, Linux/Mac/Win)

Started by baldand, December 09, 2013, 06:10:19 PM

Previous topic - Next topic

0 Members and 4 Guests are viewing this topic.

baldand



MlRawViewer 1.3.3



MlRawViewer is a cross-platform viewer for raw video files produced by Magic Lantern.

It supports both the original RAW format, and the newer MLV (RAW v2.0) format in both single and multi-file versions.

It also supports sound playback from embedded MLV_SND audio, or external WAV files.

It also supports playback of directories containing sequences of "CinemaDNG" .DNG files, as produced by mlv_dump or raw2cdng.

It also supports 2 x 1D and 1 x 3D LUT for display and ProRes export.

Features/usage

       
  • RAW, MLV and CinemaDNG playback in real-time (if you have fast file read and modest GPU), single and multi-file
  • Progress bar and timestamp overlay. Click to jump in file
  • Pause playback using SPACE key or play/pause icon.
  • Toggle fullscreen and windowed mode using TAB key or fullscreen icon
  • Jump to next/previous RAW or MLV files in same directory as current file using K/J keys.
  • Drag a RAW/MLV/DNG file onto the window to view that file. Drag a WAV file to play with the current video.
  • Step forward and backward through frames by one second (LEFT/RIGHT cursor keys) or one frame (,/. keys) while playing or paused
  • Brightness control while playing using UP/DOWN cursor keys. Or click/drag in brightness box.
  • Fast GPU Bilinear demosaicing for playback
  • High-quality (but slow) CPU demosaicing (AMaZE) when paused or enabled (Q key)
  • Export current marked range with audio with E key pr PLUS(+) icon.
  • Control start or pause procesing of export queue with Y key or red circle icon.
  • Choose export folder with W key.
  • Choose MOV (ProRes) or DNG sequence as export type using D key.
  • White Balance adjustments. Keys: 1=WhiteFluoro,2=Daylight,3=Cloudy, 4/7=Red down/up, 5/8=Green down/up, 6/9=Blue down/up. Or click/drag in Red/Blue box.
  • RGB Histogram option
  • sRGB colour output
  • sRGB or Rec.709 gamma, global (HDR) tone mapping, Linear, Log8, S-Log, S-log2, Log-C, C-Log toggle with "T" key or mapping icon
  • Drop-frame+audio and non-drop-frame modes. Toggle with "F" key
  • Slide audio sync -0.5,-0.05,+0.05,+0.5 seconds with V/B/N/M keys.
  • Mark IN/OUT, Jump to PREV/NEXT mark with I/O and U/P keys.
  • Loop or one play mode with I key or loop icon.
  • Exit viewer with ESC key
Full Key Control List

       
  • SPACE - Pause/Unpause playback
  • TAB - Toggle between initial windowed mode and fullscreen
  • LEFT/RIGHT CURSOR - Jump back/forward 1 second
  • COMMA(,)/PERIOD(.) - Nudge back/forward by 1 frame (works best when paused)
  • UP/DOWN CURSOR - Increase/decrease brightness
  • 1, 2, 3 - Change White Balance preset or click the dropper icon and then anywhere to choose a neutral colour
  • 7, 4 - Change red multiplier up and down by 0.1
  • 8, 5 - Change green multiplier up and down by 0.1 (by reduced red/blue and increasing brightness)
  • 9, 6 - Change blue multiplier up and down by 0.1
  • F - Toggle between drop-frame mode allowing synchronised audio playback, or sequential frame mode and no audio
  • Q - Toggle between fast and high-quality demosaicing for playback (high-quality is used automatically when paused)
  • A - Toggle anamorphic aspect to take into account the 1.4x squeeze from shooting 50p/60p
  • S - Toggle anamorphic aspect to take into account anamorphic lenses (1.33x, 1.4x, 1.5x, 2.0x)
  • W - File dialog to choose the export directory
  • D - Choose export type, MOV or DNG
  • E - Add marked range to the export queue. Will use the source name with ".MOV" or "_DNG" appended.
  • C - Export all files in the current directory using the current settings
  • Y - Start processing, or pause processing of the export queue
  • X - Cancel current export job (and start next one in queue)
  • Z - Cancel all export jobs
  • T - Toggle between sRGB gamma, Rec.709 gamma, linear, global tone mapping, and log mapping curves
  • J/K - Change to previous/next MLV/RAW file in same directory as current file
  • V/B/N/M - Slide audio file start by -0.5,-0.05,+0.05,+0.5 seconds
  • I/O - Set IN/OUT marks. IN mark must be before the OUT mark. OUT mark must be after the IN mark
  • U/P - Jump to the previous/next marks
  • R - Reset the marks to start/end of the file
  • L - Toggle looping or play-once mode
  • H/G - Save/load current colour balance & brightness (for matching multiple takes)
  • 0 (ZERO) - Toggle stripe/hot-pixel removing preprocess pass
  • Shift-F - FPS override cycles through a range of standard FPS rates, overriding the clips default rate.
  • Shift-L - Choose LUTs from .CUBE files to import. LUTs only need to be imported once.
  • Shift-LEFT/RIGHT - Select 1D LUT 1 from the available (imported) 1D LUTs
  • Shift-UP/DOWN - Select 3D LUT from the available (imported) 3D LUTs
  • Shift-Z/X - Select 1D LUT 2 from the available (imported) 1D LUTs
  • Shift-H - Show/Hide RGB Histogram
  • Shift-1 - Remove current 1D1 LUT from index and current file
  • Shift-3 - Remove current 3D LUT from index and current file
Linux Installation & Usage

Any normal Linux distribution (32 or 64bit) should work, but only Ubuntu 12.04 64bit has been extensively tested. NVIDIA or AMD GPUs using properietary drivers should work best. You may be able to use Intel GPUS, but problems may increase the older the GPU.

You should get the source code either with git (see below) or from a snapshot: https://bitbucket.org/baldand/mlrawviewer/get/master.tar.bz2

You should use python 2.7 (not python 3), and install pyOpenGL and numpy package. On Ubuntu/Debian do:


sudo apt-get install build-essential python-opengl python-numpy
python setup.py build_ext --inplace
chmod +x mlrawviewer.py
./mlrawviewer.py /path/to/file.MLV [/path/to/encodedfile.MOV]


Then the video should appear and playback immediately. See above for keys.

Mac OS X 10.7-10.9 Installation and Usage

A binary release or source build can be used. The binary release is known to work with 10.7.x, 10.8.x and 10.9.x. Source builds may work with earlier OS X releases.

NVIDIA and AMD GPUs will work best. Intel GPUs may work, but problems have been reported with e.g. HD3000.

Download the DMG from https://bitbucket.org/baldand/mlrawviewer/downloads/MlRawViewer_1_3_3_mac.dmg

Click the DMG to mount it, and drag the icon to your Applications folder.

Drag an MLV or RAW or DNG file into the app, or open a file using the app.

Windows 7 Installation and Usage

A binary release or source build can be used. The binary release is known to work properly with Windows 7 (32bit or 64bit). It should also work with Window 8. Source builds may work with earlier Windows versions.

NVIDIA and AMD GPUs will work best. Intel GPUs may work, but problems have been seen with some older chips.

Download the zip from https://bitbucket.org/baldand/mlrawviewer/downloads/MlRawViewer_1_3_3_win32.zip

Open the zip, and copy the mlrawviewer folder to somewhere in your machine. That folder contains mlrawviewer.exe, which is the program to run.

Drag an MLV or RAW file into the mlrawviewer.exe app icon (or a shortcut), or set up a file association so it opens when you double click a video file. Alternatively run the app and select a file from the file dialog.

A log file (mlrawviewer.log) is generated in the USER\.mlrawviewer directory when the program is run. In case of problems, please check and share the log to help the developers identify the causes.

Implementation details

The program is written in python, and makes use of OpenGL for image processing in order to be able to display videos at their intended frame rate. This also depends on you having good file read speed in your computer.

Almost everything (apart from bitunpacking and CPU demosaicing) is written in python, so it is quite easy to install, modify and extend in case you are familiar with that language.

The license for the program source code excluding AMaZE is BSD-style.
The license for the AMaZE demosaicer (amaze_demosaic_RT.c) is GPLv3
The license for ffmpeg is GPLv3.
Hence, binary releases of MlRawViewer must be GPLv3.

Testing, feedback and code contributions are welcome.

Home page: https://bitbucket.org/baldand/mlrawviewer
Git repo: https://bitbucket.org/baldand/mlrawviewer.git
Bug tracker: https://bitbucket.org/baldand/mlrawviewer/issues
IRC: Freenode:#mlrawviewer

ItsMeLenny

Did you make that program baldand (haven't it tested yet).

baldand


g3gg0

cool :)
couldnt try because i couldnt set it up on my win7 system.
i must admit, i have no experience with python in general and didnt want to search too much :)



D:\Users\g3gg0>"c:\Program Files (x86)\Python\python.exe" d:\Users\g3gg0\Desktop\y\setup.py build
running build
running build_ext
building 'bitunpack' extension
error: Unable to find vcvarsall.bat

D:\Users\g3gg0>"c:\Program Files (x86)\Python\python.exe" d:\Users\g3gg0\Desktop\y\mlrawviewer.py
  File "d:\Users\g3gg0\Desktop\y\mlrawviewer.py", line 32
    except Exception,err:
                    ^
SyntaxError: invalid syntax
Help us with datasheets - Help us with register dumps
magic lantern: 1Magic9991E1eWbGvrsx186GovYCXFbppY, server expenses: [email protected]
ONLY donate for things we have done, not for things you expect!

baldand

I'm guessing you tried to run it with a Python 3.x runtime (which doens't support that Exception syntax)?

If so, try a Python 2.x runtime, like 2.7.6 from http://www.python.org/getit/

You may still have compiler or module troubles. When I tested it on Windows, I actually used the WinPython distribution, which includes all needed external modules, and also mingw for compiling the bitunpack module. See the end of my blog post for pointers: http://thndl.com/?20

ItsMeLenny

for me I got;

cosmo@cosmo:~/Downloads/mlrawviewer-1-0-0$ ./mlrawviewer.py ~/Videos/M12-1345.MLV
Falling back to Numpy for bit unpacking operations.
Consider compiling bitunpack module for faster conversion.
Opening MLV file /home/cosmo/Videos/M12-1345.MLV
Could not open file /home/cosmo/Videos/M12-1345.MLV. Error:1280922707


and with the bitunpack.so

cosmo@cosmo:~/Downloads/mlrawviewer-1-0-0$ ./mlrawviewer.py ~/Videos/M12-1345.MLV
Opening MLV file /home/cosmo/Videos/M12-1345.MLV
Could not open file /home/cosmo/Videos/M12-1345.MLV. Error:1280922707

baldand

Quote from: ItsMeLenny on December 12, 2013, 03:52:14 AM
for me I got;

cosmo@cosmo:~/Downloads/mlrawviewer-1-0-0$ ./mlrawviewer.py ~/Videos/M12-1345.MLV
Falling back to Numpy for bit unpacking operations.
Consider compiling bitunpack module for faster conversion.
Opening MLV file /home/cosmo/Videos/M12-1345.MLV
Could not open file /home/cosmo/Videos/M12-1345.MLV. Error:1280922707


and with the bitunpack.so

cosmo@cosmo:~/Downloads/mlrawviewer-1-0-0$ ./mlrawviewer.py ~/Videos/M12-1345.MLV
Opening MLV file /home/cosmo/Videos/M12-1345.MLV
Could not open file /home/cosmo/Videos/M12-1345.MLV. Error:1280922707


That was due to an unrecognised block type in the MLV file.

Now I got round to putting the source code to bitbucket, and fixing that bug. If you have a chance to pull a new version from there, it might work for you now.

https://bitbucket.org/baldand/mlrawviewer





ItsMeLenny

It works!! And was very smooth.

I think you'd know these facts already;
(but also just in case other people who haven't tested the program and want to know a little more);

I shot: 640x320 (2:1) @ 25fps
played back: 960x540 (16:9) @ ~28fps


which I just noticed it detects:
Using Bilinear demosaic algorithm
Width: 640 Height: 320 Frames: 715


also, It's very easy to edit the python source code to change white balance (by using RGB multipliers) <-- for anybody wondering
and same with resolution


one note baldand, I think the brightness may be wrong, it at 50 blows things out, haven't done extensive testing, but that may be due to a logarithmic vs linear scale or something, maybe it should be more something like 33.

ItsMeLenny

Bug:
When using nearest to de-mosaic instead of bi-linear, everything comes out blue


Found the solution:
You didnt "-black" on the other colours.

baldand

Quote from: ItsMeLenny on December 12, 2013, 11:53:27 AM
Bug:
When using nearest to de-mosaic instead of bi-linear, everything comes out blue


Found the solution:
You didnt "-black" on the other colours.

Thanks! I pushed the fix for this now.

I'm using a simple Reinhard global tone map function (x/(x+1)) for the display, so the brightness value needed depends very much on the content. At the moment I tend to just go in and modify the value manually for each clip I view.

A step up from that would be to make it a command line parameter, and a step up from that would be to let you change it while viewing the clip, and a step up from that would be to measure a histogram of the data and calculate a suitable value along with auto colour balance and the rest. All possible, but needs a bit more development.

Contributions/pull requests most welcome :-)

ItsMeLenny

Yeah, a gui would be great, I'm really impressed by this tool.
And then the step up after that would be output or piping to avconv/ffmpeg maybe.

I'm not sure if I exposed my test I did properly so I will have to try again.
At the same time, I'm not sure if your tool does work entirely right with the brightness and colour multipliers,
not that it matters because it is a viewer and only newly released.
But in the future it may have to be altered.

But yes, I'm very impressed.
I wonder if a gui could be done with wxpython, as I've programmed with that before.

(I don't have a bitbucket (yet), only a github.)

g3gg0

@baldand:

do you pre-index the MLV blocks before processing?
Help us with datasheets - Help us with register dumps
magic lantern: 1Magic9991E1eWbGvrsx186GovYCXFbppY, server expenses: [email protected]
ONLY donate for things we have done, not for things you expect!

baldand

Quote from: g3gg0 on December 12, 2013, 03:41:44 PM
@baldand:

do you pre-index the MLV blocks before processing?

No. I tried that at first, but it was a bit painful to wait a few seconds each time while it indexed e.g. a 20Gb set of files.

Now it builds an internal temporary index as it goes, and also tries to preload the next frame while the current one is rendered. I have a slighty better version not yet pushed which can do more look-ahead.

Of course it would be good if it would generate and persist an IDX file at the same time.

g3gg0

it doesnt matter how you pre-index - if using mlv_dump or internally.
just wanted to make sure you do it at all :)
Help us with datasheets - Help us with register dumps
magic lantern: 1Magic9991E1eWbGvrsx186GovYCXFbppY, server expenses: [email protected]
ONLY donate for things we have done, not for things you expect!

baldand


a1ex


alex@thinkpad:~/src/mlrawviewer$ python mlrawviewer.py ./M08-1336.RAW
MlRawViewer v1.0.1
(c) Andrew Baldwin & contributors 2013
Falling back to Numpy for bit unpacking operations.
Consider compiling bitunpack module for faster conversion.
Opening MLRAW file ./M08-1336.RAW
Width: 1920 Height: 1080 Frames: 60
Traceback (most recent call last):
  File "/home/alex/src/mlrawviewer/GLCompute.py", line 223, in __draw
    self.onDraw(w,h)
  File "mlrawviewer.py", line 186, in onDraw
    self.init()
  File "mlrawviewer.py", line 178, in init
    self.demosaic = DemosaicScene(self._raw,size=(self._raw.width(),self._raw.height()))
  File "mlrawviewer.py", line 93, in __init__
    self.rawUploadTex = GLCompute.Texture((self.raw.width(),self.raw.height()),rgbadata=frame0.rawimage,hasalpha=False,mono=True,sixteen=True)
  File "/home/alex/src/mlrawviewer/GLCompute.py", line 85, in __init__
    glTexImage2D(GL_TEXTURE_2D,0,GL_R32F,self.width,self.height,0,GL_RED,GL_UNSIGNED_SHORT,rgbadata)
  File "/usr/local/lib/python2.6/dist-packages/PyOpenGL-3.0.2-py2.6.egg/OpenGL/latebind.py", line 45, in __call__
    return self._finalCall( *args, **named )
  File "/usr/local/lib/python2.6/dist-packages/PyOpenGL-3.0.2-py2.6.egg/OpenGL/wrapper.py", line 792, in wrapperCall
    raise err
GLError: GLError(
err = 1281,
description = 'invalid value',
baseOperation = glTexImage2D,
pyArgs = (
GL_TEXTURE_2D,
0,
GL_R32F,
1920,
1080,
0,
GL_RED,
GL_UNSIGNED_SHORT,
array([[16382, 16382, 16382, ..., 163...,
),
cArgs = (
GL_TEXTURE_2D,
0,
GL_R32F,
1920,
1080,
0,
GL_RED,
GL_UNSIGNED_SHORT,
array([[16382, 16382, 16382, ..., 163...,
),
cArguments = (
GL_TEXTURE_2D,
0,
GL_R32F,
1920,
1080,
0,
GL_RED,
GL_UNSIGNED_SHORT,
array([[16382, 16382, 16382, ..., 163...,
)
)


Python 2.6.5, PyOpenGL 3.0.2.

Tried to print the arguments before the call to glTexImage2D:

            print self.width, self.height
            print rgbadata
            print glGetIntegerv(GL_MAX_TEXTURE_SIZE)
=>

1920 1080
[[16382 16382 16382 ..., 16382 16382 16382]
[16382 16382 16382 ..., 16382 16382 16382]
[16382 16382 16382 ..., 16382 16382 16382]
...,
[ 9928  6171 11226 ...,  6250 11173  6021]
[10345  6163 10482 ...,  5800 10179  6075]
[10423  5907  9725 ...,  5539 10362  5808]]
4096


Also tried smaller textures (64x64) and 8-bit, didn't help.

NeHe lesson 6 (texture mapping) runs fine (it has a call to glTexImage2D and seems to work).

Will keep looking, but maybe you have any suggestions on what to try?

baldand

What kind of platform are you running on, e.g.

Native Linux or under a VM? (VirtualBox/VMWare often have more limited OpenGL implementations)

What kind of graphics card/drivers - Intel, AMD, NVIDIA?

For reference, I've used it on (low end integrated) AMD & (mid range) NVIDIA, but not Intel (though I think it should generally work also there).

My suspicion here is the GL_R32F as the internal format. Your environment might not support floating point textures. One thing to try might be to change that to R16F or just R16 and see if that helps.

baldand

I just pushed a change for that line to use R16 internally, which should be ok for the raw bayer data.
Would be good to know if your env now fails on the next texture create which is RGB float.

a1ex

It's Ubuntu Lucid, native, and the card is Intel 4500MHD integrated. Not exactly the best choice for OpenGL.

Got it somewhat working with this change:

diff --git a/GLCompute.py b/GLCompute.py
index 161cc79..73575f6 100755
--- a/GLCompute.py
+++ b/GLCompute.py
@@ -80,7 +80,7 @@ class Texture:
         elif not hasalpha and not mono and fp:
             glTexImage2D(GL_TEXTURE_2D,0,GL_RGB32F,self.width,self.height,0,GL_RGB,GL_FLOAT,None)
         elif mono and not sixteen:
-            glTexImage2D(GL_TEXTURE_2D,0,GL_RED,self.width,self.height,0,GL_RED,GL_UNSIGNED_BYTE,rgbadata)
+            glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,self.width,self.height,0,GL_RED,GL_UNSIGNED_BYTE,rgbadata)
         elif mono and sixteen:
             glTexImage2D(GL_TEXTURE_2D,0,GL_R16,self.width,self.height,0,GL_RED,GL_UNSIGNED_SHORT,rgbadata)
         elif not mono and sixteen:
diff --git a/ShaderText.py b/ShaderText.py
index dd82c4b..dbcc56e 100644
--- a/ShaderText.py
+++ b/ShaderText.py
@@ -32,7 +32,7 @@ attribute vec4 axyuv;
attribute vec4 argba;
attribute vec4 actmg;
varying vec2 texcoord;
-uniform mat4x4 matrix;
+uniform mat4 matrix;
uniform float opacity;
uniform vec4 urgba;
varying vec4 rgba;
diff --git a/mlrawviewer.py b/mlrawviewer.py
index d7609b1..d3082b4 100755
--- a/mlrawviewer.py
+++ b/mlrawviewer.py
@@ -90,8 +90,8 @@ class DemosaicScene(GLCompute.Scene):
         frame0.convert()
         self.raw.preloadFrame(f)
         print "Width:",self.raw.width(),"Height:",self.raw.height(),"Frames:",self.raw.frames()
-        self.rawUploadTex = GLCompute.Texture((self.raw.width(),self.raw.height()),rgbadata=frame0.rawimage,hasalpha=False,mono=True,sixteen=True)
-        self.rgbImage = GLCompute.Texture((self.raw.width(),self.raw.height()),None,hasalpha=False,mono=False,sixteen=True,fp=True)
+        self.rawUploadTex = GLCompute.Texture((self.raw.width(),self.raw.height()),rgbadata=frame0.rawimage,hasalpha=False,mono=True,sixteen=False)
+        self.rgbImage = GLCompute.Texture((self.raw.width(),self.raw.height()),None,hasalpha=False,mono=False,sixteen=False,fp=False)
         demosaicer = Demosaicer(raw,self.rawUploadTex)
         print "Using",demosaicer.shader.demosaic_type,"demosaic algorithm"
         self.drawables.append(demosaicer)


Of course, the pixel format is incorrect, but hey, it's playing!

a1ex

I've split the topic; feel free to add a link to it in the old one, and edit the first post to keep things updated.

Small remark: I've noticed you are updating the black level on the fly, and you are computing it as MIN(all_pixels). This is incorrect for the following reasons:

- some cameras have bad pixels with raw value = 0 (okay, you can filter these out easily)
- if the image is exposed to the right, you will end up with a black value much higher than normal, and this will cause strong green cast in shadows
- if the image is exposed to the left, you will read something way below the real black level (you have a Gaussian noise, stdev something around 15, so you can end up easily 100 units below the correct value => pink cast; also, the minimum is not statistically robust so the level will change while playing).

So, I strongly recommend you to use the "EXIF" black level. If that one is wrong, it's a bug in ML, and must be reported and fixed there, not worked around in post software.


ItsMeLenny

Quote from: a1ex on December 14, 2013, 06:40:35 AM
I've split the topic; feel free to add a link to it in the old one, and edit the first post to keep things updated.

Small remark: I've noticed you are updating the black level on the fly, and you are computing it as MIN(all_pixels). This is incorrect for the following reasons:

- some cameras have bad pixels with raw value = 0 (okay, you can filter these out easily)
- if the image is exposed to the right, you will end up with a black value much higher than normal, and this will cause strong green cast in shadows
- if the image is exposed to the left, you will read something way below the real black level (you have a Gaussian noise, stdev something around 15, so you can end up easily 100 units below the correct value => pink cast; also, the minimum is not statistically robust so the level will change while playing).

So, I strongly recommend you to use the "EXIF" black level. If that one is wrong, it's a bug in ML, and must be reported and fixed there, not worked around in post software.

I reported this as a bug already as one video I tried it blew into this light washed out purple.
I'd prefer it without the black level update. But the EXIF isn't a bad idea.


ItsMeLenny

Quote from: a1ex on December 14, 2013, 07:34:33 AM
Fixed my video card issues and the black level problem.

https://bitbucket.org/baldand/mlrawviewer/pull-request/4/small-fixes

I'll leave it for baldand to merge to make sure he is happy.


(Also I just added different white balance values, changeable by using the numpad or number keys [0 1 2 3 4])

baldand

Thanks for all the great contributions so far. It's already working way better than just a few days ago.

Next up , I'm planning to integrate CPU-based AMaZE demosaicing (which is much slower than GPU demosaicing, but better looking) for using to export sections of a video through ffmpeg, e.g. to ProRes files.

ItsMeLenny

Quote from: baldand on December 14, 2013, 12:31:21 PM
Next up , I'm planning to integrate CPU-based AMaZE demosaicing (which is much slower than GPU demosaicing, but better looking) for using to export sections of a video through ffmpeg, e.g. to ProRes files.

Sweet!
On a similar note; would it be worth bicubic and/or synclancoz, rather than bilinear?