2424#include < utility>
2525#include < vector>
2626
27+ #include " absl/base/nullability.h"
2728#include " absl/container/flat_hash_map.h"
2829#include " absl/container/flat_hash_set.h"
2930#include " absl/log/absl_check.h"
@@ -625,58 +626,35 @@ absl::Status ValidateAndApplyUserTrimming(
625626
626627} // namespace
627628
628- AudioFrameGenerator::AudioFrameGenerator (
629+ absl::StatusOr<std::unique_ptr<AudioFrameGenerator> absl_nonnull>
630+ AudioFrameGenerator::Create (
629631 const ::google::protobuf::RepeatedPtrField<
630- iamf_tools_cli_proto::AudioFrameObuMetadata>& audio_frame_metadata ,
632+ iamf_tools_cli_proto::AudioFrameObuMetadata>& audio_frame_metadatas ,
631633 const ::google::protobuf::RepeatedPtrField<
632- iamf_tools_cli_proto::CodecConfigObuMetadata>& codec_config_metadata ,
634+ iamf_tools_cli_proto::CodecConfigObuMetadata>& codec_config_metadatas ,
633635 const absl::flat_hash_map<DecodedUleb128, AudioElementWithData>&
634636 audio_elements,
635637 const DemixingModule& demixing_module,
636638 ParametersManager& parameters_manager,
637- GlobalTimingModule& global_timing_module)
638- : audio_elements_(audio_elements),
639- demixing_module_ (demixing_module),
640- parameters_manager_(parameters_manager),
641- global_timing_module_(global_timing_module),
642- // Set to a state NOT taking samples at first; may be changed to
643- // `kTakingSamples` once `Initialize()` is called.
644- state_( kFlushingRemaining ) {
645- for ( const auto & audio_frame_obu_metadata : audio_frame_metadata) {
646- audio_frame_metadata_[audio_frame_obu_metadata. audio_element_id ()] =
647- audio_frame_obu_metadata;
648- }
649-
650- for (const auto & codec_config_obu_metadata : codec_config_metadata ) {
651- codec_config_metadata_ [codec_config_obu_metadata.codec_config_id ()] =
639+ GlobalTimingModule& global_timing_module) {
640+ if (audio_frame_metadatas. empty ()) {
641+ // Ok, nothing will be generated. This state helps clients handle trivial IA
642+ // Sequences.
643+ return absl::WrapUnique (
644+ new AudioFrameGenerator ({}, {}, demixing_module, parameters_manager,
645+ global_timing_module, {}, {}, {}));
646+ }
647+
648+ // Mapping from Codec Config ID to additional codec config metadata used
649+ // to configure encoders.
650+ absl::flat_hash_map<DecodedUleb128, iamf_tools_cli_proto::CodecConfig>
651+ codec_config_metadata;
652+ for (const auto & codec_config_obu_metadata : codec_config_metadatas ) {
653+ codec_config_metadata [codec_config_obu_metadata.codec_config_id ()] =
652654 codec_config_obu_metadata.codec_config ();
653655 }
654- }
655-
656- absl::StatusOr<uint32_t > AudioFrameGenerator::GetNumberOfSamplesToDelayAtStart (
657- const iamf_tools_cli_proto::CodecConfig& codec_config_metadata,
658- const CodecConfigObu& codec_config) {
659- // This function is useful when querying what the codec delay should be. We
660- // don't want it to fail if the user-provided codec delay is wrong.
661- constexpr bool kDontValidateCodecDelay = false ;
662-
663- std::unique_ptr<EncoderBase> encoder;
664- RETURN_IF_NOT_OK (InitializeEncoder (codec_config_metadata, codec_config,
665- /* num_channels=*/ 1 , encoder,
666- kDontValidateCodecDelay ));
667- if (encoder == nullptr ) {
668- return absl::InvalidArgumentError (" Failed to initialize encoder" );
669- }
670- return encoder->GetNumberOfSamplesToDelayAtStart ();
671- }
672656
673- absl::Status AudioFrameGenerator::Initialize () {
674- absl::MutexLock lock (&mutex_);
675- if (audio_frame_metadata_.empty ()) {
676- return absl::OkStatus ();
677- }
678- const auto & first_audio_frame_metadata =
679- audio_frame_metadata_.begin ()->second ;
657+ const auto & first_audio_frame_metadata = *audio_frame_metadatas.begin ();
680658 const int64_t common_samples_to_trim_at_start = static_cast <int64_t >(
681659 first_audio_frame_metadata.samples_to_trim_at_start ());
682660 const int64_t common_samples_to_trim_at_end =
@@ -687,15 +665,23 @@ absl::Status AudioFrameGenerator::Initialize() {
687665 first_audio_frame_metadata
688666 .samples_to_trim_at_start_includes_codec_delay ();
689667
690- for (const auto & [audio_element_id, audio_frame_metadata] :
691- audio_frame_metadata_) {
668+ absl::flat_hash_map<DecodedUleb128, absl::flat_hash_set<ChannelLabel::Label>>
669+ audio_element_id_to_labels;
670+ absl::flat_hash_map<uint32_t , std::unique_ptr<EncoderBase>>
671+ substream_id_to_encoder;
672+ absl::flat_hash_map<uint32_t , SubstreamData> substream_id_to_substream_data;
673+ absl::flat_hash_map<uint32_t , TrimmingState> substream_id_to_trimming_state;
674+ for (const auto & audio_frame_metadata : audio_frame_metadatas) {
675+ const DecodedUleb128 audio_element_id =
676+ audio_frame_metadata.audio_element_id ();
677+
692678 // Precompute the `ChannelLabel::Label` for each channel label string.
693679 RETURN_IF_NOT_OK (ChannelLabelUtils::SelectConvertAndFillLabels (
694- audio_frame_metadata, audio_element_id_to_labels_ [audio_element_id]));
680+ audio_frame_metadata, audio_element_id_to_labels [audio_element_id]));
695681
696682 // Find the Codec Config OBU for this mono or coupled stereo substream.
697- const auto audio_elements_iter = audio_elements_ .find (audio_element_id);
698- if (audio_elements_iter == audio_elements_ .end ()) {
683+ const auto audio_elements_iter = audio_elements .find (audio_element_id);
684+ if (audio_elements_iter == audio_elements .end ()) {
699685 return absl::InvalidArgumentError (absl::StrCat (
700686 " Audio Element with ID= " , audio_element_id, " not found" ));
701687 }
@@ -710,25 +696,25 @@ absl::Status AudioFrameGenerator::Initialize() {
710696 " The spec disallows trimming multiple frames from the end." );
711697 }
712698 RETURN_IF_NOT_OK (GetEncodingDataAndInitializeEncoders (
713- codec_config_metadata_ , audio_element_with_data,
714- substream_id_to_encoder_ ));
699+ codec_config_metadata , audio_element_with_data,
700+ substream_id_to_encoder ));
715701
716702 // Intermediate data for all substreams belonging to an Audio Element.
717703 RETURN_IF_NOT_OK (InitializeSubstreamData (
718- audio_element_with_data.substream_id_to_labels ,
719- substream_id_to_encoder_, num_samples_per_frame,
704+ audio_element_with_data.substream_id_to_labels , substream_id_to_encoder,
705+ num_samples_per_frame,
720706 audio_frame_metadata.samples_to_trim_at_start_includes_codec_delay (),
721707 audio_frame_metadata.samples_to_trim_at_start (),
722- substream_id_to_substream_data_ ));
708+ substream_id_to_substream_data ));
723709
724710 // Validate that a `DemixingParamDefinition` is available if down-mixing
725711 // is needed.
726712 absl::StatusOr<const std::list<Demixer>*> down_mixers =
727- demixing_module_ .GetDownMixers (audio_element_id);
713+ demixing_module .GetDownMixers (audio_element_id);
728714 if (!down_mixers.ok ()) {
729715 return down_mixers.status ();
730716 }
731- if (!parameters_manager_ .DemixingParamDefinitionAvailable (
717+ if (!parameters_manager .DemixingParamDefinitionAvailable (
732718 audio_element_id) &&
733719 !(*down_mixers)->empty ()) {
734720 return absl::InvalidArgumentError (
@@ -749,9 +735,9 @@ absl::Status AudioFrameGenerator::Initialize() {
749735 const int64_t additional_samples_to_trim_at_start =
750736 common_samples_to_trim_at_start_includes_codec_delay
751737 ? 0
752- : substream_id_to_encoder_ [substream_id]
738+ : substream_id_to_encoder [substream_id]
753739 ->GetNumberOfSamplesToDelayAtStart ();
754- substream_id_to_trimming_state_ [substream_id] = {
740+ substream_id_to_trimming_state [substream_id] = {
755741 .increment_samples_to_trim_at_end_by_padding =
756742 !audio_frame_metadata.samples_to_trim_at_end_includes_padding (),
757743 .user_samples_left_to_trim_at_end = common_samples_to_trim_at_end,
@@ -762,13 +748,29 @@ absl::Status AudioFrameGenerator::Initialize() {
762748 }
763749 }
764750
765- // If `substream_id_to_substream_data_` is not empty, meaning this generator
766- // is expecting audio substreams and is ready to take audio samples.
767- if (!substream_id_to_substream_data_.empty ()) {
768- state_ = kTakingSamples ;
769- }
751+ return absl::WrapUnique (new AudioFrameGenerator (
752+ audio_element_id_to_labels, audio_elements, demixing_module,
753+ parameters_manager, global_timing_module,
754+ std::move (substream_id_to_encoder),
755+ std::move (substream_id_to_substream_data),
756+ std::move (substream_id_to_trimming_state)));
757+ }
770758
771- return absl::OkStatus ();
759+ absl::StatusOr<uint32_t > AudioFrameGenerator::GetNumberOfSamplesToDelayAtStart (
760+ const iamf_tools_cli_proto::CodecConfig& codec_config_metadata,
761+ const CodecConfigObu& codec_config) {
762+ // This function is useful when querying what the codec delay should be. We
763+ // don't want it to fail if the user-provided codec delay is wrong.
764+ constexpr bool kDontValidateCodecDelay = false ;
765+
766+ std::unique_ptr<EncoderBase> encoder;
767+ RETURN_IF_NOT_OK (InitializeEncoder (codec_config_metadata, codec_config,
768+ /* num_channels=*/ 1 , encoder,
769+ kDontValidateCodecDelay ));
770+ if (encoder == nullptr ) {
771+ return absl::InvalidArgumentError (" Failed to initialize encoder" );
772+ }
773+ return encoder->GetNumberOfSamplesToDelayAtStart ();
772774}
773775
774776bool AudioFrameGenerator::TakingSamples () const {
0 commit comments