]> git.sesse.net Git - nageru/commitdiff
Add a flag to output Y'CbCr using Rec. 709 coefficients.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 15 Jan 2017 20:05:39 +0000 (21:05 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 15 Jan 2017 23:24:07 +0000 (00:24 +0100)
We will be needing this for HDMI/SDI output.

flags.cpp
flags.h
quicksync_encoder.cpp
theme.cpp
x264_encoder.cpp

index 1983c75e3d6f7b232ed95b3c9b937ca1841e61db..02ea81b6fd8ed4174916a344151f33eb2b238889 100644 (file)
--- a/flags.cpp
+++ b/flags.cpp
@@ -46,7 +46,8 @@ enum LongOption {
        OPTION_DISABLE_ALSA_OUTPUT,
        OPTION_NO_FLUSH_PBOS,
        OPTION_PRINT_VIDEO_LATENCY,
-       OPTION_AUDIO_QUEUE_LENGTH_MS
+       OPTION_AUDIO_QUEUE_LENGTH_MS,
+       OPTION_OUTPUT_YCBCR_COEFFICIENTS
 };
 
 void usage()
@@ -102,6 +103,8 @@ void usage()
        fprintf(stderr, "                                    possible to run with apitrace in real time)\n");
        fprintf(stderr, "      --print-video-latency       print out measurements of video latency on stdout\n");
        fprintf(stderr, "      --audio-queue-length-ms     length of audio resampling queue (default 100.0)\n");
+       fprintf(stderr, "      --output-ycbcr-coefficients={rec601,rec709}\n");
+       fprintf(stderr, "                                  Y'CbCr coefficient standard of output (default rec601)\n");
 }
 
 void parse_flags(int argc, char * const argv[])
@@ -149,9 +152,11 @@ void parse_flags(int argc, char * const argv[])
                { "no-flush-pbos", no_argument, 0, OPTION_NO_FLUSH_PBOS },
                { "print-video-latency", no_argument, 0, OPTION_PRINT_VIDEO_LATENCY },
                { "audio-queue-length-ms", required_argument, 0, OPTION_AUDIO_QUEUE_LENGTH_MS },
+               { "output-ycbcr-coefficients", required_argument, 0, OPTION_OUTPUT_YCBCR_COEFFICIENTS },
                { 0, 0, 0, 0 }
        };
        vector<string> theme_dirs;
+       string output_ycbcr_coefficients = "rec601";
        for ( ;; ) {
                int option_index = 0;
                int c = getopt_long(argc, argv, "c:t:I:v:m:M:w:h:", long_options, &option_index);
@@ -304,6 +309,9 @@ void parse_flags(int argc, char * const argv[])
                case OPTION_AUDIO_QUEUE_LENGTH_MS:
                        global_flags.audio_queue_length_ms = atof(optarg);
                        break;
+               case OPTION_OUTPUT_YCBCR_COEFFICIENTS:
+                       output_ycbcr_coefficients = optarg;
+                       break;
                case OPTION_HELP:
                        usage();
                        exit(0);
@@ -353,4 +361,13 @@ void parse_flags(int argc, char * const argv[])
                        exit(1);
                }
        }
+
+       if (output_ycbcr_coefficients == "rec709") {
+               global_flags.ycbcr_rec709_coefficients = true;
+       } else if (output_ycbcr_coefficients == "rec601") {
+               global_flags.ycbcr_rec709_coefficients = false;
+       } else {
+               fprintf(stderr, "ERROR: --output-ycbcr-coefficients must be “rec601” or “rec709”\n");
+               exit(1);
+       }
 }
diff --git a/flags.h b/flags.h
index b3e676d09ade636e0cc98f8d0f1aec46c1b7357c..06b08d1f160f88ddabb5b594d9912b82709c03a8 100644 (file)
--- a/flags.h
+++ b/flags.h
@@ -42,6 +42,7 @@ struct Flags {
        std::string midi_mapping_filename;  // Empty for none.
        bool print_video_latency = false;
        double audio_queue_length_ms = 100.0;
+       bool ycbcr_rec709_coefficients = false;
 };
 extern Flags global_flags;
 
