View Full Version : XYZ to RGB colorspace conversion
So, i've got DCP-file in MXF-conteiner, and i need to re-encode video to common format (for example h.264 in matroska).
As you know, in MXF there are lots of JPEG2000-compressed frames with images sampled by 12 bits per channel, and the channels are X, Y and Z (CIE 1931 color space). FFmpeg can demux MXF container and decode JPEG200 (through libopenjpeg), but it can not convert colorspace from XYZ to RGB (see discussion (http://ffmpeg.org/trac/ffmpeg/ticket/1279)), so i only can get picture with ugly colors.
I thought that it would be nice to build pipeline with ffmpeg and some colorspace converter, for example:
ffmpeg -i input.mxf -pix_fmt rgb48le -f rawvideo pipe:1 | xyztorgb | \
ffmpeg -i pipe:0 -blah-blah-blah output.mkv
In that case i only need XYZ to RGB converter. The task seemed simple for me (as i have seen this code from GIMP (http://www.koders.com/c/fid3D0B9544198EA82273F5328CF32117BC68C8365F.aspx), this thread about XYZ to RGB conversion for MXFsource (http://forum.doom9.org/showthread.php?t=160125) and this tread about XYZ/RGB matrices (http://forum.doom9.org/showthread.php?t=150145)).
I also tried to extract one frame from my MXF-file and applied color transform matrix with imagemagick:
ffmpeg -i input.mxf -pix_fmt rgb48le -f rawvideo -frames 1 temp.rgb && \
convert -depth 16 -size 2048x858 \
-color-matrix "3.240479 -1.537150 -0.498535 \
-0.969256 1.875992 0.041556 \
0.055648 -0.204043 1.057311" \
temp.rgb \
-depth 8 temp.png
The result was good.
The main task is to write some converter. I wrote this code (see attachment), but it is not able to do colorspace conversion right.
Any ideas, gentlemen?
Ok, gentlemen!
I was confused since ffmpeg told me that output colorspace was rgb48le, so i used little endian order for double-byte encoded components:
X = (six[0] * 256 + six[1]) / 65535.0;
Y = (six[2] * 256 + six[3]) / 65535.0;
Z = (six[4] * 256 + six[5]) / 65535.0;
But values seems to be big endian, so correct code should be:
X = (six[1] * 256 + six[0]) / 65535.0;
Y = (six[3] * 256 + six[2]) / 65535.0;
Z = (six[5] * 256 + six[4]) / 65535.0;
With this conversion will be correct.
StainlessS
11th June 2012, 23:42
With little endian, first byte would be the the least significant byte, for big endian, it is the
most significant byte, so your second code snip is correct for little endian, eg i86.
I would though prefer to read it formatted as below
X = (six[0] + six[1] * 256) / 65535.0;
Y = (six[2] + six[3] * 256) / 65535.0;
Z = (six[4] + six[5] * 256) / 65535.0;
Jonathan Swift has a lot to answer for.
Thank you, StainlessS!
To test my code i downloaded this trailer (http://wdsspr.ru/W/Total%20Recall/trailer/Digital/TOTAL-RECALL_TRL-A_S_RU-XX_RU_51_2K_20120326_CLB.zip?download).
This command works well for me:
ffmpeg -i trec.mxf \
-f rawvideo -pix_fmt rgb48le pipe:1 | ./xyztorgb | \
ffmpeg -r 24 -s 2048x858 -f rawvideo -pix_fmt rgb24 -i pipe:0 \
-pix_fmt yuv420p -f yuv4mpegpipe pipe:1 | \
x264 --profile high --level 4.1 --ref 4 \
--bframes 4 --b-adapt 2 --b-pyramid normal \
--deblock -1:-1 \
--crf 20 --rc-lookahead 60 --ratetol 10.0 \
--aq-mode 2 \
--8x8dct \
--partitions all --direct auto --weightp 2 --me umh --subme 10 \
--psy-rd 1.0:0.15 --trellis 2 \
--no-fast-pskip --no-dct-decimate \
--output trec.mkv \
--demuxer y4m --threads 4 -
Result is good, but my code is very slow. More optimizations needed badly.
StainlessS
12th June 2012, 22:36
if (inputcsp = 2)
Should it be outputcsp ?
I would try using float rather than double, the extra precision of double is probably superflous.
If source for i86 only then handle differently as native little endian, ie use unsigned short[3] rather than unsigned char[6],
otherwise, might be better (depending on compiler) to use shift by 8 rather rather than multiply by 256.
Also could try to input and output multiple samples at once rather than one at a time.
{with more buffer space, (eg six[256][6 or 3 depending type], and Three[256][3])}
and deal with the number of samples all at once before writing to output.
(obviously have to use value returned from fread function)
Could pre-calculate scaled to 1 (full range) X-Y-Z-values in 65536 array of double/float.
Lots of room to speed up, good luck. :)
Gavino
19th June 2012, 09:35
if (inputcsp = 2)
Should it be outputcsp ?
Not only that, it should be
if (outputcsp == 2)
and similarly use == in the earlier line
if (inputcsp = 1)
Using '=' instead of '==' means the conditions will always evaluate to 'true' (non-zero). However, as the program stands, inputsp and outputcsp are always 1 and 2 respectively, so in practice it makes no difference to the result.
Sparktank
10th February 2013, 00:05
Are there any full packages/guides that are updated to help convert DCP/MXF trailers to h264/mkv?
I'm on Windows 7, 64bit.
It's not easy trying to read through all the threads.
A lot of information is jumbled around and there's no single post with updated information. It's all fragmented so I have no idea what to do.
I've got several mxf/dcp trailers (2D and 3D) and would like to convert them to h264/mkv.
I've googled and found a lot of tools but a lot of them have very little documentation or very little coherent support threads/forums.
There also seems to be a lot of source codes you need to compile yourself (of which I have no experience) with patches and updates.
I've already got OpenDCP and OpenJPEG 2.0 installed.
I've also got in my arsenal: MXFSource AVISynth Plugin 0.1, Open Cinema Tools Release 1.1.2, OpenJPEG library and codecs.
I have Zeranoe FFmpeg builds and x264 from x264.nl.
I read somewhere that a custom ffmpeg will need to be compiled from source?
xledentaldj
10th February 2013, 00:46
Good luck with all that. Go over on the Mac OS X side, it might be easier? :-D.
sneaker_ger
11th February 2013, 23:06
I have Zeranoe FFmpeg builds and x264 from x264.nl.
I read somewhere that a custom ffmpeg will need to be compiled from source?
Did you test Zeranoe's builds already? The sample trailer posted by ar above seems to be supported by it.
sneaker_ger
12th February 2013, 16:38
That download is only for registered users.
xledentaldj
12th February 2013, 19:42
well, it was free for me to use and register
Sparktank
20th February 2013, 01:22
Did you test Zeranoe's builds already? The sample trailer posted by ar above seems to be supported by it.
I actually hadn't any time to try out it. But I will if they seem to be supported now.
Its an 16 second 48fps 2K DCP 3D Policy trailer. Short and easy for conversion testing.
That download is only for registered users.
I re-upped to Zippyshare, "No Sign Up Required".
Rio 3D Put your 3D glasses.rar
(http://www48.zippyshare.com/v/59552123/file.html)
I'm okay with batch scripts. A GUI would come in handy for single projects.
Mind you, I'm still doing just simple batch scripts without all the other functions or brackets.
Babysteps.
xledentaldj
20th February 2013, 01:40
Let me know if you sucsessfully convert that DCP to a 2D file that will play on a consumer media streamer/player.
Sparktank
20th February 2013, 03:02
I've changed the "inputcsp = 2" and added the double equal signs as suggested in the original ".c" anway.
I've tried the batch script from post #4 (with putting the "xyztorgb.c" into the ffmpeg ((2013-02-16) git-b9c5448 static 32bit build) folder and the folder with the mxf files as well)) but I keep getting frame rate errors.
The Rio 3D glasses has a frame rate of 48 and I get "Timecode frame rate X/1 not supported" and the batch closes.
It's an even 48.000 fps.
I then just copied the batch script and ran it in CMD and got this tidbit before it spat out more errors...
[mxf @ 03926a60] "OPAtom" with 2 ECs - assuming OP1a
[mxf @ 03926a60] Timecode frame rate 48/1 not supported
Input #0, mxf, from 'F:\Work\Trailers\Rio 3D Put your 3D glasses\3D Glasses.mxf':
Duration: 00:00:16.00, start: 0.000000, bitrate: 96485 kb/s
Stream #0:0: Video: jpeg2000, rgb48le (12 bpc), 2048x858, 24 tbr, 24 tbn, 24 tbc
[NULL @ 03930000] Unable to find a suitable output format for '\'
\: Invalid argument
I tried adding "-force_fps" and still didn't work. I also tried removing the "-r" and let it do it itself and still errors.
I'm not having any luck googling anything about ffmpeg and 48fps.
I don't know what I'm doing wrong.
sneaker_ger
21st February 2013, 01:31
I re-upped to Zippyshare, "No Sign Up Required".
Rio 3D Put your 3D glasses.rar (http://www48.zippyshare.com/v/59552123/file.html)
Seems to work fine here, but with 24 fps?:
ffmpeg -i "3D Glasses.mxf" -i "3D Glasses_audio.mxf" -vf scale=1920:-1 -sws_flags bicubic -pix_fmt yuv420p -vcodec libx264 -preset medium -crf 18 -acodec ac3 -ab 384k output.mkv
I'm not sure if I got the scaling correctly (to 1920 width and 4:2:0 for consumer players). You could of course pipe to raw video and audio and do other conversions yourself.
Sparktank
22nd February 2013, 01:25
ffmpeg -i "3D Glasses.mxf" -i "3D Glasses_audio.mxf" -vf scale=1920:-1 -sws_flags bicubic -pix_fmt yuv420p -vcodec libx264 -preset medium -crf 18 -acodec ac3 -ab 384k output.mkv
I tried that and it gives me a null file.
The MKV has MediaInfo data and does show up as 24fps.
However, the file size is only 622 bytes with no actual data.
There's no video, no audio; just a blank screen.
I still get the 48/1 fps error.
[mxf @ 00000000021d9520] Timecode frame rate 48/1 not supported
sneaker_ger
22nd February 2013, 07:14
I also get the error, but it seems to work nonetheless.
I'm using this (http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20130205-git-c2dd5a1-win64-static.7z) build.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.