New support for AUDIO

Allows looking for audio streams in media files (settings) and enabling  / disabling audio for each MediaPlayer individually. Control of volume per media, saving in session file.
This commit is contained in:
Bruno Herbelin
2023-10-28 12:58:17 +02:00
parent f19b18d806
commit 5a1a88bf33
9 changed files with 142 additions and 6 deletions

View File

@@ -743,9 +743,13 @@ void ImGuiVisitor::visit (MediaSource& s)
{
if (ImGui::Selectable( ICON_FA_MICROCHIP " / " ICON_FA_COGS " Auto select", &hwdec ))
mp->setSoftwareDecodingForced(false);
if (ImGui::IsItemHovered() && !hwdec)
ImGuiToolkit::ToolTip( "Changing decoding will\nre-open the media" );
hwdec = mp->softwareDecodingForced();
if (ImGui::Selectable( ICON_FA_COGS " Software only", &hwdec ))
mp->setSoftwareDecodingForced(true);
if (ImGui::IsItemHovered() && !hwdec)
ImGuiToolkit::ToolTip( "Changing decoding will\nre-open the media" );
ImGui::EndCombo();
}
}
@@ -756,6 +760,47 @@ void ImGuiVisitor::visit (MediaSource& s)
ImGui::TextDisabled("Hardware decoding disabled");
}
// enable / disable audio if available
if (mp->audioAvailable()) {
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if (ImGui::BeginCombo("Audio", mp->audioEnabled() ? ICON_FA_VOLUME_UP " Enabled" : ICON_FA_VOLUME_MUTE " Disabled" ) )
{
if (ImGui::Selectable( ICON_FA_VOLUME_UP " Enable", mp->audioEnabled() ))
mp->setAudioEnabled(true);
if (ImGui::IsItemHovered() && !mp->audioEnabled())
ImGuiToolkit::ToolTip( "Changing audio will\nre-open the media" );
if (ImGui::Selectable( ICON_FA_VOLUME_MUTE " Disable", !mp->audioEnabled() ))
mp->setAudioEnabled(false);
if (ImGui::IsItemHovered() && mp->audioEnabled())
ImGuiToolkit::ToolTip( "Changing audio will\nre-open the media" );
ImGui::EndCombo();
}
if (mp->audioEnabled()) {
ImGuiIO& io = ImGui::GetIO();
///
/// AUDIO VOLUME
///
int vol = mp->audioVolume();
ImGui::SetNextItemWidth(IMGUI_RIGHT_ALIGN);
if ( ImGui::SliderInt("##Volume", &vol, 0, 100, "%d%%") )
mp->setAudioVolume(vol);
if (ImGui::IsItemHovered() && io.MouseWheel != 0.f ){
vol = CLAMP(vol + int(10.f * io.MouseWheel), 0, 100);
mp->setAudioVolume(vol);
}
ImGui::SameLine(0, IMGUI_SAME_LINE);
if (ImGuiToolkit::TextButton("Volume")) {
mp->setAudioVolume(100);
}
}
}
}
}

View File

@@ -30,6 +30,7 @@
#include "BaseToolkit.h"
#include "GstToolkit.h"
#include "Metronome.h"
#include "Settings.h"
#include "MediaPlayer.h"
@@ -72,6 +73,10 @@ MediaPlayer::MediaPlayer()
position_ = GST_CLOCK_TIME_NONE;
loop_ = LoopMode::LOOP_REWIND;
// default audio disabled
audio_enabled_ = false;
audio_volume_ = 100;
// start index in frame_ stack
write_index_ = 0;
last_index_ = 0;
@@ -241,6 +246,11 @@ MediaInfo MediaPlayer::UriDiscoverer(const std::string &uri)
video_stream_info.log = "No video stream";
gst_discoverer_stream_info_list_free(streams);
// test audio
GList *audios = gst_discoverer_info_get_audio_streams(info);
video_stream_info.hasaudio = g_list_length(audios) > 0 && Settings::application.accept_audio;
gst_discoverer_stream_info_list_free(audios);
}
if (info)
@@ -347,6 +357,8 @@ void MediaPlayer::execute_open()
gint flags;
// ENABLE ONLY VIDEO, NOT AUDIO AND TEXT SUBTITLES
flags = GST_PLAY_FLAG_VIDEO;
if (media_.hasaudio && audio_enabled_)
flags |= GST_PLAY_FLAG_AUDIO;
// ENABLE DEINTERLACING
if (media_.interlaced)
flags |= GST_PLAY_FLAG_DEINTERLACE;
@@ -467,6 +479,9 @@ void MediaPlayer::execute_open()
Log::Info("MediaPlayer %s Timeline [%ld %ld] %ld frames, %d gaps", std::to_string(id_).c_str(),
timeline_.begin(), timeline_.end(), timeline_.numFrames(), timeline_.numGaps());
if (media_.hasaudio)
Log::Info("MediaPlayer %s Audio track %s", std::to_string(id_).c_str(), audio_enabled_ ? "enabled" : "disabled");
opened_ = true;
// register media player
@@ -1660,6 +1675,34 @@ void MediaPlayer::TimeCounter::tic ()
}
void MediaPlayer::setAudioEnabled(bool on)
{
// in case of change
if (audio_enabled_ != on) {
// toggle
audio_enabled_ = on;
// if openned
if (media_.hasaudio ) {
// apply
reopen();
// reset volume
setAudioVolume(audio_volume_);
}
}
}
void MediaPlayer::setAudioVolume(int vol)
{
// set value
audio_volume_ = CLAMP(vol, 0, 100);
// apply value
if (pipeline_ && media_.hasaudio)
gst_stream_volume_set_volume (GST_STREAM_VOLUME (pipeline_), GST_STREAM_VOLUME_FORMAT_LINEAR, gdouble(audio_volume_) * 0.01);
}
//static void audio_changed_callback (GstElement *pipeline, MediaPlayer *mp)
//{
// gint n_audio;

