I am not an expert on c# but just trying to churn out a quick solution.
Gist of the solution:
I have a sensor that sends a signal via serial port, and based on the signal the video played must be changed. It switches between two videos
It works as it stands now using axWindowsMediaPlayer. But unfortunately the app crashes after, lets say, 2 hours or so.
Here is the code that i use to change the video url when signal arrives
if (axWindowsMediaPlayer1.playState == WMPPlayState.wmppsPlaying) axWindowsMediaPlayer1.Ctlcontrols.stop();
axWindowsMediaPlayer1.uiMode = "none";
axWindowsMediaPlayer1.URL = mainFile;
axWindowsMediaPlayer1.Ctlcontrols.play();
Initializing the player with this
axWindowsMediaPlayer1.uiMode = "none";
axWindowsMediaPlayer1.Dock = System.Windows.Forms.DockStyle.Fill;
axWindowsMediaPlayer1.settings.setMode("loop", true);
axWindowsMediaPlayer1.settings.volume = 0;
I assume this his some adverse effect on the memory or something; just not expert enough to figure it out. ANy suggestions, is this the right way to change video url?
Thanks
Related
I have a dynamic pipeline that switches between sources (File/HTTP/RMTP/SRT) on set intervals, and outputs to an RTMP sink. This is working fine, until I attempt to perform a seek.
The seek itself works, but the next time I try to switch sources, the pipeline hangs.
I've been able to stop it from hanging by recreating the muxer after performing a seek, but I still end up with audio/video synchronization issues - the audio plays, but the video falls behind.
For what it's worth, I'm testing the outgoing RTMP stream in VLC, and if I stop/play the stream is back in sync and continues to play without issue.
Here is my pipeline graph:
The application is written in C#.
I'm performing the seek like this:
var bus = pipeline.Bus;
do
{
var msg = bus.TimedPopFiltered(Constants.SECOND, MessageType.Error | MessageType.Eos | MessageType.StateChanged);
// Parse message
if (msg != null)
{
...
}
else
{
if (pipeline.CurrentState == State.Playing && !seekDone)
{
seekDone = true;
pipeline.SetState(State.Paused);
var seekTo = 50 * Gst.Constant.SECOND;
var seeked = mux.SeekSimple(Format.Time, SeekFlags.Flush | SeekFlags.KeyUnit, seekTo);
if (!seeked)
{
Console.WriteLine("Seek failed");
}
else
{
Console.WriteLine("Performing seek");
}
pipeline.SetState(State.Playing);
}
}
}
while(!terminate)
The source switching is handled by a Timer on a separate thread while the pipeline is in the Paused state.
Any help would be greatly appreciated.
EDIT: I placed pad probes on the video and audio queues and can see that the video timestamps are falling behind the audio by a few seconds.
Considering that this only happens after a seek, I am wondering if there is something in the video processing that is taking too long and for the player to handle.
The VLC logs show that the player is dropping a lot of late video frames.
I´m doing this small RPG game in the C# console app, and I wanted to add some background music and effects when choosing menu options.
What I noticed was that I wasn´t able to do anything when the background music started to play. I thought of threading, but this is completly new to me (started to learn C# 6 weeks ago).
What I managed to do was starting a new thread and play the sounds
static Thread backgroundMusic = new Thread(() =>
{
using (var audioFile = new AudioFileReader(AppDomain.CurrentDomain.BaseDirectory + "\\menu.mp3"))
using (var outputDevice = new WaveOutEvent())
{
backgroundMusic.IsBackground = true;
outputDevice.Init(audioFile);
outputDevice.Play();
while (true)
{
Thread.Sleep(1);
}
}
});
And then for the sound effect I do...
static Thread click = new Thread(() =>
{
using (var audioFile = new AudioFileReader(AppDomain.CurrentDomain.BaseDirectory + "\\click.mp3"))
using (var outputDevice = new WaveOutEvent())
{
click.IsBackground = true;
outputDevice.Init(audioFile);
outputDevice.Play();
while (true)
{
Thread.Sleep(1);
}
}
});
I start these with
click.Start();
backgroundMusic.Start();
Ok so far so good. It plays the background music and it plays the sound effect, but only one time. Can I reuse the thread in some way to play the click sound again when another option is chosen?
And can I abort sound in some way? I might want different music when you play the game and in the menus.
tried backgroundMusic.Abort(); but then I got this:
System.PlatformNotSupportedException: 'Thread abort is not supported on this platform.'
And i can not restart a thread once I´ve started it one time. I tried with
backgroundMusic.Start();
I´ve been checking out forums but all seems to cover windows forms, and not be working with console app.
https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread?view=net-5.0
I´ve also checked out the documentation... but honestly I think the documentation at microsoft is NOT for beginners. I find it very hard to understand.
I´ve might have been doing it all wrong, so don´t be hard on me, but please come with suggestions how I can improve.
So I want:
Background music playing and looping
Click sound every time you choose a menu option
I have:
Background music playing once (til the end of the file)
Click sound on the first menu option, there after it throws an exception (see above)
You should never, ever use Thread.Abort(). It just stops the thread in an "evil" way - by throwing an exception, and you never know what side effects that will have.
You need CancellationToken. Check out this article: https://learn.microsoft.com/en-us/dotnet/standard/threading/cancellation-in-managed-threads
I've tried setting background audio through both a mediaElement in XAML
<MediaElement x:Name="MyAudio" Source="Assets/Sound.mp3" AudioCategory="BackgroundCapableMedia" AutoPlay="False" />
And programmatically
async void setUpAudio()
{
var package = Windows.ApplicationModel.Package.Current;
var installedLocation = package.InstalledLocation;
var storageFile = await installedLocation.GetFileAsync("Assets\\Sound.mp3");
if (storageFile != null)
{
var stream = await storageFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
_soundEffect = new MediaElement();
_soundEffect.AudioCategory = AudioCategory.BackgroundCapableMedia;
_soundEffect.AutoPlay = false;
_soundEffect.SetSource(stream, storageFile.ContentType);
}
}
// and later...
_soundEffect.Play();
But neither works for me. As soon as I minimise the app the music fades out
akton replied to a similar question with this excellent answer
It wasn't easy to find initially as it doesn't use 'audio' in the title and I wasn't playing music. It's an excellent, comprehensive answer, the likes of which I love to see on StackExchange. It also mentions a few things other answers to similar questions had failed to point out. In brief
You need to handle the MediaControl events PlayPressed, PausePressed, PlayPausedTogglePressed and StopPressed, even if you have no buttons. EDIT: these events are required by Windows 8 app certification, make sure they actually work.
Add audio to the list of support background tasks in the applications manifest [see aktons answer for more detail]
However, in implementing this solution I did come across what I can only assume is a bug. I've built a kitchen timer within a UserControl. It plays an optional ticking sound as it counts down and then buzzes when elapsed. However, if the ticking sound is turned off before the timer is set, the buzz sound will not play. It seems that a Windows 8 app needs to play a sound before being minimised in order for background audio to work. To fix this, I created a silent audio file which is 1 second in duration. This file plays whether the ticking is on or off. It's a weird hack, and I hope I can figure out a better solution, but for now its all I can think of.
I'am building a game in C#/XNA, it is an top-view racing game and I want to play a sound effect, when my car bumps into a wall.
The problem is that my sound keeps looping so, when I hit a wall, the song will instantly start playing, but I want it to play, and when it is finished playing, then it can be played again.
Here is the code that takes care of the collision:
if (map[x][y] == 0)
{
car.speed = 0;
crash.Play(); }
Please ask me if I'am not clear about something.
Thanks in advance!
Here is the complete answer to your questions: http://msdn.microsoft.com/en-us/library/dd940203.aspx
SoundEffectInstance instance = soundEffect.CreateInstance();
instance.IsLooped = true;
However, by default, SoundEffect should not be looped...
Call SoundEffect.CreateInstance() to get a SoundEffectInstance. Then set the IsLooped property to false before you call Play:
crashSoundEffectInstance.IsLooped = false;
You may want to look into the SoundEffectInstance class. Here's an example on how to use it properly.
You can check if the sound effect state to see if it's currently playing
Edit: I've added a more complete code, as I felt it was needed. It's roughly the same example as in the link I've provided. (Note: This code is untested)
//In your content load
SoundEffect crash;
crash = Content.Load<SoundEffect>("PathToYourSoundEffect");
SoundEffectInstance sei = crash.CreateInstance();
//In your update code
if(sei.State == SoundState.Stopped || sei.State == SoundState.Paused)
{
sei.Play();
}
I have a windows media player COM in my Windows Form project that plays and opens videos admirably. However, I would like to be able to grab the first frame of the loaded video so my program users can preview the video (and, ideally, recognize one video from another).
How can I update the frame displayed by the windows media player object?
I have tried using the following code at the end of my openFileDialog event response:
private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
{
Text = openFileDialog1.SafeFileName + " - MPlayer 2.0";
//mediaPlayer1.openPlayer(openFileDialog1.FileName);
mediaPlayer1.URL = openFileDialog1.FileName;
//hopefully, this will load the first frame.
mediaPlayer1.Ctlcontrols.play();
mediaPlayer1.Ctlcontrols.pause();
}
However, when I run this, the pause command gets ignored (Auto-play for video loading is turned off, so the video won't start playing without calling .play(), above). If I had to guess, I'd say that this is because of some threading operation that calls play, moves on to call pause, calls pause, and then, finally, the play resolves, and the video starts - but because the .pause resolved before the .play, the net effect is the .pause is ultimately unheeded.
Firstly, is there a way other than .play(); .pause(); to snag a preview image of the video for the AxWindowsMediaPlayer object? If not, how can I make sure that my .pause() doesn't get ignored?
(I know that .play(); .pause(); works in the general case, because I tested with a separate button that invoked those two methods after the video finished loading, and it worked as expected)
You can't do a lot of things with this COM. However Follow this link and you will find a Class that will help you extract an image from a Video file. You could simply get extract the image and just put it in top of the video, or next to it. This is a simple workaround for your requirement. If not happy with it, I would strongly recommend not using this COM at all and use some other open source video player/plugins. There a lot of real good ones, but I could recommend the VLC Plugin, or try finding another.
Good luck in your quest.
Hanlet
While the Windows Media Player Com might not officially support a feature like this, its quite easy to 'fake' this. If you use a CtlControls2, you have access to the built-in "step(1)" function, which proceeds exactly one frame.
I've discovered that if you call step(1) after calling pause(), searching on the trackbar will also update the video.
It's not pretty, but it works!
This is a little trick to solve the common step(-1) not working issue.
IWMPControls2 Ctlcontrols2 = (IWMPControls2)WindowsMediaPlayer.Ctlcontrols;
double frameRate = WindowsMediaPlayer.network.encodedFrameRate;
Console.WriteLine("FRAMERATE: " + frameRate); //Debug
double step = 1.0 / frameRate;
Console.WriteLine("STEP: " + step); //Debug
WindowsMediaPlayer.Ctlcontrols.currentPosition -= step; //Go backwards
WindowsMediaPlayer.Ctlcontrols.pause();
Ctlcontrols2.step(1);