# ColorMatrix v2.5

## Abstract

author: tritical
version: v2.5
download: http://bengal.missouri.edu/~kes25c/
category: Misc Plugins
requirements:

- YV12 & YUY2 Colorspace

license: GPL

## Description

ColorMatrix v2.0 is based on the original ColorMatrix filter by Wilbert Dijkhof.

When converting from RGB to YUV and vice versa there are multiple sets of coefficients that can be used. The most common are Rec.709, FCC, Rec.601 (aka SMPTE 170M or ITU-R BT.470-2), and SMPTE 240M. The purpose of ColorMatrix is to recalculate the values of a YUV video that has been converted from RGB using one set of coefficients to what the values would be had it been converted from RGB using a different set of coefficients. The reason this is useful is that MPEG-2 streams typically use Rec.709, whereas most computer software (XviD/DivX decoders, etc...) assumes Rec.601. Thus, if you take an MPEG-2 stream using Rec.709 and pass it as YUV to a decoder which upsamples to RGB using Rec.601 the colors will be slightly off. In this case, you could use ColorMatrix to convert the video from Rec.709 to Rec.601 and then pass it to the decoder. Another example is if you capture video with software that uses Rec.601 and then want to encode it to MPEG-2 using an encoder that assumes Rec.709.

At first glance, it would appear that to accomplish its task ColorMatrix would need to internally convert to RGB using the source coefficients and then convert back to YUV using the new coefficients. However, this is not the case. What colormatrix actually does is compute the inverse matrix of the source coefficients (gives a matrix for doing YUV->RGB) and then multiplies that matrix with the new coefficient matrix. This gives a set of coefficients for doing the conversion directly from YUV to YUV.

ColorMatrix supports YV12 and YUY2 colorspaces, and can convert between Rec.709, FCC, Rec.601, and SMPTE 240M. ColorMatrix also has the ability to do range expansion and contraction ([16,235/240]->[0,255] or [0,255]->[16,235/240]) as part of the colorimetry conversion or on its own.

### Syntax

`ColorMatrix` (clip, string "mode", int "source", int "dest", int "clamp", bool "interlaced", bool "inputFR", bool "outputFR", bool "hints", string "d2v", bool "debug", int "threads", int "thrdmthd", int "opt")

### Parameters

mode:

Can be used to set the source and destination formats in string form. Specify the string as `"source->dest"`, where `source` and `dest` are each replaced by one of the following (capitalization does not matter):

- Rec.709
- FCC
- Rec.601
- SMPTE 240M

Examples:

- ColorMatrix(mode="Rec.709->Rec.601")
- ColorMatrix(mode="Rec.601->FCC")
- ColorMatrix(mode="SMPTE 240M->Rec.601")
- ColorMatrix(mode="Rec.709->FCC")

source and dest cannot be the same if inputFR and outputFR are also the same.

default - "" (string)

source:

Allows setting the source format in integer form. If the mode parameter is specified, then it will override source. Possible settings:

- 0 - Rec.709
- 1 - FCC
- 2 - Rec.601
- 3 - SMPTE 240M

The source and dest parameters cannot be equal if inputFR and outputFR are also equal.

default - 0 (int)

dest:

Allows setting the destination format in integer form. If the mode parameter is specified, then it will override dest. Possible settings:

- 0 - Rec.709
- 1 - FCC
- 2 - Rec.601
- 3 - SMPTE 240M

The source and dest parameters cannot be equal if inputFR and outputFR are also equal.

default - 2 (int)

clamp:

Specifies whether pre/post clipping with limiter to 16-235/16-240 should be used. Possible settings:

- 0 - no clipping
- 1 - pre clipping (clip input to ColorMatrix)
- 2 - post clipping (clip output from ColorMatrix)
- 3 - pre and post clipping

3 is what previous (v1.x) versions of ColorMatrix used.

default - 3 (int)

interlaced:

Interlaced YV12 video requires special handling... so if your video is YV12 and is interlaced you need to set this parameter to true. Otherwise, leave it false. For interlaced processing the input clip to ColorMatrix must not be fieldbased. If it is, ColorMatrix will throw an error indicating this and stating that you should use AssumeFrameBased() beforehand.

default - false (bool)

