@@ -133,9 +133,13 @@ struct VideoEncoder::Impl final
133133 bool init_video_codec_av (const AVCodec *codec);
134134 bool init_video_codec_pyro (PyroEnc::Profile profile);
135135 bool init_video_codec_pyrowave ();
136+ bool init_video_codec_pyrowave_buffers (unsigned bitrate_kbits);
136137 bool init_video_codec ();
137138 bool init_audio_codec ();
138139
140+ bool update_bitrate_async ();
141+ std::atomic<unsigned > update_bitrate_kbits = {};
142+
139143 std::vector<int16_t > audio_buffer_s16;
140144
141145 struct
@@ -460,10 +464,21 @@ void VideoEncoder::Impl::write_frames_interleaved_f32(const float *data, size_t
460464}
461465#endif
462466
467+ bool VideoEncoder::Impl::update_bitrate_async ()
468+ {
469+ auto new_value = update_bitrate_kbits.exchange (0 , std::memory_order_acq_rel);
470+ if (new_value)
471+ options.bitrate_kbits = new_value;
472+ return new_value != 0 ;
473+ }
474+
463475bool VideoEncoder::Impl::encode_frame (const PyroWave::ViewBuffers &views, int64_t pts, int compensate_audio_us)
464476{
465477 assert (mux_stream_callback);
466478
479+ if (update_bitrate_async () && !init_video_codec_pyrowave_buffers (options.bitrate_kbits ))
480+ return false ;
481+
467482 auto cmd = device->request_command_buffer (Vulkan::CommandBuffer::Type::AsyncCompute);
468483 pyrowave_encoder.encode (*cmd, views, pyrowave.buffers );
469484 cmd->barrier (VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT , VK_ACCESS_2_SHADER_STORAGE_WRITE_BIT ,
@@ -1335,42 +1350,17 @@ bool VideoEncoder::Impl::init_video_codec_av(const AVCodec *codec)
13351350 return true ;
13361351}
13371352
1338- bool VideoEncoder::Impl::init_video_codec_pyrowave ( )
1353+ bool VideoEncoder::Impl::init_video_codec_pyrowave_buffers ( unsigned bitrate_kbits )
13391354{
1340- if (!pyrowave_encoder.init (device, int (options.width ), int (options.height ),
1341- format_needs_downsample (options.format ) ?
1342- PyroWave::ChromaSubsampling::Chroma420 :
1343- PyroWave::ChromaSubsampling::Chroma444))
1344- return false ;
1345-
1346- pyro_codec.video_codec = PYRO_VIDEO_CODEC_PYROWAVE ;
1347- pyro_codec.width = options.width ;
1348- pyro_codec.height = options.height ;
1349- pyro_codec.frame_rate_num = options.frame_timebase .den ;
1350- pyro_codec.frame_rate_den = options.frame_timebase .num ;
1351-
1352- if (format_needs_downsample (options.format ))
1353- {
1354- pyro_codec.video_color_profile = options.hdr10 ?
1355- PYRO_VIDEO_COLOR_BT2020NCL_PQ_FULL_CENTER_CHROMA_420 :
1356- PYRO_VIDEO_COLOR_BT709_FULL_CENTER_CHROMA_420 ;
1357- }
1358- else
1359- {
1360- pyro_codec.video_color_profile = options.hdr10 ?
1361- PYRO_VIDEO_COLOR_BT2020NCL_PQ_FULL_CHROMA_444 :
1362- PYRO_VIDEO_COLOR_BT709_FULL_CHROMA_444 ;
1363- }
1364-
1365- pyrowave.payload_size = (1000ull * options.bitrate_kbits * options.frame_timebase .num ) /
1355+ pyrowave.payload_size = (1000ull * bitrate_kbits * options.frame_timebase .num ) /
13661356 (options.frame_timebase .den * 8 );
13671357
13681358 pyrowave.payload_size &= ~3 ;
13691359
13701360 Vulkan::BufferCreateInfo bufinfo = {};
13711361 bufinfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
1372- VK_BUFFER_USAGE_TRANSFER_DST_BIT |
1373- VK_BUFFER_USAGE_TRANSFER_SRC_BIT ;
1362+ VK_BUFFER_USAGE_TRANSFER_DST_BIT |
1363+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT ;
13741364
13751365 bufinfo.size = pyrowave.payload_size + pyrowave_encoder.get_meta_required_size ();
13761366 bufinfo.domain = Vulkan::BufferDomain::Device;
@@ -1394,7 +1384,37 @@ bool VideoEncoder::Impl::init_video_codec_pyrowave()
13941384
13951385 pyrowave.bitstream .resize (pyrowave.payload_size );
13961386
1397- return true ;
1387+ return pyrowave.bitstream_gpu && pyrowave.bitstream_cpu && pyrowave.meta_gpu && pyrowave.meta_cpu ;
1388+ }
1389+
1390+ bool VideoEncoder::Impl::init_video_codec_pyrowave ()
1391+ {
1392+ if (!pyrowave_encoder.init (device, int (options.width ), int (options.height ),
1393+ format_needs_downsample (options.format ) ?
1394+ PyroWave::ChromaSubsampling::Chroma420 :
1395+ PyroWave::ChromaSubsampling::Chroma444))
1396+ return false ;
1397+
1398+ pyro_codec.video_codec = PYRO_VIDEO_CODEC_PYROWAVE ;
1399+ pyro_codec.width = options.width ;
1400+ pyro_codec.height = options.height ;
1401+ pyro_codec.frame_rate_num = options.frame_timebase .den ;
1402+ pyro_codec.frame_rate_den = options.frame_timebase .num ;
1403+
1404+ if (format_needs_downsample (options.format ))
1405+ {
1406+ pyro_codec.video_color_profile = options.hdr10 ?
1407+ PYRO_VIDEO_COLOR_BT2020NCL_PQ_FULL_CENTER_CHROMA_420 :
1408+ PYRO_VIDEO_COLOR_BT709_FULL_CENTER_CHROMA_420 ;
1409+ }
1410+ else
1411+ {
1412+ pyro_codec.video_color_profile = options.hdr10 ?
1413+ PYRO_VIDEO_COLOR_BT2020NCL_PQ_FULL_CHROMA_444 :
1414+ PYRO_VIDEO_COLOR_BT709_FULL_CHROMA_444 ;
1415+ }
1416+
1417+ return init_video_codec_pyrowave_buffers (options.bitrate_kbits );
13981418}
13991419
14001420bool VideoEncoder::Impl::init_video_codec_pyro (PyroEnc::Profile profile)
@@ -1940,6 +1960,11 @@ void VideoEncoder::process_rgb(Vulkan::CommandBuffer &cmd, YCbCrPipeline &pipeli
19401960 }
19411961}
19421962
1963+ void VideoEncoder::update_bitrate_kbits (unsigned bitrate_kbits)
1964+ {
1965+ impl->update_bitrate_kbits .exchange (bitrate_kbits, std::memory_order_acq_rel);
1966+ }
1967+
19431968bool VideoEncoder::encode_frame (YCbCrPipeline &pipeline_ptr, int64_t pts, int compensate_audio_us)
19441969{
19451970 auto &pipeline = *pipeline_ptr;
0 commit comments