diff --git a/packager/media/event/combined_muxer_listener.cc b/packager/media/event/combined_muxer_listener.cc index 05a461fea9..f1b2ea5953 100644 --- a/packager/media/event/combined_muxer_listener.cc +++ b/packager/media/event/combined_muxer_listener.cc @@ -9,56 +9,49 @@ namespace shaka { namespace media { -CombinedMuxerListener::CombinedMuxerListener( - std::list>* muxer_listeners) { - DCHECK(muxer_listeners); - muxer_listeners_.swap(*muxer_listeners); +void CombinedMuxerListener::AddListener( + std::unique_ptr listener) { + muxer_listeners_.push_back(std::move(listener)); } -CombinedMuxerListener::~CombinedMuxerListener() {} - void CombinedMuxerListener::OnEncryptionInfoReady( bool is_initial_encryption_info, FourCC protection_scheme, const std::vector& key_id, const std::vector& iv, const std::vector& key_system_info) { - for (auto& listener: muxer_listeners_) { + for (auto& listener : muxer_listeners_) { listener->OnEncryptionInfoReady(is_initial_encryption_info, - protection_scheme, - key_id, - iv, + protection_scheme, key_id, iv, key_system_info); } } void CombinedMuxerListener::OnEncryptionStart() { - for (auto& listener: muxer_listeners_) { + for (auto& listener : muxer_listeners_) { listener->OnEncryptionStart(); } } -void CombinedMuxerListener::OnMediaStart( - const MuxerOptions& muxer_options, - const StreamInfo& stream_info, - uint32_t time_scale, - ContainerType container_type) { - for (auto& listener: muxer_listeners_) { - listener->OnMediaStart( - muxer_options, stream_info, time_scale, container_type); +void CombinedMuxerListener::OnMediaStart(const MuxerOptions& muxer_options, + const StreamInfo& stream_info, + uint32_t time_scale, + ContainerType container_type) { + for (auto& listener : muxer_listeners_) { + listener->OnMediaStart(muxer_options, stream_info, time_scale, + container_type); } } -void CombinedMuxerListener::OnSampleDurationReady( - uint32_t sample_duration) { - for (auto& listener: muxer_listeners_) { +void CombinedMuxerListener::OnSampleDurationReady(uint32_t sample_duration) { + for (auto& listener : muxer_listeners_) { listener->OnSampleDurationReady(sample_duration); } } void CombinedMuxerListener::OnMediaEnd(const MediaRanges& media_ranges, float duration_seconds) { - for (auto& listener: muxer_listeners_) { + for (auto& listener : muxer_listeners_) { listener->OnMediaEnd(media_ranges, duration_seconds); } } @@ -67,7 +60,7 @@ void CombinedMuxerListener::OnNewSegment(const std::string& file_name, uint64_t start_time, uint64_t duration, uint64_t segment_file_size) { - for (auto& listener: muxer_listeners_) { + for (auto& listener : muxer_listeners_) { listener->OnNewSegment(file_name, start_time, duration, segment_file_size); } } diff --git a/packager/media/event/combined_muxer_listener.h b/packager/media/event/combined_muxer_listener.h index 46d57d78ba..e48d98912d 100644 --- a/packager/media/event/combined_muxer_listener.h +++ b/packager/media/event/combined_muxer_listener.h @@ -17,9 +17,9 @@ namespace media { class CombinedMuxerListener : public MuxerListener { public: - explicit CombinedMuxerListener( - std::list>* muxer_listeners); - ~CombinedMuxerListener() override; + CombinedMuxerListener() = default; + + void AddListener(std::unique_ptr listener); void OnEncryptionInfoReady(bool is_initial_encryption_info, FourCC protection_scheme, diff --git a/packager/packager.cc b/packager/packager.cc index 4f2564a008..fdac16697d 100644 --- a/packager/packager.cc +++ b/packager/packager.cc @@ -272,7 +272,6 @@ class Job : public base::SimpleThread { }; bool StreamInfoToTextMediaInfo(const StreamDescriptor& stream_descriptor, - const MuxerOptions& stream_muxer_options, MediaInfo* text_media_info) { const std::string& language = stream_descriptor.language; const std::string format = DetermineTextFileFormat(stream_descriptor.input); @@ -283,18 +282,17 @@ bool StreamInfoToTextMediaInfo(const StreamDescriptor& stream_descriptor, } if (!File::Copy(stream_descriptor.input.c_str(), - stream_muxer_options.output_file_name.c_str())) { + stream_descriptor.output.c_str())) { LOG(ERROR) << "Failed to copy the input file (" << stream_descriptor.input - << ") to output file (" << stream_muxer_options.output_file_name - << ")."; + << ") to output file (" << stream_descriptor.output << ")."; return false; } - text_media_info->set_media_file_name(stream_muxer_options.output_file_name); + text_media_info->set_media_file_name(stream_descriptor.output); text_media_info->set_container_type(MediaInfo::CONTAINER_TEXT); - if (stream_muxer_options.bandwidth != 0) { - text_media_info->set_bandwidth(stream_muxer_options.bandwidth); + if (stream_descriptor.bandwidth != 0) { + text_media_info->set_bandwidth(stream_descriptor.bandwidth); } else { // Text files are usually small and since the input is one file; there's no // way for the player to do ranged requests. So set this value to something @@ -311,16 +309,93 @@ bool StreamInfoToTextMediaInfo(const StreamDescriptor& stream_descriptor, return true; } -std::shared_ptr CreateOutputMuxer(const MuxerOptions& options, - MediaContainerName container) { - if (container == CONTAINER_WEBM) { - return std::shared_ptr(new webm::WebMMuxer(options)); - } else if (container == CONTAINER_MPEG2TS) { - return std::shared_ptr(new mp2t::TsMuxer(options)); - } else { - DCHECK_EQ(container, CONTAINER_MOV); - return std::shared_ptr(new mp4::MP4Muxer(options)); +std::unique_ptr CreateMuxerListener( + const StreamDescriptor& stream, + int stream_number, + bool output_media_info, + MpdNotifier* mpd_notifier, + hls::HlsNotifier* hls_notifier) { + std::unique_ptr combined_listener( + new CombinedMuxerListener); + + if (output_media_info) { + std::unique_ptr listener( + new VodMediaInfoDumpMuxerListener(stream.output + kMediaInfoSuffix)); + combined_listener->AddListener(std::move(listener)); } + + if (mpd_notifier) { + std::unique_ptr listener( + new MpdNotifyMuxerListener(mpd_notifier)); + combined_listener->AddListener(std::move(listener)); + } + + if (hls_notifier) { + // TODO(rkuroiwa): Do some smart stuff to group the audios, e.g. detect + // languages. + std::string group_id = stream.hls_group_id; + std::string name = stream.hls_name; + std::string hls_playlist_name = stream.hls_playlist_name; + if (group_id.empty()) + group_id = "audio"; + if (name.empty()) + name = base::StringPrintf("stream_%d", stream_number); + if (hls_playlist_name.empty()) + hls_playlist_name = base::StringPrintf("stream_%d.m3u8", stream_number); + + std::unique_ptr listener(new HlsNotifyMuxerListener( + hls_playlist_name, name, group_id, hls_notifier)); + combined_listener->AddListener(std::move(listener)); + } + + return std::move(combined_listener); +} + +std::shared_ptr CreateMuxer(const PackagingParams& packaging_params, + const StreamDescriptor& stream, + base::Clock* clock, + std::unique_ptr listener) { + const MediaContainerName format = GetOutputFormat(stream); + + MuxerOptions options; + options.mp4_params = packaging_params.mp4_output_params; + options.temp_dir = packaging_params.temp_dir; + options.bandwidth = stream.bandwidth; + options.output_file_name = stream.output; + options.segment_template = stream.segment_template; + + std::shared_ptr muxer; + + switch (format) { + case CONTAINER_WEBM: + muxer = std::make_shared(options); + break; + case CONTAINER_MPEG2TS: + muxer = std::make_shared(options); + break; + case CONTAINER_MOV: + muxer = std::make_shared(options); + break; + default: + LOG(ERROR) << "Cannot support muxing to " << format; + break; + } + + if (!muxer) { + return nullptr; + } + + // We successfully created a muxer, then there is a couple settings + // we should set before returning it. + if (clock) { + muxer->set_clock(clock); + } + + if (listener) { + muxer->SetMuxerListener(std::move(listener)); + } + + return muxer; } std::shared_ptr CreateCryptoHandler( @@ -399,8 +474,7 @@ Status CreateRemuxJobs(const StreamDescriptorList& stream_descriptors, if (stream_iter->stream_selector == "text" && output_format != CONTAINER_MOV) { MediaInfo text_media_info; - if (!StreamInfoToTextMediaInfo(*stream_iter, stream_muxer_options, - &text_media_info)) { + if (!StreamInfoToTextMediaInfo(*stream_iter, &text_media_info)) { return Status(error::INVALID_ARGUMENT, "Could not create media info for stream."); } @@ -414,8 +488,7 @@ Status CreateRemuxJobs(const StreamDescriptorList& stream_descriptors, } } else if (packaging_params.output_media_info) { VodMediaInfoDumpMuxerListener::WriteMediaInfoToFile( - text_media_info, - stream_muxer_options.output_file_name + kMediaInfoSuffix); + text_media_info, stream_iter->output + kMediaInfoSuffix); } continue; } @@ -455,45 +528,19 @@ Status CreateRemuxJobs(const StreamDescriptorList& stream_descriptors, trick_play_handler.reset(); } - std::shared_ptr muxer( - CreateOutputMuxer(stream_muxer_options, output_format)); - if (packaging_params.test_params.inject_fake_clock) - muxer->set_clock(fake_clock); + // Create the muxer (output) for this track. + std::unique_ptr muxer_listener = CreateMuxerListener( + *stream_iter, stream_number, packaging_params.output_media_info, + mpd_notifier, hls_notifier); + std::shared_ptr muxer = CreateMuxer( + packaging_params, *stream_iter, + packaging_params.test_params.inject_fake_clock ? fake_clock : nullptr, + std::move(muxer_listener)); - std::list> muxer_listeners; - DCHECK(!(packaging_params.output_media_info && mpd_notifier)); - if (packaging_params.output_media_info) { - const std::string output_media_info_file_name = - stream_muxer_options.output_file_name + kMediaInfoSuffix; - muxer_listeners.emplace_back( - new VodMediaInfoDumpMuxerListener(output_media_info_file_name)); - } - - if (mpd_notifier) { - muxer_listeners.emplace_back(new MpdNotifyMuxerListener(mpd_notifier)); - } - - if (hls_notifier) { - // TODO(rkuroiwa): Do some smart stuff to group the audios, e.g. detect - // languages. - std::string group_id = stream_iter->hls_group_id; - std::string name = stream_iter->hls_name; - std::string hls_playlist_name = stream_iter->hls_playlist_name; - if (group_id.empty()) - group_id = "audio"; - if (name.empty()) - name = base::StringPrintf("stream_%d", stream_number); - if (hls_playlist_name.empty()) - hls_playlist_name = base::StringPrintf("stream_%d.m3u8", stream_number); - - muxer_listeners.emplace_back(new HlsNotifyMuxerListener( - hls_playlist_name, name, group_id, hls_notifier)); - } - - if (!muxer_listeners.empty()) { - std::unique_ptr combined_muxer_listener( - new CombinedMuxerListener(&muxer_listeners)); - muxer->SetMuxerListener(std::move(combined_muxer_listener)); + if (!muxer) { + return Status(error::INVALID_ARGUMENT, "Failed to create muxer for " + + stream_iter->input + ":" + + stream_iter->stream_selector); } // Create a new trick_play_handler. Note that the stream_decriptors