inputFR:

Tells ColorMatrix whether the input video is full-range [0-255] or limited-range [16-235/240]. This setting has no effect if it is set equal to outputFR. A value of true indicates full-range and false indicates limited-range.

default - false (bool)

outputFR:

Tells ColorMatrix whether to output full-range [0-255] or limited-range [16-235/240] YUV values. This setting has no effect if it is set equal to inputFR. A value of true indicates full-range and false indicates limited-range.

default - false (bool)

hints:

DGDecode v1.20 or newer can output colorimetry hints in the video stream which ColorMatrix can read in order to automatically determine the source coefficients. To enable this, set `info=3` in `mpeg2source()` and set `hints=true` in `ColorMatrix()` as shown below:

    Mpeg2source("F:\TestStreams\avs\AguileraGrammies.d2v", info=3)
    ColorMatrix(hints=true)

If you would like to view the colorimetry info use `info=1` in `mpeg2source()` as shown below:

    Mpeg2source("F:\TestStreams\avs\AguileraGrammies.d2v", info=1)

If ColorMatrix is unable to detect hints in the stream (for example because you are using an incorrect dgdecode version) it will output an error. When using hints=true, the conversion specified by mode (or by source and dest if mode is not set) will only be applied when the colorimetry of the input video does not match the destination colorimetry. For example, if mode is set to "Rec.709->Rec.601" (or mode is left blank and source=0 and dest=2), then the conversion will only be applied if the input video's colorimetry is not already "Rec.601". If the input video's colorimetry already matches the destination colorimetry, then the frames are passed through untouched (except for limiter if clamp>0 or for range conversion if inputFR and outputFR are not equal). You can see which scenario is happening by using debug=true.

default - false (bool)

d2v:

Newer versions of DGIndex (v1.20+) write the colorimetry information into the d2v project file. ColorMatrix is able to parse the d2v file and automatically determine the source coefficients from that information. To enable this, set the d2v parameter equal to the path and name of the d2v project file as shown below:

    Mpeg2source("F:\TestStreams\avs\AguileraGrammies.d2v")
    ColorMatrix(d2v="AguileraGrammies.d2v")

If the d2v file is located in a different folder than the Avisynth script you will need to give the full path. The operation of the filter when the d2v parameter is specified is the same as with hints=true. If the input video's colorimetry already matches the destination colorimetry specified in the mode parameter (or with source and dest), then the conversion is not applied. If the colorimetry does not match, then the conversion is applied. Using the d2v parameter is faster than using hints.

It is possible for the colorimetry to change in a clip. If this is the case, then the d2v option will only work if you do not trim() or rearrange frames (ivtc for example) prior to the ColorMatrix call. If ColorMatrix detects that the colorimetry in the d2v file changes it will require that the number of frames specified by the d2v file is equal to the number of frames in the input clip. The hints option does not have this restriction.

For people who are interested, it is this (and subsequent) line(s) in the d2v file

    800 5 0 8210 0 0 32 32 92 b2 b2 a2 b2 b2 a2 b2 b2 a2

I've made the colorimetry info bold. See Colorimetry for an explanation of the info.

default - "" (string)

debug:

If set to true, debug information is output via OutputDebugString(). You can use the DebugView utility from Systeminternals to view this information. The information includes hints detected, routine being used (c, mmx, or sse), etc...

default - false (bool)

threads:

Sets the number of threads Colormatrix will use for processing. Can be any value greater than 0 and, for YUY2, less than the frame height, for YV12, less than the frame height divided by 2. If set to 0, ColorMatrix will automatically detect the number of available processors and set threads equal to that value.

default - 1 (int)

thrdmthd:

