diff --git a/src/projects/transcoder/transcoder_stream.cpp b/src/projects/transcoder/transcoder_stream.cpp index 5758a3cb4..7d7a762fa 100644 --- a/src/projects/transcoder/transcoder_stream.cpp +++ b/src/projects/transcoder/transcoder_stream.cpp @@ -231,7 +231,7 @@ bool TranscoderStream::PrepareInternal() logti("No decoder generated"); } - StoreInputTrackSnapshot(_input_stream); + StoreTracks(_input_stream); return true; } @@ -244,9 +244,9 @@ bool TranscoderStream::UpdateInternal(const std::shared_ptr &strea // - The input track should not change. _is_updating = true; - if (IsAvailableSmoothTransition(stream) == true) + if (CanSeamlessTransition(stream) == true) { - logtd("%s This stream will be a smooth transition", _log_prefix.CStr()); + logtd("%s This stream support seamless transitions", _log_prefix.CStr()); FlushBuffers(); RemoveDecoders(); @@ -256,7 +256,7 @@ bool TranscoderStream::UpdateInternal(const std::shared_ptr &strea } else { - logtw("%s This stream does not support smooth transitions. renew the all components", _log_prefix.CStr()); + logtw("%s This stream does not support seamless transitions. Renewing all", _log_prefix.CStr()); FlushBuffers(); @@ -269,7 +269,7 @@ bool TranscoderStream::UpdateInternal(const std::shared_ptr &strea UpdateMsidOfOutputStreams(stream->GetMsid()); NotifyUpdateStreams(); - StoreInputTrackSnapshot(stream); + StoreTracks(stream); } _is_updating = false; @@ -389,24 +389,12 @@ std::shared_ptr TranscoderStream::GetOutputStreamByTrackId(MediaTr return nullptr; } -bool TranscoderStream::IsAvailableSmoothTransition(const std::shared_ptr &input_stream) +bool TranscoderStream::CanSeamlessTransition(const std::shared_ptr &input_stream) { - // #1. The number of tracks per media type should not exceed one. - int32_t track_count_per_mediatype[(uint32_t)cmn::MediaType::Nb] = {0}; - for (const auto &[track_id, track] : input_stream->GetTracks()) - { - UNUSED_VARIABLE(track_id) - - if ((++track_count_per_mediatype[(uint32_t)track->GetMediaType()]) > 1) - { - // Could not support smooth transition. because, number of tracks per media type exceed one. - logtw("%s Smooth transitions are not possible because the number of tracks per media type exceeds one.", _log_prefix.CStr()); - return false; - } - } + auto new_tracks = input_stream->GetTracks(); - // #2. Check if the number and type of original tracks are different. - if(IsEqualCountAndMediaTypeOfMediaTracks(input_stream->GetTracks(), GetInputTrackSnapshot()) == false) + // Check if the number and type of original tracks are different. + if(CompareTracksForSeamlessTransition(new_tracks, GetStoredTracks()) == false) { logtw("%s The input track has changed. It does not support smooth transitions.", _log_prefix.CStr()); return false; @@ -1509,8 +1497,8 @@ void TranscoderStream::OnDecodedFrame(TranscodeResult result, MediaTrackId decod // Record the timestamp of the last decoded frame. managed by microseconds. _last_decoded_frame_pts[decoder_id] = last_frame->GetPts() * filter_expr * 1000000.0; - logtd("%s Create filler frame because there is no decoding frame. Type(%s), Decoder(%u), FillerFrames(%d)" - , _log_prefix.CStr(), cmn::GetMediaTypeString(input_track->GetMediaType()).CStr(), decoder_id, 1); + // logtd("%s Create filler frame because there is no decoding frame. Type(%s), Decoder(%u), FillerFrames(%d)" + // , _log_prefix.CStr(), cmn::GetMediaTypeString(input_track->GetMediaType()).CStr(), decoder_id, 1); // Send Temporary Frame to Filter SpreadToFilters(decoder_id, last_frame); @@ -1600,7 +1588,7 @@ void TranscoderStream::OnDecodedFrame(TranscodeResult result, MediaTrackId decod } SpreadToFilters(decoder_id, clone_frame); - // logte("%s Create filler frame. Type(%s), %s", _log_prefix.CStr(), cmn::GetMediaTypeString(input_track->GetMediaType()).CStr(), clone_frame->GetInfoString().CStr()); + // logtd("%s Create filler frame. Type(%s), %s", _log_prefix.CStr(), cmn::GetMediaTypeString(input_track->GetMediaType()).CStr(), clone_frame->GetInfoString().CStr()); } } } @@ -1610,6 +1598,7 @@ void TranscoderStream::OnDecodedFrame(TranscodeResult result, MediaTrackId decod } case TranscodeResult::DataReady: { + // The last decoded frame is kept and used as a filling frame in the blank section. SetLastDecodedFrame(decoder_id, decoded_frame); diff --git a/src/projects/transcoder/transcoder_stream.h b/src/projects/transcoder/transcoder_stream.h index b4e13cca0..576442d0d 100644 --- a/src/projects/transcoder/transcoder_stream.h +++ b/src/projects/transcoder/transcoder_stream.h @@ -248,7 +248,7 @@ class TranscoderStream : public ov::EnableSharedFromThis, publ void UpdateInputTrack(std::shared_ptr buffer); void UpdateOutputTrack(std::shared_ptr buffer); void UpdateMsidOfOutputStreams(uint32_t msid); - bool IsAvailableSmoothTransition(const std::shared_ptr &stream); + bool CanSeamlessTransition(const std::shared_ptr &stream); void FlushBuffers(); // Step 2: Filter (resample/rescale the decoded frame) diff --git a/src/projects/transcoder/transcoder_stream_internal.cpp b/src/projects/transcoder/transcoder_stream_internal.cpp index c3df517ac..5eeabbf9b 100644 --- a/src/projects/transcoder/transcoder_stream_internal.cpp +++ b/src/projects/transcoder/transcoder_stream_internal.cpp @@ -756,41 +756,41 @@ void TranscoderStreamInternal::UpdateOutputTrackTranscode(const std::shared_ptr< } } -bool TranscoderStreamInternal::StoreInputTrackSnapshot(std::shared_ptr stream) +bool TranscoderStreamInternal::StoreTracks(std::shared_ptr stream) { - _input_track_snapshot.clear(); + _store_tracks.clear(); for (auto &[track_id, track] : stream->GetTracks()) { auto clone = track->Clone(); - _input_track_snapshot[track_id] = clone; + _store_tracks[track_id] = clone; } return true; } -std::map>& TranscoderStreamInternal::GetInputTrackSnapshot() +std::map>& TranscoderStreamInternal::GetStoredTracks() { - return _input_track_snapshot; + return _store_tracks; } -bool TranscoderStreamInternal::IsEqualCountAndMediaTypeOfMediaTracks(std::map> a, std::map> b) +bool TranscoderStreamInternal::CompareTracksForSeamlessTransition(std::map> prev_tracks, std::map> new_tracks) { - if (a.size() != b.size()) + // #1 Check the number of tracks + if (prev_tracks.size() != new_tracks.size()) { return false; } - for (auto &[track_id, track] : a) + // #2 Check type of tracks + for (auto &[track_id, prev_track] : prev_tracks) { - if (b.find(track_id) == b.end()) + if (new_tracks.find(track_id) == new_tracks.end()) { return false; } - auto track_b = b[track_id]; - - if(track->GetMediaType() != track_b->GetMediaType()) + if(prev_track->GetMediaType() != new_tracks[track_id]->GetMediaType()) { return false; } diff --git a/src/projects/transcoder/transcoder_stream_internal.h b/src/projects/transcoder/transcoder_stream_internal.h index 102fc96b4..3a3e75f11 100644 --- a/src/projects/transcoder/transcoder_stream_internal.h +++ b/src/projects/transcoder/transcoder_stream_internal.h @@ -60,13 +60,11 @@ class TranscoderStreamInternal uint32_t &audio, uint32_t &audio_bypass, uint32_t &image, uint32_t &data); - public: - // For the purpose of checking if the input track has changed during the update. - bool StoreInputTrackSnapshot(std::shared_ptr stream); - std::map>& GetInputTrackSnapshot(); - bool IsEqualCountAndMediaTypeOfMediaTracks(std::map> a, std::map> b); + // This is used to check if the input track has changed during the update. + bool StoreTracks(std::shared_ptr stream); + std::map> &GetStoredTracks(); + bool CompareTracksForSeamlessTransition(std::map> prev_tracks, std::map> new_tracks); -private: - std::map> _input_track_snapshot; + std::map> _store_tracks; };