diff --git a/src/projects/base/info/audio_map_item.h b/src/projects/base/info/audio_map_item.h index 9ba682e31..848487708 100644 --- a/src/projects/base/info/audio_map_item.h +++ b/src/projects/base/info/audio_map_item.h @@ -58,6 +58,6 @@ namespace info private: int _index; ov::String _name; - ov::String _language; + ov::String _language = "und"; }; } // namespace info \ No newline at end of file diff --git a/src/projects/providers/scheduled/schedule.cpp b/src/projects/providers/scheduled/schedule.cpp index bf0d70b63..7f3093d69 100644 --- a/src/projects/providers/scheduled/schedule.cpp +++ b/src/projects/providers/scheduled/schedule.cpp @@ -141,6 +141,57 @@ namespace pvd _stream = MakeStream(name, bypass_transcoder, video_track, audio_track); + // audioMap + + /* + "audioMap": [ + { + "name": "Korean", + "language": "kor" + }, + { + "name": "English", + "language": "eng" + } + ] + + for (uint32_t i=0; i(i), public_name, language}); + } + } + return true; } @@ -422,6 +473,42 @@ namespace pvd _stream = MakeStream(name, bypass_transcoder, video_track, audio_track); + // Optional + /* + + + Korean + kor + + + English + eng + + + */ + auto audio_map_node = stream_node.child("AudioMap"); + uint32_t index = 0; + for (auto audio_map_item_node = audio_map_node.child("Item"); audio_map_item_node; audio_map_item_node = audio_map_item_node.next_sibling("Item")) + { + ov::String public_name; + ov::String language; + + auto public_name_node = audio_map_item_node.child("Name"); + if (public_name_node) + { + public_name = public_name_node.text().as_string(); + } + + auto language_node = audio_map_item_node.child("Language"); + if (language_node) + { + language = language_node.text().as_string(); + } + + _stream.audio_map.push_back({static_cast(index), public_name, language}); + index ++; + } + return true; } diff --git a/src/projects/providers/scheduled/schedule.h b/src/projects/providers/scheduled/schedule.h index 36b7c0281..12b453944 100644 --- a/src/projects/providers/scheduled/schedule.h +++ b/src/projects/providers/scheduled/schedule.h @@ -10,6 +10,7 @@ #include #include +#include #include /* @@ -100,6 +101,8 @@ namespace pvd bool bypass_transcoder = false; bool video_track = true; bool audio_track = true; + + std::vector audio_map; }; struct Program diff --git a/src/projects/providers/scheduled/scheduled_application.cpp b/src/projects/providers/scheduled/scheduled_application.cpp index 29c16719d..6b8c4fe2b 100644 --- a/src/projects/providers/scheduled/scheduled_application.cpp +++ b/src/projects/providers/scheduled/scheduled_application.cpp @@ -206,16 +206,41 @@ namespace pvd if (channel_info.audio_track == true) { - auto track = std::make_shared(); - track->SetId(kScheduledAudioTrackId); - auto public_name = ov::String::FormatString("Audio_%d", track->GetId()); - track->SetPublicName(public_name); - track->SetMediaType(cmn::MediaType::Audio); - - // Set Timebase to 1/1000 fixed - track->SetTimeBase(1, 1000); - - stream->AddTrack(track); + if (channel_info.audio_map.empty()) + { + auto track = std::make_shared(); + track->SetId(kScheduledAudioTrackId); + auto public_name = ov::String::FormatString("Audio_%d", track->GetId()); + track->SetPublicName(public_name); + track->SetMediaType(cmn::MediaType::Audio); + + // Set Timebase to 1/1000 fixed + track->SetTimeBase(1, 1000); + + stream->AddTrack(track); + } + else + { + for (const auto &audio_map_item : channel_info.audio_map) + { + auto track = std::make_shared(); + track->SetId(kScheduledAudioTrackId + audio_map_item.GetIndex()); + + ov::String public_name = audio_map_item.GetName(); + if (public_name.IsEmpty()) + { + public_name = ov::String::FormatString("Audio_%d", track->GetId()); + } + track->SetPublicName(public_name); + track->SetLanguage(audio_map_item.GetLanguage()); + track->SetMediaType(cmn::MediaType::Audio); + + // Set Timebase to 1/1000 fixed + track->SetTimeBase(1, 1000); + + stream->AddTrack(track); + } + } } if (AddStream(stream) == false) diff --git a/src/projects/providers/scheduled/scheduled_stream.cpp b/src/projects/providers/scheduled/scheduled_stream.cpp index 5f8fbef82..cd644bbc5 100644 --- a/src/projects/providers/scheduled/scheduled_stream.cpp +++ b/src/projects/providers/scheduled/scheduled_stream.cpp @@ -528,6 +528,7 @@ namespace pvd auto single_file_dts = dts - track_single_file_dts_offset_map[track_id]; AdjustTimestampByBase(track_id, pts, dts, std::numeric_limits::max(), duration); + logtd("Scheduled Channel Send Packet : %s/%s: Track %d, origin dts : %lld, pts %lld, dts %lld, duration %lld, tb %f", GetApplicationName(), GetName().CStr(), track_id, single_file_dts, pts, dts, duration, track->GetTimeBase().GetExpr()); media_packet->SetPts(pts); media_packet->SetDts(dts); @@ -714,6 +715,7 @@ namespace pvd bool video_track_needed = _channel_info.video_track; bool audio_track_needed = _channel_info.audio_track; + uint32_t audio_index = 0; int64_t total_duration_ms = 0; _origin_id_track_id_map.clear(); for (uint32_t track_id = 0; track_id < format_context->nb_streams; track_id++) @@ -763,9 +765,15 @@ namespace pvd continue; } - new_track->SetId(kScheduledAudioTrackId); + auto audio_track_id = kScheduledAudioTrackId + audio_index; + audio_index++; + auto old_track = GetTrack(audio_track_id); + + new_track->SetId(audio_track_id); new_track->SetTimeBase(1, new_track->GetSampleRate()); - _origin_id_track_id_map.emplace(stream->index, kScheduledAudioTrackId); + new_track->SetPublicName(old_track->GetPublicName()); + new_track->SetLanguage(old_track->GetLanguage()); + _origin_id_track_id_map.emplace(stream->index, audio_track_id); UpdateTrack(new_track); if (total_duration_ms == 0) @@ -776,8 +784,11 @@ namespace pvd { total_duration_ms = std::min(total_duration_ms, (int64_t)(stream->duration * 1000 * ::av_q2d(stream->time_base))); } - - audio_track_needed = false; + + if (audio_index + 1 > _channel_info.audio_map.size()) + { + audio_track_needed = false; + } } else { @@ -1116,6 +1127,7 @@ namespace pvd _origin_id_track_id_map.clear(); bool video_track_needed = _channel_info.video_track; bool audio_track_needed = _channel_info.audio_track; + uint32_t audio_index = 0; for (const auto &[track_id, track] : stream_tap->GetStreamInfo()->GetTracks()) { if (video_track_needed == false && audio_track_needed == false) @@ -1147,13 +1159,19 @@ namespace pvd { continue; } + + auto audio_track_id = kScheduledAudioTrackId + audio_index; + audio_index++; - new_track->SetId(kScheduledAudioTrackId); + new_track->SetId(audio_track_id); new_track->SetTimeBase(1, new_track->GetSampleRate()); - _origin_id_track_id_map.emplace(track_id, kScheduledAudioTrackId); + _origin_id_track_id_map.emplace(track_id, audio_track_id); UpdateTrack(new_track); - - audio_track_needed = false; + + if (audio_index + 1 > _channel_info.audio_map.size()) + { + audio_track_needed = false; + } } else { diff --git a/src/projects/providers/scheduled/scheduled_stream.h b/src/projects/providers/scheduled/scheduled_stream.h index 5c2979c37..a2e211e8f 100644 --- a/src/projects/providers/scheduled/scheduled_stream.h +++ b/src/projects/providers/scheduled/scheduled_stream.h @@ -19,8 +19,8 @@ namespace pvd { // ScheduledStream doesn't support multiple tracks yet constexpr int kScheduledVideoTrackId = 0; - constexpr int kScheduledAudioTrackId = 1; - constexpr int kScheduledDataTrackId = 2; + constexpr int kScheduledAudioTrackId = 100; + constexpr int kScheduledDataTrackId = 200; constexpr int kScheduledVideoTimebase = 90000; class ScheduledStream : public Stream diff --git a/src/projects/publishers/llhls/llhls_master_playlist.cpp b/src/projects/publishers/llhls/llhls_master_playlist.cpp index 4645e6d01..6e752b556 100644 --- a/src/projects/publishers/llhls/llhls_master_playlist.cpp +++ b/src/projects/publishers/llhls/llhls_master_playlist.cpp @@ -70,7 +70,7 @@ bool LLHlsMasterPlaylist::AddStreamInfo(const ov::String &video_group_id, int vi if (video_group_id.IsEmpty() == false) { auto video_group = GetMediaGroup(video_group_id); - if (video_group == nullptr || video_group->_media_infos.size() <= video_index_hint) + if (video_group == nullptr || video_group->_media_infos.size() <= static_cast(video_index_hint)) { logte("Could not find valid video group: %s", video_group_id.CStr()); return false;