X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=theme.cpp;h=0cc498e8ba0a4297be74bb320440f6c75cba2f7f;hb=2abf57fbc06f52c04fb2ca1f765459908e688890;hp=bcdd6f37bad5d69cd6462f6d0732064c21896a9d;hpb=138c12c13443d39f8b1168b5d54b36d9835c6405;p=nageru diff --git a/theme.cpp b/theme.cpp index bcdd6f3..0cc498e 100644 --- a/theme.cpp +++ b/theme.cpp @@ -265,19 +265,32 @@ 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; + + // This will be overridden if HDMI/SDI output is in force. 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; + output_ycbcr_format.num_levels = 1 << global_flags.x264_bit_depth; + + GLenum type = global_flags.x264_bit_depth > 8 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE; + + chain->add_ycbcr_output(inout_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED, output_ycbcr_format, YCBCR_OUTPUT_SPLIT_Y_AND_CBCR, type); - chain->add_ycbcr_output(inout_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED, output_ycbcr_format, YCBCR_OUTPUT_SPLIT_Y_AND_CBCR); - chain->set_dither_bits(8); + // If we're using zerocopy video encoding (so the destination + // Y texture is owned by VA-API and will be unavailable for + // display), add a copy, where we'll only be using the Y component. + if (global_flags.use_zerocopy) { + chain->add_ycbcr_output(inout_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED, output_ycbcr_format, YCBCR_OUTPUT_INTERLEAVED, type); // Add a copy where we'll only be using the Y component. + } + chain->set_dither_bits(global_flags.x264_bit_depth > 8 ? 16 : 8); chain->set_output_origin(OUTPUT_ORIGIN_TOP_LEFT); + } else { + chain->add_output(inout_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED); } - chain->add_output(inout_format, OUTPUT_ALPHA_FORMAT_POSTMULTIPLIED); chain->finalize(); return 0; @@ -603,8 +616,9 @@ LiveInputWrapper::LiveInputWrapper(Theme *theme, EffectChain *chain, bool overri // 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_x = global_flags.ten_bit_input ? 1 : 2; input_ycbcr_format.chroma_subsampling_y = 1; + input_ycbcr_format.num_levels = global_flags.ten_bit_input ? 1024 : 256; input_ycbcr_format.cb_x_position = 0.0; input_ycbcr_format.cr_x_position = 0.0; input_ycbcr_format.cb_y_position = 0.5; @@ -628,10 +642,12 @@ LiveInputWrapper::LiveInputWrapper(Theme *theme, EffectChain *chain, bool overri num_inputs = 1; } for (unsigned i = 0; i < num_inputs; ++i) { + // When using 10-bit input, we're converting to interleaved through v210Converter. + YCbCrInputSplitting splitting = global_flags.ten_bit_input ? YCBCR_INPUT_INTERLEAVED : YCBCR_INPUT_SPLIT_Y_AND_CBCR; if (override_bounce) { - inputs.push_back(new NonBouncingYCbCrInput(inout_format, input_ycbcr_format, global_flags.width, global_flags.height, YCBCR_INPUT_SPLIT_Y_AND_CBCR)); + inputs.push_back(new NonBouncingYCbCrInput(inout_format, input_ycbcr_format, global_flags.width, global_flags.height, splitting)); } else { - inputs.push_back(new YCbCrInput(inout_format, input_ycbcr_format, global_flags.width, global_flags.height, YCBCR_INPUT_SPLIT_Y_AND_CBCR)); + inputs.push_back(new YCbCrInput(inout_format, input_ycbcr_format, global_flags.width, global_flags.height, splitting)); } chain->add_input(inputs.back()); } @@ -680,8 +696,12 @@ void LiveInputWrapper::connect_signal(int signal_num) userdata = (const PBOFrameAllocator::Userdata *)frame.frame->userdata; } - inputs[i]->set_texture_num(0, userdata->tex_y[frame.field_number]); - inputs[i]->set_texture_num(1, userdata->tex_cbcr[frame.field_number]); + if (global_flags.ten_bit_input) { + inputs[i]->set_texture_num(0, userdata->tex_444[frame.field_number]); + } else { + inputs[i]->set_texture_num(0, userdata->tex_y[frame.field_number]); + inputs[i]->set_texture_num(1, userdata->tex_cbcr[frame.field_number]); + } inputs[i]->set_width(userdata->last_width[frame.field_number]); inputs[i]->set_height(userdata->last_height[frame.field_number]); @@ -963,12 +983,28 @@ int Theme::map_signal(int signal_num) if (signal_to_card_mapping.count(signal_num)) { return signal_to_card_mapping[signal_num]; } - if (signal_num >= int(num_cards)) { - fprintf(stderr, "WARNING: Theme asked for input %d, but we only have %u card(s).\n", signal_num, num_cards); - fprintf(stderr, "Mapping to card %d instead.\n", signal_num % num_cards); + + int card_index; + if (global_flags.output_card != -1 && num_cards > 1) { + // Try to exclude the output card from the default card_index. + card_index = signal_num % (num_cards - 1); + if (card_index >= global_flags.output_card) { + ++card_index; + } + if (signal_num >= int(num_cards - 1)) { + fprintf(stderr, "WARNING: Theme asked for input %d, but we only have %u input card(s) (card %d is busy with output).\n", + signal_num, num_cards - 1, global_flags.output_card); + fprintf(stderr, "Mapping to card %d instead.\n", card_index); + } + } else { + card_index = signal_num % num_cards; + if (signal_num >= int(num_cards)) { + fprintf(stderr, "WARNING: Theme asked for input %d, but we only have %u card(s).\n", signal_num, num_cards); + fprintf(stderr, "Mapping to card %d instead.\n", card_index); + } } - signal_to_card_mapping[signal_num] = signal_num % num_cards; - return signal_num % num_cards; + signal_to_card_mapping[signal_num] = card_index; + return card_index; } void Theme::set_signal_mapping(int signal_num, int card_num)