|
| 1 | +/****************************************************************************** |
| 2 | + Copyright (C) 2025 by Sean DuBois <[email protected]> |
| 3 | +
|
| 4 | + This program is free software: you can redistribute it and/or modify |
| 5 | + it under the terms of the GNU General Public License as published by |
| 6 | + the Free Software Foundation, either version 2 of the License, or |
| 7 | + (at your option) any later version. |
| 8 | +
|
| 9 | + This program is distributed in the hope that it will be useful, |
| 10 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | + GNU General Public License for more details. |
| 13 | +
|
| 14 | + You should have received a copy of the GNU General Public License |
| 15 | + along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 16 | +******************************************************************************/ |
| 17 | +#pragma once |
| 18 | + |
| 19 | +struct WHIPSimulcastEncoders { |
| 20 | +public: |
| 21 | + void Create(const char *encoderId, int rescaleFilter, int whipSimulcastTotalLayers, uint32_t outputWidth, |
| 22 | + uint32_t outputHeight) |
| 23 | + { |
| 24 | + if (rescaleFilter == OBS_SCALE_DISABLE) { |
| 25 | + rescaleFilter = OBS_SCALE_BICUBIC; |
| 26 | + } |
| 27 | + |
| 28 | + if (whipSimulcastTotalLayers <= 1) { |
| 29 | + return; |
| 30 | + } |
| 31 | + |
| 32 | + auto widthStep = outputWidth / whipSimulcastTotalLayers; |
| 33 | + auto heightStep = outputHeight / whipSimulcastTotalLayers; |
| 34 | + std::string encoder_name = "whip_simulcast_0"; |
| 35 | + |
| 36 | + for (auto i = whipSimulcastTotalLayers - 1; i > 0; i--) { |
| 37 | + uint32_t width = widthStep * i; |
| 38 | + width -= width % 2; |
| 39 | + |
| 40 | + uint32_t height = heightStep * i; |
| 41 | + height -= height % 2; |
| 42 | + |
| 43 | + encoder_name[encoder_name.size() - 1] = std::to_string(i).at(0); |
| 44 | + auto whip_simulcast_encoder = |
| 45 | + obs_video_encoder_create(encoderId, encoder_name.c_str(), nullptr, nullptr); |
| 46 | + |
| 47 | + if (whip_simulcast_encoder) { |
| 48 | + obs_encoder_set_video(whip_simulcast_encoder, obs_get_video()); |
| 49 | + obs_encoder_set_scaled_size(whip_simulcast_encoder, width, height); |
| 50 | + obs_encoder_set_gpu_scale_type(whip_simulcast_encoder, (obs_scale_type)rescaleFilter); |
| 51 | + whipSimulcastEncoders.push_back(whip_simulcast_encoder); |
| 52 | + obs_encoder_release(whip_simulcast_encoder); |
| 53 | + } else { |
| 54 | + blog(LOG_WARNING, |
| 55 | + "Failed to create video streaming WHIP Simulcast encoders (BasicOutputHandler)"); |
| 56 | + } |
| 57 | + } |
| 58 | + } |
| 59 | + |
| 60 | + void Update(obs_data_t *videoSettings, int videoBitrate) |
| 61 | + { |
| 62 | + auto bitrateStep = videoBitrate / static_cast<int>(whipSimulcastEncoders.size() + 1); |
| 63 | + for (auto &whipSimulcastEncoder : whipSimulcastEncoders) { |
| 64 | + videoBitrate -= bitrateStep; |
| 65 | + obs_data_set_int(videoSettings, "bitrate", videoBitrate); |
| 66 | + obs_encoder_update(whipSimulcastEncoder, videoSettings); |
| 67 | + } |
| 68 | + } |
| 69 | + |
| 70 | + void SetVideoFormat(enum video_format format) |
| 71 | + { |
| 72 | + for (auto enc : whipSimulcastEncoders) |
| 73 | + obs_encoder_set_preferred_video_format(enc, format); |
| 74 | + } |
| 75 | + |
| 76 | + void SetStreamOutput(obs_output_t *streamOutput) |
| 77 | + { |
| 78 | + for (size_t i = 0; i < whipSimulcastEncoders.size(); i++) |
| 79 | + obs_output_set_video_encoder2(streamOutput, whipSimulcastEncoders[i], i + 1); |
| 80 | + } |
| 81 | + |
| 82 | +private: |
| 83 | + std::vector<OBSEncoder> whipSimulcastEncoders; |
| 84 | +}; |
0 commit comments