index 749eb63d7056e638f8c8f4ac1d640706532b3d3e..875b264fdfe90342a0efcdfba78c38d33243ca66 100644 (file)
@@ -322,6 +322,7 @@ void QuickSyncEncoderImpl::sps_rbsp(bitstream *bs)
     if ( false ) {
         bitstream_put_ui(bs, 0, 1); /* vui_parameters_present_flag */
     } else {
+        // See H.264 annex E for the definition of this header.
         bitstream_put_ui(bs, 1, 1); /* vui_parameters_present_flag */
         bitstream_put_ui(bs, 0, 1); /* aspect_ratio_info_present_flag */
         bitstream_put_ui(bs, 0, 1); /* overscan_info_present_flag */
@@ -333,7 +334,11 @@ void QuickSyncEncoderImpl::sps_rbsp(bitstream *bs)
             {
                 bitstream_put_ui(bs, 1, 8);  /* colour_primaries (1 = BT.709) */
                 bitstream_put_ui(bs, 2, 8);  /* transfer_characteristics (2 = unspecified, since we use sRGB) */
-                bitstream_put_ui(bs, 6, 8);  /* matrix_coefficients (6 = BT.601/SMPTE 170M) */
+                if (global_flags.ycbcr_rec709_coefficients) {
+                    bitstream_put_ui(bs, 1, 8);  /* matrix_coefficients (1 = BT.709) */
+                } else {
+                    bitstream_put_ui(bs, 6, 8);  /* matrix_coefficients (6 = BT.601/SMPTE 170M) */
+                }
             }
         }
         bitstream_put_ui(bs, 0, 1); /* chroma_loc_info_present_flag */
index ef635763515ee854a9bbca8c5be8f956396871ec..24c6cdc261b93114a6a98a6ef222dfdcb9f8d18f 100644 (file)
--- a/theme.cpp
+++ b/theme.cpp
@@ -265,13 +265,11 @@ int EffectChain_finalize(lua_State* L)
                // happens in a pass not run by Movit (see ChromaSubsampler::subsample_chroma()).
                output_ycbcr_format.chroma_subsampling_x = 1;
                output_ycbcr_format.chroma_subsampling_y = 1;
-
-               // Rec. 709 would be the sane thing to do, but it seems many players
-               // (e.g. MPlayer and VLC) just default to BT.601 coefficients no matter
-               // what (see discussions in e.g. https://trac.ffmpeg.org/ticket/4978).
-               // We _do_ set the right flags, though, so that a player that works
-               // properly doesn't have to guess.
-               output_ycbcr_format.luma_coefficients = YCBCR_REC_601;
+               if (global_flags.ycbcr_rec709_coefficients) {
+                       output_ycbcr_format.luma_coefficients = YCBCR_REC_709;
+               } else {
+                       output_ycbcr_format.luma_coefficients = YCBCR_REC_601;
+               }
                output_ycbcr_format.full_range = false;
                output_ycbcr_format.num_levels = 256;
 
index fcd20e7aa519b33345a86b08728177bddf515b8b..f9b562443869211c8020731c94d9fe0701fd15a0 100644 (file)
@@ -101,13 +101,16 @@ void X264Encoder::init_x264()
                param.i_frame_reference = 16;  // Because speedcontrol is never allowed to change this above what we set at start.
        }
 
-       // NOTE: These should be in sync with the ones in h264encode.cpp (sbs_rbsp()).
+       // NOTE: These should be in sync with the ones in quicksync_encoder.cpp (sps_rbsp()).
        param.vui.i_vidformat = 5;  // Unspecified.
        param.vui.b_fullrange = 0;
        param.vui.i_colorprim = 1;  // BT.709.
        param.vui.i_transfer = 2;  // Unspecified (since we use sRGB).
-       param.vui.i_colmatrix = 6;  // BT.601/SMPTE 170M.
-
+       if (global_flags.ycbcr_rec709_coefficients) {
+               param.vui.i_colmatrix = 1;  // BT.709.
+       } else {
+               param.vui.i_colmatrix = 6;  // BT.601/SMPTE 170M.
+       }
 
        param.rc.i_rc_method = X264_RC_ABR;
        param.rc.i_bitrate = global_flags.x264_bitrate;