Closed courteous closed 3 years ago
I really don't know. Perhaps you've found some problem with LibVLC's media players when using multiple souts.
Maybe trying changing the order of your dst= so that the "display" dst is first.
Hello Mark just tried changing the dst i.e.
":sout=#transcode{vcodec=h264,fps=24,vb=750,scale=Auto,width=640,height=360,acodec=mp4a,ab=128,channels=2,samplerate=44100,threads=8,scodec=none}"
+ ":duplicate{"
+ "dst=display"
+ ","
+ "dst=standard{access=udp,mux=ts,dst=172.26.15.107:5555}"
+ "}"
still the same result.
Do you think that this is something that is on the vlcj side or LibVLC. The way i see it this NativeEventManager callback is the reason but this one can come either from LibVLC or vlcj . Any ideas how to debug something like this?
This issue can be demonstrated by simply just using the #transcode string or not, the duplicate part is not relevant to the issue.
And indeed there are no audio events when using #transcode.
My LibVLC discord contacts have no answer for this.
But it seems enabling transcoding prevents, on the native side, audio controls and audio events from working correctly.
Debugging it has to happen IMO on the native VLC side. Since I am not so familiar with gdb etc, I'd be editing VLC sources to add some console log output to work out what was going on. Unfortunately, I suspect this is something deep within VLC.
The VLC devs would say that none of these sout options are supported for use with LibVLC.
Hello Mark, thank you for the feedback and for your support. It is kind of strange that "VLC devs would say that none of these sout options are supported" since they are the once that put those options there. I am not sure about that. Even the VLC software itself provides those options to you in a textual form once you want to do a streaming. I belive that those options are supported since they are mentioned in the official wiki of the vlc i.e. vlc wiki
Anyway, I would like to test something this Friday i.e. i want to see if i have two separate embedded VLC players i.e. one with transcode and another without it, if i can control the second one and if the second is able to receive the events. Those should be on separate threads. I would test that this Friday and report back.
I do agree that this is most likely something on the LibVLC side. I think what we can try next is to see which part of LibVLC is responsible for that NativeEventManager callback. If we can find that, then we know what is "expected" behavior, and then we set some breakpoints in LibVLC and dump the callback stack. From there on, we should be able to find the place where that stack is different. Just my 2 cents.
The sout options are not supported via LibVLC. If there is no API for the sout options then if it works it's a bonus, but it comes with no guarantees.
They are of course supported by VLC itself.
VLC is not responsible for the NativeEventManager callback at all - there is not necessarily a direct analog between vlcj code and VLC code.
I suppose you are right that those options are not supported. I was hoping for the best :) . About the callback: What i meant is the part of the code that is responsible for calling the NativeEventManager callback. My understanding so far is that this is somewhere in LibVLC, but i am not sure about that, maybe you can elaborate on it.
There are event managers in LibVLC. But I think the problem will go much deeper than that. It might be possible to track it down but it will take some work I reckon.
Well this is a real bump, i was thinking that i can use Java Native Sound System and mute the application using the getSourceDataLine directly however it turns out that this is not possible because all all lines on my Laptop are missing i.e. the BooleanControl.Type.MUTE is not supported. Then i printed all of the Mixers and all SourceDataLines, and it turns out that my laptop has 13 mixers and non of them support the BooleanControl.Type.MUTE type. In fact my all mixers that have SourceDataLines the array "Control [] controls = lineSpeaker.getControls();" is empty I really did not expected this unfortunate event. This seems to be dependent of Java and hardware. Here is the code if anyone one to try this. Mark do you have any other idea how to mute that sound while transcoding?
@FXML
private void muteButtonAction(ActionEvent event) {
// this is the laptop default speaker.
int reporterMixerNumber = 7;
Mixer.Info[] mixInfors = AudioSystem.getMixerInfo();
final Mixer.Info mxInfo = mixInfors[reporterMixerNumber];
String mixerName = mxInfo.getName();
String mixerDescription = mxInfo.getDescription();
System.out.println("MIXER name : " + mixerName);
System.out.println("\t-----Mixer Description :" + mixerDescription);
System.out.println("\t-----Mixer Vendor :" + mxInfo.getVendor());
System.out.println("\t-----Mixer version :" + mxInfo.getVersion());
Mixer speakerMixer = AudioSystem.getMixer(mxInfo);
Line.Info[] sourceLineInfos = speakerMixer.getSourceLineInfo();
Line.Info lineInfoLineZero = sourceLineInfos[0];
SourceDataLine speakers = null;
AudioFormat format = new AudioFormat(8000.0f, 16, 1, true, true);
try {
//
speakers = AudioSystem.getSourceDataLine(format, mxInfo);
} catch (LineUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("\t\t-----Line Info [] : " + lineInfoLineZero );
Line lineSpeaker = null;
try {
lineSpeaker = speakerMixer.getLine(lineInfoLineZero);
Boolean IsMuteSupported = lineSpeaker.isControlSupported(BooleanControl.Type.MUTE);
Control [] controls = lineSpeaker.getControls();
if(IsMuteSupported) {
Control control = lineSpeaker.getControl(BooleanControl.Type.MUTE);
BooleanControl bc = (BooleanControl) control;
if (bc != null) {
bc.setValue(true);
}
}
} catch (LineUnavailableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
The interesting thing is that the VLC 3.0.16 itself can do transcoding, streaming and mute control simultaneously. I just tested this from the VLC directlly, and i can mute and unmute white transcoding.
I'm not so familiar with JavaSound, but if there isn't a boolean mute control can't you just use a volume control and set that to 0.
But then I see you say they have no controls at all, which can't be right. So something else must be wrong there.
To mute while transcoding, well, do you really need to duplicate the sout to "display"?
Hello Mark,
And about the missing controls the Java doc mentions explicitly that that the controls might be missing. And i am afraid this is the case with my particular laptop. About the duplicate "display", why do you ask? Is there a constellation where the events will work without the duplicate display? What would be if i do not need the duplicate display.
I was even thinking about creating an instance of the embedded player that will do only transcoding, and another instance that will subscribe to the stream and play it locally (trough local multicast), however unfortunately i can not use multicast, hence the unicast address in the example.
The question is why are you transcoding and playing it on the local display? Do you really need to do that?
I can't answer your other questions, try it and see...
Maybe you will need to resort to making native calls to whatever OS audio mixer you're using (Alsa, Windows etc).
The bottom line here I think is that there is probably nothing you can do from the vlcj perspective.
I don't think there's anything more can be added to this. The issue can be reopened if something new turns up.
Hello Mark,
I realized that #1082 is closed and decided to describe the problem in more details.
The problem i am describing can be reproduced using the same simple project that has basically 2 main files i.e. vlcjTestMute
notice that i am starting the player with the "-vvv" option i.e.
"new MediaPlayerFactory("-vvv");"
this is the most important part i.e. :
After the player is started i am able to see in the logs that the player is working i.e. transcoding is working as well and i see the UDP packets in wireshark. The sout string is also correctly processed i.e. here is the output of the "-vvv" option debugging
basically all options are processed correctly by the libvlc . However the only difference here is that when executing an mute event trough vlcj for some reason there is no calback which is comming from the NativeEventManager that i described in issue #1082 i.e. when the muting fiction is working correctly that callback is being seen. That callback is responsible to call the overwritten methods from the MediaPlayerFactory class. In this case that is not happening.
Below is the normal process
a) we execute
"audioApi.setMute(true);"
b) then we see the call to"libvlc_audio_set_mute(mediaPlayerInstance, mute ? 1 : 0);"
d) then we get a callback from the libvlc i.e. see the screenshot below e) then the overwritten method muted in the MediaPlayerEventAdapter is being executed.in this case that callback from NativeEventManager is missing. Do you have any idea why or how to troubleshoot that further?