Determines how a frame will be divided among the processing threads when threads is greater than 1. Option 0 will split the frame into contiguous chunks (each thread will process a block of height/threads lines). Option 1 will split the frame into non-contiguous chunks (each thread will process every threads'th line).

default - 0 (int)

opt:

Due to rounding differences, the output from the mmx and sse2 routines (only present for YV12) is not exactly the same as the output from the c routine (the c routine is more accurate). The maximum difference between the simd and c routines is +-1 on the Y/U/V planes. The mmx and sse2 routines do produce matching output. If a range conversion occurs (inputFR and outputFR are different), then only c routines are used. The opt parameter is included to disable the usage of simd optimizations if you want to. Possible settings:

- 0 - force c routine
- 1 - force mmx routine
- 2 - force sse2 routine
- 3 - auto detect

default - 3 (int)

## Colorimetry

This is a list of all possibilities according to the MPEG-2 specs and DGDecode. The right most column shows how GSpot abbreviates each item.

0 | forbidden | N/A
1 | ITU-R BT.709 | I709
2 | Unspecified Video (unknown) | N/A
3 | reserved | N/A
4 | FCC | FCC
5 | ITU-R BT.470-2 (exactly the same as ITU-R BT.601) | I470
6 | SMPTE 170M (exactly the same as ITU-R BT.601) | S170
7 | SMPTE 240M | S240
8-255 | reserved | N/A

** Recommendation BT.601 is an update BT.470-2

## Background information

There are several ways to convert a YUV stream to RGB. The most well known uses Rec.601 coefficients. It is, for example, used in the color conversion routines of Avisynth (by default), VirtualDub and XviD/DivX. When playing back a XviD or DivX file the stream is converted to RGB using Rec.601 coefficients. The main issue is that sometimes other coefficients should be used for the YUV to RGB conversion (Rec.709, FCC, or SMPTE 240M). A problem arises if a stream is encoded using one set of coefficients (Rec.709 coefficients for many dvd streams for example), and somewhere in the reencoding-processing-playback chain a different set of coefficients is assumed (Rec.601 coefficients for the XviD/DivX decoder, FCC coefficients for TMPGEnc/QuEnc, or Rec.709 coefficients for CCE). It will cause a slight color distortion, which looks like a change in brightness (it's not really a change in brightness, the colors are just slightly off).

How do you know which set of coefficients were used when encoding a MPEG-2 stream? Usually, the coefficient information is stored in the header of the MPEG-2 file (the "matrix_coefficients" field in the "sequence display extension"). Newer versions of GSpot will be able to read and display this information. Also, DGDecode v1.20+ (with Mpeg2source(info=1)) can be used to view it. If this extension field is not present in the header of the MPEG-2 file, the specs say we are supposed to assume the default of Rec.709

## References

- users reporting the problem - getting different brightness when comparing the avs script with opening the mpeg2 directly in VDubMod.
- background info - doom9 thread about the problem.
- The "matrix coefficients" field specifies a set of coefficients given in Table 6-9 of ISO/IEC 13818-2, section 6.3.6 (Rec.709 are not entirely correct).
- ITU-R_BT.709 - you can get three free recommendations per valid email address.

## Changelog

v2.5, 25th January 2009
+ Updated d2v parsing to correctly determine frame count for v16 DGIndex project files.
- Fixed a bug causing the mmx/sse2 routines for FCC<->Rec.601 conversions to give incorrect U plane output.

v2.4, 18th January 2009
- Fixed a bug causing the sse2 routines not to process the last (width&15) pixels, and the mmx routines not to process the last (width&7) pixels.

v2.3, 08th January 2008
- Calculate conversion coefficients for PB/PR rows from luma coefficients
- Added inputFR and outputFR parameters allowing for YUV range expansion/contraction
- Changed the clamp parameter from bool to int to allow specifying only pre clipping or only post clipping or both

v2.2, 28th August 2007
- Changed the integer scaling parameter to a boolean parameter named clamp (scaling 1/2 were redundant)
- Fixed source==dest error when using d2v or hints
- Fixed thrdmthd being switched internally (i.e. backwards versus the behaviors described in the readme)

v2.1, 18th January 2007
+ Added multithreading support (the threads and thrdmthd parameters)
- Don't invoke AssumeFrameBased() internally during interlaced processing (requires that the input clip be framebased)

v2.0, 12th October 2006 (Changes from v1.10)
+ Rewrote a large portion of the code
+ Added ability to convert between any of: Rec.709, FCC, Rec.601, and SMPTE 240M
+ Added source and dest parameters
+ Added scaling parameter (optional clipping and unscaled coefficients)
+ d2v option supports changing colorimetry info (with trim() and frame rearrangement restriction)
- fixed a problem with calculated luma values that were < 0 being set to 255 instead of 0