]> git.sesse.net Git - nageru/commitdiff
Fix a bunch of colorspace issues, after practical testing. There is still some left...
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 1 Nov 2015 14:30:20 +0000 (15:30 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Sun, 1 Nov 2015 14:30:20 +0000 (15:30 +0100)
h264encode.cpp
httpd.cpp
theme.cpp

index 55ed9a18caa362264e836f161645e8cfad33c601..d63fe896e5efebfaf717e368226fca20c7a5c6c5 100644 (file)
@@ -340,7 +340,17 @@ static void sps_rbsp(bitstream *bs)
         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 */
-        bitstream_put_ui(bs, 0, 1); /* video_signal_type_present_flag */
+        bitstream_put_ui(bs, 1, 1); /* video_signal_type_present_flag */
+        {
+            bitstream_put_ui(bs, 5, 3);  /* video_format (5 = Unspecified) */
+            bitstream_put_ui(bs, 0, 1);  /* video_full_range_flag */
+            bitstream_put_ui(bs, 1, 1);  /* colour_description_present_flag */
+            {
+                bitstream_put_ui(bs, 1, 8);  /* colour_primaries (1 = BT.709) */
+                bitstream_put_ui(bs, 1, 8);  /* transfer_characteristics (1 = BT.709) */
+                bitstream_put_ui(bs, 1, 8);  /* matrix_coefficients (1 = BT.709) */
+            }
+        }
         bitstream_put_ui(bs, 0, 1); /* chroma_loc_info_present_flag */
         bitstream_put_ui(bs, 1, 1); /* timing_info_present_flag */
         {
index 38e685e6e8d0b4a2064590426a4714a24756f71c..de0af8e99489133f399fa8ae816ac5f8c1aa6e25 100644 (file)
--- a/httpd.cpp
+++ b/httpd.cpp
@@ -89,6 +89,17 @@ HTTPD::Mux::Mux(AVFormatContext *avctx, int width, int height)
        avstream_video->codec->time_base = AVRational{1, TIMEBASE};
        avstream_video->codec->ticks_per_frame = 1;  // or 2?
 
+       // Colorspace details. Closely correspond to settings in EffectChain_finalize,
+       // as noted in each comment.
+       // Note that the H.264 stream also contains this information and depending on the
+       // mux, this might simply get ignored. See sps_rbsp().
+       avstream_video->codec->color_primaries = AVCOL_PRI_BT709;  // RGB colorspace (inout_format.color_space).
+       avstream_video->codec->color_trc = AVCOL_TRC_BT709;  // Gamma curve (inout_format.gamma_curve).
+       avstream_video->codec->colorspace = AVCOL_SPC_BT709;  // YUV colorspace (output_ycbcr_format.luma_coefficients).
+       avstream_video->codec->color_range = AVCOL_RANGE_MPEG;  // Full vs. limited range (output_ycbcr_format.full_range).
+       avstream_video->codec->chroma_sample_location = AVCHROMA_LOC_LEFT;  // Chroma sample location. See chroma_offset_0[] in Mixer::subsample_chroma().
+       avstream_video->codec->field_order = AV_FIELD_PROGRESSIVE;
+
        AVCodec *codec_audio = avcodec_find_encoder(AV_CODEC_ID_MP3);
        avstream_audio = avformat_new_stream(avctx, codec_audio);
        if (avstream_audio == nullptr) {
index 767abac0389f98ea318513c583bd11c8f24f3067..56d5f84553c5d00bcbb0406c6548ec703fecd059 100644 (file)
--- a/theme.cpp
+++ b/theme.cpp
@@ -123,15 +123,21 @@ int EffectChain_finalize(lua_State* L)
        bool is_main_chain = checkbool(L, 2);
 
        // Add outputs as needed.
+       // NOTE: If you change any details about the output format, you will need to
+       // also update what's given to the muxer (HTTPD::Mux constructor) and
+       // what's put in the H.264 stream (sps_rbsp()).
        ImageFormat inout_format;
-       inout_format.color_space = COLORSPACE_sRGB;
-       inout_format.gamma_curve = GAMMA_sRGB;
+       inout_format.color_space = COLORSPACE_REC_709;
+       inout_format.gamma_curve = GAMMA_REC_709;
        if (is_main_chain) {
                YCbCrFormat output_ycbcr_format;
+               // We actually output 4:2:0 in the end, but chroma subsampling
+               // happens in a pass not run by Movit (see Mixer::subsample_chroma()).
                output_ycbcr_format.chroma_subsampling_x = 1;
                output_ycbcr_format.chroma_subsampling_y = 1;
                output_ycbcr_format.luma_coefficients = YCBCR_REC_709;
                output_ycbcr_format.full_range = false;
+               output_ycbcr_format.num_levels = 256;
 
                chain->add_ycbcr_output(inout_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED, output_ycbcr_format, YCBCR_OUTPUT_SPLIT_Y_AND_CBCR);
                chain->set_dither_bits(8);
@@ -319,6 +325,11 @@ LiveInputWrapper::LiveInputWrapper(Theme *theme, EffectChain *chain, bool overri
        inout_format.color_space = COLORSPACE_sRGB;
        inout_format.gamma_curve = GAMMA_sRGB;
 
+       // The Blackmagic driver docs claim that the device outputs Y'CbCr
+       // according to Rec. 601, but practical testing indicates it definitely
+       // is Rec. 709 (at least up to errors attributable to rounding errors).
+       // Perhaps 601 was only to indicate the subsampling positions, not the
+       // colorspace itself? Tested with a Lenovo X1 gen 3 as input.
        YCbCrFormat input_ycbcr_format;
        input_ycbcr_format.chroma_subsampling_x = 2;
        input_ycbcr_format.chroma_subsampling_y = 1;
@@ -326,7 +337,7 @@ LiveInputWrapper::LiveInputWrapper(Theme *theme, EffectChain *chain, bool overri
        input_ycbcr_format.cr_x_position = 0.0;
        input_ycbcr_format.cb_y_position = 0.5;
        input_ycbcr_format.cr_y_position = 0.5;
-       input_ycbcr_format.luma_coefficients = YCBCR_REC_601;
+       input_ycbcr_format.luma_coefficients = YCBCR_REC_709;
        input_ycbcr_format.full_range = false;
 
        if (override_bounce) {