@@ -21,63 +21,72 @@ public static async Task<VideoColorData> GetColorData(string path)
2121
2222 string infoFfprobe = AvProcess . GetFfprobeOutput ( $ "-v quiet -show_frames -read_intervals \" %+#1\" { path . Wrap ( ) } ") ;
2323
24- if ( infoFfprobe . Contains ( "side_data_type=Mastering display metadata" ) )
24+ string [ ] linesFfprobe = infoFfprobe . SplitIntoLines ( ) ;
25+
26+ foreach ( string line in linesFfprobe )
2527 {
26- string [ ] linesFfprobe = infoFfprobe . Split ( "side_data_type=Mastering display metadata" ) [ 1 ] . Split ( "[/SIDE_DATA]" ) [ 0 ] . SplitIntoLines ( ) ;
28+ if ( line . Contains ( "color_transfer=" ) )
29+ data . ColorTransfer = GetColorTransfer ( line . Split ( '=' ) . Last ( ) ) ;
2730
28- foreach ( string line in linesFfprobe )
29- {
30- if ( line . Contains ( "red_x=" ) )
31- data . RedX = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
31+ else if ( line . Contains ( "color_space=" ) )
32+ data . ColorMatrixCoeffs = GetMatrixCoeffs ( line . Split ( '=' ) . Last ( ) ) ;
3233
33- else if ( line . Contains ( "red_y =" ) )
34- data . RedY = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
34+ else if ( line . Contains ( "color_primaries =" ) )
35+ data . ColorPrimaries = GetColorPrimaries ( line . Split ( '=' ) . Last ( ) ) ;
3536
36- else if ( line . Contains ( "green_x =" ) )
37- data . GreenX = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
37+ else if ( line . Contains ( "color_range =" ) )
38+ data . ColorRange = GetColorRange ( line . Split ( '=' ) . Last ( ) ) ;
3839
39- else if ( line . Contains ( "green_y =" ) )
40- data . GreenY = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
40+ else if ( line . Contains ( "red_x =" ) )
41+ data . RedX = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
4142
42- else if ( line . Contains ( "blue_x =" ) )
43- data . BlueY = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
43+ else if ( line . Contains ( "red_y =" ) )
44+ data . RedY = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
4445
45- else if ( line . Contains ( "blue_y =" ) )
46- data . BlueX = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
46+ else if ( line . Contains ( "green_x =" ) )
47+ data . GreenX = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
4748
48- else if ( line . Contains ( "white_point_x =" ) )
49- data . WhiteY = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
49+ else if ( line . Contains ( "green_y =" ) )
50+ data . GreenY = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
5051
51- else if ( line . Contains ( "white_point_y =" ) )
52- data . WhiteX = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
52+ else if ( line . Contains ( "blue_x =" ) )
53+ data . BlueY = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
5354
54- else if ( line . Contains ( "max_luminance =" ) )
55- data . LumaMax = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
55+ else if ( line . Contains ( "blue_y =" ) )
56+ data . BlueX = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
5657
57- else if ( line . Contains ( "min_luminance=" ) )
58- data . LumaMin = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
59- }
58+ else if ( line . Contains ( "white_point_x=" ) )
59+ data . WhiteY = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
60+
61+ else if ( line . Contains ( "white_point_y=" ) )
62+ data . WhiteX = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
63+
64+ else if ( line . Contains ( "max_luminance=" ) )
65+ data . LumaMax = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
66+
67+ else if ( line . Contains ( "min_luminance=" ) )
68+ data . LumaMin = line . Contains ( "/" ) ? FractionToFloat ( line . Split ( '=' ) . Last ( ) ) : line . Split ( '=' ) . Last ( ) ;
6069 }
6170
6271 string infoMkvinfo = await AvProcess . RunMkvInfo ( $ "{ path . Wrap ( ) } ") ;
63-
72+
6473 if ( infoMkvinfo . Contains ( "+ Video track" ) )
6574 {
6675 string [ ] lines = infoMkvinfo . Split ( "+ Video track" ) [ 1 ] . Split ( "+ Track" ) [ 0 ] . Split ( "+ Tags" ) [ 0 ] . SplitIntoLines ( ) ;
6776
6877 foreach ( string line in lines )
6978 {
7079 if ( line . Contains ( "+ Colour transfer:" ) )
71- data . ColorTransfer = ValidateNumber ( line . Split ( ':' ) [ 1 ] ) ;
80+ data . ColorTransfer = ValidateNumber ( line . Split ( ':' ) [ 1 ] ) . GetInt ( ) ;
7281
7382 else if ( line . Contains ( "+ Colour matrix coefficients:" ) )
74- data . ColorMatrixCoeffs = ValidateNumber ( line . Split ( ':' ) [ 1 ] ) ;
83+ data . ColorMatrixCoeffs = ValidateNumber ( line . Split ( ':' ) [ 1 ] ) . GetInt ( ) ;
7584
7685 else if ( line . Contains ( "+ Colour primaries:" ) )
77- data . ColorPrimaries = ValidateNumber ( line . Split ( ':' ) [ 1 ] ) ;
86+ data . ColorPrimaries = ValidateNumber ( line . Split ( ':' ) [ 1 ] ) . GetInt ( ) ;
7887
7988 else if ( line . Contains ( "+ Colour range:" ) )
80- data . ColorRange = ValidateNumber ( line . Split ( ':' ) [ 1 ] ) ;
89+ data . ColorRange = ValidateNumber ( line . Split ( ':' ) [ 1 ] ) . GetInt ( ) ;
8190
8291 else if ( line . Contains ( "+ Red colour coordinate x:" ) )
8392 data . RedX = ValidateNumber ( line . Split ( ':' ) [ 1 ] ) ;
@@ -136,7 +145,7 @@ public static async Task SetColorData(string path, VideoColorData d)
136145 $ "--colour-transfer-characteristics 0:{ d . ColorTransfer } " +
137146 $ "--colour-primaries 0:{ d . ColorPrimaries } " +
138147 $ "--max-luminance 0:{ d . LumaMax } " +
139- $ "--min-luminance 0:{ d . LumaMin } " +
148+ $ "--min-luminance 0:{ d . LumaMin } " +
140149 $ "--chromaticity-coordinates 0:{ d . RedX } ,{ d . RedY } ,{ d . GreenX } ,{ d . GreenY } ,{ d . BlueX } ,{ d . BlueY } " +
141150 $ "--white-colour-coordinates 0:{ d . WhiteX } ,{ d . WhiteY } " +
142151 $ "{ path . Wrap ( ) } ";
@@ -157,10 +166,155 @@ public static async Task SetColorData(string path, VideoColorData d)
157166 File . Move ( tmpPath , path ) ;
158167 }
159168 }
160- catch ( Exception e )
169+ catch ( Exception e )
161170 {
162171 Logger . Log ( $ "SetColorData Error: { e . Message } \n { e . StackTrace } ") ;
163172 }
164173 }
174+
175+ public static int GetColorPrimaries ( string s ) // Defined by the "Color primaries" section of ISO/IEC 23091-4/ITU-T H.273
176+ {
177+ s = s . Trim ( ) . ToLower ( ) ;
178+ if ( s == "bt709" ) return 1 ;
179+ if ( s == "bt470m" ) return 4 ;
180+ if ( s == "bt470bg" ) return 5 ;
181+ if ( s == "bt610" ) return 6 ;
182+ if ( s == "smpte240m" ) return 7 ;
183+ if ( s == "film" ) return 8 ;
184+ if ( s == "bt2020" ) return 9 ;
185+ if ( s == "smpte428" ) return 10 ;
186+ if ( s == "smpte431" ) return 11 ;
187+ if ( s == "smpte432" ) return 12 ;
188+ return 2 ; // Fallback: 2 = Unspecified
189+ }
190+
191+ public static int GetColorTransfer ( string s ) // Defined by the "Transfer characteristics" section of ISO/IEC 23091-4/ITU-T H.273
192+ {
193+ s = s . Trim ( ) . ToLower ( ) ;
194+ if ( s == "bt709" ) return 1 ;
195+ if ( s == "gamma22" || s == "bt470m" ) return 4 ;
196+ if ( s == "gamma28" || s == "bt470bg" ) return 5 ; // BT.470 System B, G (historical)
197+ if ( s == "bt610" || s == "smpte170m" ) return 6 ; // BT.601
198+ if ( s == "smpte240m" ) return 7 ; // SMPTE 240 M
199+ if ( s == "linear" ) return 8 ; // Linear
200+ //if (s == "?") return 9; // Logarithmic(100 : 1 range)
201+ //if (s == "?") return 10; // Logarithmic (100 * Sqrt(10) : 1 range)
202+ if ( s == "iec61966-2-4" ) return 11 ; // IEC 61966-2-4
203+ if ( s == "bt1361" || s == "bt1361e" ) return 12 ; // BT.1361
204+ if ( s == "srgb" ) return 13 ; // SRGB
205+ if ( s == "bt2020-10" ) return 14 ; // BT.2020 10-bit systems
206+ if ( s == "bt2020-12" ) return 15 ; // BT.2020 12-bit systems
207+ if ( s == "smpte2084" ) return 16 ; // SMPTE ST 2084, ITU BT.2100 PQ
208+ if ( s == "smpte428" ) return 17 ; // SMPTE ST 428
209+ if ( s == "bt2100" ) return 18 ; // BT.2100 HLG, ARIB STD-B67
210+ return 2 ; // Fallback: 2 = Unspecified
211+ }
212+
213+ public static int GetMatrixCoeffs ( string s ) // Defined by the "Matrix coefficients" section of ISO/IEC 23091-4/ITU-T H.27
214+ {
215+ s = s . Trim ( ) . ToLower ( ) ;
216+ if ( s == "bt709" ) return 1 ;
217+ if ( s == "fcc" ) return 4 ; // US FCC 73.628
218+ if ( s == "bt470bg" ) return 5 ; // BT.470 System B, G (historical)
219+ if ( s == "bt610" || s == "smpte170m" ) return 6 ; // BT.601
220+ if ( s == "smpte240m" ) return 7 ; // SMPTE 240 M
221+ if ( s == "ycgco" ) return 8 ; // YCgCo
222+ if ( s == "bt2020ncl" || s == "bt2020nc" ) return 9 ; // BT.2020 non-constant luminance, BT.2100 YCbCr
223+ if ( s == "bt2020" ) return 10 ; // BT.2020 constant luminance
224+ if ( s == "smpte2085" ) return 11 ; // SMPTE ST 2085 YDzDx
225+ // 12: MC_CHROMAT_NCL - Chromaticity-derived non-constant luminance
226+ // 13: MC_CHROMAT_CL - Chromaticity-derived constant luminance
227+ // 14: MC_ICTCP BT.2100 - ICtCp
228+ return 2 ; // Fallback: 2 = Unspecified
229+ }
230+
231+ public static int GetColorRange ( string s ) // Defined by the "Matrix coefficients" section of ISO/IEC 23091-4/ITU-T H.27
232+ {
233+ s = s . Trim ( ) . ToLower ( ) ;
234+ if ( s == "tv" ) return 1 ; // TV
235+ if ( s == "pc" ) return 2 ; // PC/Full
236+ return 0 ; // Fallback: Unspecified
237+ }
238+
239+ public static string GetColorPrimariesName ( int n )
240+ {
241+ switch ( n )
242+ {
243+ case 1 : return "BT.709" ;
244+ case 2 : return "Unspecified" ;
245+ case 4 : return "BT.470 System B, G (historical)" ;
246+ case 5 : return "BT.470 System M (historical)" ;
247+ case 6 : return "BT.601" ;
248+ case 7 : return "SMPTE 240" ;
249+ case 8 : return "Generic film (color filters using illuminant C)" ;
250+ case 9 : return "BT.2020, BT.2100" ;
251+ case 10 : return "SMPTE 428 (CIE 1921 XYZ)" ;
252+ case 11 : return "SMPTE RP 431-2" ;
253+ case 12 : return "SMPTE EG 432-1" ;
254+ case 22 : return "EBU Tech. 3213-E" ;
255+ }
256+
257+ return "Unknown" ;
258+ }
259+
260+ public static string GetColorTransferName ( int n )
261+ {
262+ switch ( n )
263+ {
264+ case 1 : return "BT.709" ;
265+ case 2 : return "Unspecified" ;
266+ case 4 : return "BT.470 System B, G (historical)" ;
267+ case 5 : return "BT.470 System M (historical)" ;
268+ case 6 : return "BT.601" ;
269+ case 7 : return "SMPTE 240 M" ;
270+ case 8 : return "Linear" ;
271+ case 9 : return "Logarithmic (100 : 1 range)" ;
272+ case 10 : return "Logarithmic (100 * Sqrt(10) : 1 range)" ;
273+ case 11 : return "IEC 61966-2-4" ;
274+ case 12 : return "BT.1361" ;
275+ case 13 : return "sRGB or sYCC" ;
276+ case 14 : return "BT.2020 10-bit systems" ;
277+ case 15 : return "BT.2020 12-bit systems" ;
278+ case 16 : return "SMPTE ST 2084, ITU BT.2100 PQ" ;
279+ case 17 : return "SMPTE ST 428" ;
280+ case 18 : return "BT.2100 HLG, ARIB STD-B67" ;
281+ }
282+
283+ return "Unknown" ;
284+ }
285+
286+ public static string GetColorMatrixCoeffsName ( int n )
287+ {
288+ switch ( n )
289+ {
290+ case 1 : return "BT.709" ;
291+ case 2 : return "Unspecified" ;
292+ case 4 : return "US FCC 73.628" ;
293+ case 5 : return "BT.470 System B, G (historical)" ;
294+ case 6 : return "BT.601" ;
295+ case 7 : return "SMPTE 240 M" ;
296+ case 8 : return "YCgCo" ;
297+ case 9 : return "BT.2020 non-constant luminance, BT.2100 YCbCr" ;
298+ case 10 : return "BT.2020 constant luminance" ;
299+ case 11 : return "SMPTE ST 2085 YDzDx" ;
300+ case 12 : return "Chromaticity-derived non-constant luminance" ;
301+ case 13 : return "Chromaticity-derived constant luminance" ;
302+ case 14 : return "BT.2100 ICtCp" ;
303+ }
304+
305+ return "Unknown" ;
306+ }
307+
308+ public static string GetColorRangeName ( int n )
309+ {
310+ switch ( n )
311+ {
312+ case 0 : return "Unspecified" ;
313+ case 1 : return "TV (Limited)" ;
314+ case 2 : return "PC (Full)" ;
315+ }
316+
317+ return "Unknown" ;
318+ }
165319 }
166320}
0 commit comments