View File

@@ -37,6 +37,7 @@ struct MediaInfo {
GstClockTime dt;
GstClockTime end;
std::string log;
bool hasaudio;
MediaInfo() {
width = par_width = 1;
@@ -49,6 +50,7 @@ struct MediaInfo {
interlaced = false;
seekable = false;
valid = false;
hasaudio = false;
dt = GST_CLOCK_TIME_NONE;
end = GST_CLOCK_TIME_NONE;
log = "";
@@ -264,6 +266,15 @@ public:
void setVideoEffect(const std::string &pipeline_element);
inline std::string videoEffect() { return video_filter_; }
inline bool videoEffectAvailable() { return video_filter_available_; }
/**
* Enables or disables audio
* NB: setAudioEnabled reopens the video
* */
void setAudioEnabled(bool on);
void setAudioVolume(int vol);
inline bool audioEnabled() const { return audio_enabled_; }
inline int audioVolume() const { return audio_volume_; }
inline bool audioAvailable() const { return media_.hasaudio; }
/**
* Accept visitors
* */
@@ -309,6 +320,8 @@ private:
bool enabled_;
bool rewind_on_disable_;
bool force_software_decoding_;
bool audio_enabled_;
int audio_volume_;
std::string decoder_name_;
bool video_filter_available_;
std::string video_filter_;

View File

@@ -894,6 +894,14 @@ void SessionLoader::visit(MediaPlayer &n)
n.setTimeline(tl);
}
// audio
int audiovolume = 100;
mediaplayerNode->QueryIntAttribute("audio_volume", &audiovolume);
n.setAudioVolume(audiovolume);
bool audioenabled = false;
mediaplayerNode->QueryBoolAttribute("audio", &audioenabled);
n.setAudioEnabled(audioenabled);
// change play rate: will be activated in SessionLoader::visit (MediaSource& s)
double speed = 1.0;
mediaplayerNode->QueryDoubleAttribute("speed", &speed);

View File

@@ -423,6 +423,11 @@ void SessionVisitor::visit(MediaPlayer &n)
XMLElement *newelement = xmlDoc_->NewElement("MediaPlayer");
newelement->SetAttribute("id", n.id());
if (n.audioAvailable()) {
newelement->SetAttribute("audio", n.audioEnabled());
newelement->SetAttribute("audio_volume", n.audioVolume());
}
if (!n.singleFrame()) {
newelement->SetAttribute("loop", (int) n.loop());
newelement->SetAttribute("speed", n.playSpeed());

View File

@@ -144,6 +144,7 @@ void Settings::Save(uint64_t runtime)
applicationNode->SetAttribute("broadcast_port", application.broadcast_port);
applicationNode->SetAttribute("loopback_camera", application.loopback_camera);
applicationNode->SetAttribute("shm_socket_path", application.shm_socket_path.c_str());
applicationNode->SetAttribute("accept_audio", application.accept_audio);
pRoot->InsertEndChild(applicationNode);
// Widgets
@@ -437,6 +438,7 @@ void Settings::Load()
applicationNode->QueryIntAttribute("stream_protocol", &application.stream_protocol);
applicationNode->QueryIntAttribute("broadcast_port", &application.broadcast_port);
applicationNode->QueryIntAttribute("loopback_camera", &application.loopback_camera);
applicationNode->QueryBoolAttribute("accept_audio", &application.accept_audio);
// text attributes
const char *tmpstr = applicationNode->Attribute("shm_socket_path");

View File

@@ -295,6 +295,9 @@ struct Application
int shm_method;
std::string shm_socket_path;
// audio
bool accept_audio;
// Settings of widgets
WidgetsConfig widget;
@@ -369,6 +372,7 @@ struct Application
windows = std::vector<WindowConfig>(1+MAX_OUTPUT_WINDOW);
windows[0].w = 1600;
windows[0].h = 900;
accept_audio = true;
}
};

View File

@@ -1511,6 +1511,10 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
ImGui::PopStyleColor(1);
ImGui::SetCursorScreenPos(imgarea.GetTL() + ImVec2(h_space_, v_space_));
if ( mediaplayer_active_->audioEnabled())
// Icon to inform audio decoding
ImGui::Text("%s " ICON_FA_VOLUME_UP, ms->initials());
else
ImGui::Text("%s", ms->initials());
ImGui::PopFont();
}
@@ -1532,6 +1536,12 @@ void SourceControlWindow::RenderMediaPlayer(MediaSource *ms)
ImGui::SetCursorScreenPos(imgarea.GetTL() + ImVec2(h_space_, v_space_));
ImGui::Text("%s", info_.str().c_str());
// Icon to inform audio decoding
if ( mediaplayer_active_->audioEnabled()) {
ImGui::SetCursorScreenPos(imgarea.GetTL() + ImVec2( imgarea.GetWidth() - 2.f * ImGui::GetTextLineHeightWithSpacing(), 0.35f * tooltip_height));
ImGui::Text(ICON_FA_VOLUME_UP);
}
// Icon to inform hardware decoding
if ( mediaplayer_active_->decoderName().compare("software") != 0) {
ImGui::SetCursorScreenPos(imgarea.GetTL() + ImVec2( imgarea.GetWidth() - ImGui::GetTextLineHeightWithSpacing(), 0.35f * tooltip_height));

View File

@@ -5330,15 +5330,13 @@ void Navigator::RenderMainPannelSettings()
// System preferences
//
ImGuiToolkit::Spacing();
// ImGuiToolkit::HelpMarker("If you encounter some rendering issues on your machine, "
// "you can try to disable some of the OpenGL optimizations below.");
// ImGui::SameLine();
ImGui::TextDisabled("System");
static bool need_restart = false;
static bool vsync = (Settings::application.render.vsync > 0);
static bool multi = (Settings::application.render.multisampling > 0);
static bool gpu = Settings::application.render.gpu_decoding;
static bool audio = Settings::application.accept_audio;
bool change = false;
// hardware support deserves more explanation
ImGuiToolkit::Indication("If enabled, tries to find a platform adapted hardware-accelerated "
@@ -5349,6 +5347,12 @@ void Navigator::RenderMainPannelSettings()
else
ImGui::TextDisabled("Hardware en/decoding unavailable");
// audio support deserves more explanation
ImGuiToolkit::Indication("If enabled, tries to find audio in openned videos "
"and allows enabling audio for each source.", ICON_FA_VOLUME_OFF);
ImGui::SameLine(0);
change |= ImGuiToolkit::ButtonSwitch( "Audio support", &audio);
#ifndef NDEBUG
change |= ImGuiToolkit::ButtonSwitch( "Vertical synchronization", &vsync);
change |= ImGuiToolkit::ButtonSwitch( "Multisample antialiasing", &multi);
@@ -5356,7 +5360,8 @@ void Navigator::RenderMainPannelSettings()
if (change) {
need_restart = ( vsync != (Settings::application.render.vsync > 0) ||
multi != (Settings::application.render.multisampling > 0) ||
gpu != Settings::application.render.gpu_decoding );
gpu != Settings::application.render.gpu_decoding ||
audio != Settings::application.accept_audio );
}
if (need_restart) {
ImGuiToolkit::Spacing();
@@ -5364,6 +5369,7 @@ void Navigator::RenderMainPannelSettings()
Settings::application.render.vsync = vsync ? 1 : 0;
Settings::application.render.multisampling = multi ? 3 : 0;
Settings::application.render.gpu_decoding = gpu;
Settings::application.accept_audio = audio;
if (UserInterface::manager().TryClose())
Rendering::manager().close();
}