I have a UWP Desktop application in which I use a MediaComposition with multiple images. The problem is that all images have a specific time to appear and a duration. How do I set the start time for each MediaClip?
MediaComposition mediaComposition = new MediaComposition();
var clipCover = await MediaClip.CreateFromImageFileAsync(stgCover, tmsCompositionDuration);
mediaComposition.Clips.Add(clip);
How to set the start time of MediaClips in c# MediaComposition?
Currently, there is not such api to set start time for the MediaClip, you just make image clip with specific duration and insert it into mediaComposition list. for the start time, you need calculate it manually (previous clips duration summation).
For your scenario, you could use MediaClip.CreateFromColor to make empty color frame and insert it into specific index to update the clip's start time.
for more detail, please refer to this Media compositions and editing tutorial.
You can use Overlays:
Because overlays are stacked on top of each other instead of being played sequentially, all overlays start playback at the beginning of the composition by default. To cause an overlay to be begin playback at another time, set the Delay property to the desired time offset (source)
Related
I'm using GPUImageVideoCamera and GPUImageMovieWriter to record a video. Everything is working good except I want to show the user a progress bar with the duration as the movie is being recorded. The GPUImageMovieWriter has a property called Duration, but I'm not sure how to make it update the UI in real time (as the video is being recorded).
I just need someone to point me in the right direction on how I can achieve this, I've been trying to figure this out for a few days now.
Set up a NSTimer to fire once every second or two and update the progress bar.
I am using D3DImage to display a sequence of frames that are rendered unto the same Direct3D Surface one after the other. My current logic is thus:
Display last rendered frame (i.e.D3DImage.Lock()/AddDirtyRect()/Unlock())
Start rendering next frame
Wait for next frame to be ready and that it's time to display it
Display last rendered frame
...
The problem with this approach is that when we are done calling Unlock() on D3DImage, the image isn't actually copied, it's only scheduled to be copied on the next WPF render. It's therefore possible that we render a new frame on the Direct3D surface before WPF has had the chance to display it. The net result is that we see missed frames on the display.
Right now I'm experimenting with using a separate Direct3D texture for rendering and performing a copy to a "display texture" just before display, which is giving better results but incurs substantial overhead. It would be preferrable to just be able to know when D3DImage is done refreshing and start rendering the next frame immediately after. Is this possible, if so how? Or do you have a better idea altogether?
Thanks.
The CompositionTarget.Rendering event is called when WPF is going to render, so that's when you should do your Lock() and Unlock(). After the Unlock(), you can kick off the next render.
You should also check the RenderingTime because the event may fire multiple times per frame. Try something like this:
private void HandleWpfCompositionTargetRendering(object sender, EventArgs e)
{
RenderingEventArgs rea = e as RenderingEventArgs;
// It's possible for Rendering to call back twice in the same frame
// so only render when we haven't already rendered in this frame.
if (this.lastRenderTime == rea.RenderingTime)
return;
if (this.renderIsFinished)
{
// Lock();
// SetBackBuffer(...);
// AddDirtyRect(...);
// Unlock();
this.renderIsFinished = false;
// Fire event to start new render
// the event needs to set this.renderIsFinished = true when the render is done
// Remember last render time
this.lastRenderTime = rea.RenderingTime;
}
}
Update to address comments
Are you sure that there's a race condition? This page says that the back buffer gets copied when you call Unlock().
And if there really is a race condition, how about putting Lock/Unlock around the render code? This page says that Lock() will block until the copy is finished.
It looks like the clean way of doing this, in order to render in parallel with the UI, is to render into a separate D3D surface, and copy it to the display surface (i.e. the one passed to SetBackBuffer) between the calls to Lock() and Unlock(). So the algorithm becomes:
Copy and display the last rendered frame, i.e.
Lock()
Copy from render to display surface
SetBackBuffer(displaySurface)
AddDirtyRect()
Unlock()
Schedule a new render to the render surface
Wait for it to complete and that the timing is ok to display it
Goto 1
The documentation for D3DImage explicitely states:
Do not update the Direct3D surface while the D3DImage is unlocked.
The sore point here is the copy, which is potentially costly (i.e. >2ms if the hardware is busy). In order to use the display surface while the D3DImage is unlocked (avoiding a potentially costly operation at render time), one would have to resort to disassembly and reflection to hook into D3DImage's own rendering...
How can I use trackview or timeline in Naudio in C#?
Here is my code and it's not working.
I want to see my line going as track is playing.
NAudio.Wave.WaveStream pcm = NAudio.Wave.WaveFormatConversionStream.CreatePcmStream(new NAudio.Wave.Mp3FileReader(open.FileName));
customWaveViewer2.WaveStream = pcm;
stream = new NAudio.Wave.BlockAlignReductionStream(pcm);
trackView1.NowTime = stream.CurrentTime;
Unfortunately, TrackView and TimeLine are not completed controls, and you would be better off writing your own custom control to place a vertical line at a position that represents the now playing time.
You would probably be best using a timer to invalidate your custom wave viewer, and in the Paint method, drawing a vertical line that represents the current play time.
I need to load 101 bitmaps from the filesystem (they can't be built into the app as a resource as they will be changed for each run of the program) into a windows form application picturebox sequentially based on short duration timer events (500ms give or take) .
Essentially it should work like a slow animation but it is critical that every image be shown.
I've roughed out a simple application in C# to do this however it seems that the image loading and displaying is taking longer than the 500ms so some images are never displayed.
Is there some way I can avoid this? Preloading or creating 101 pictureboxes and showing and hiding?
Anybody have any suggestions?
What's taking the longest? Image loading or displaying? Are you loading each image when it needs displaying? A look at your code would be really valuable.
If you are certain that it will always be exactly 101 images, load them all into an array of System.Drawing.Bitmap first then have an iterator variable that gets incremented on each call of the Tick event of a Timer. Have this Tick event load the image from the array into the PictureBox using PictureBox.Image = myBitmapArray[iterator] If you increment the iterator using ++i%=101; you won't get an OutOfBounds error and the animation will loop.
Populate an array of Bitmap objects before starting the animation.
A couple of options... pick one or combine them:
(1) Use a lock and a counter to guarantee that when the event fires it's loading the next image in line.
(2) Disable the timer in the Tick event, then re-enable it after you've loaded the image. The result is that the images arrive 500ms after the last one is drawn, so if a picture takes one second to load, the images are drawn at t=1000ms, t=1500ms, t=3000ms, etc. All the images are drawn, and 500ms is guaranteed to pass between pictures, but the animation might appear slow.
(3) Do the above, but track the time the event starts, and after the image is drawn, set the next timer tick to be 500 - (Now - eventStart)... so that if the image takes 250ms to draw, the next timer tick will fire in 250ms. If Now - eventStart < 0, the next timer tick should fire immediately. The animation will take the minimum amount of time possible, but images could potentially flash by, appearing only for a few milliseconds.
(4) Use PictureBox.LoadAsync() to give you some multi-threading... the next event can be loading the image while the previous event is drawing. But you'll need a Mutex that you release in the LoadCompleted event that you wait on before calling LoadAsync(), if you need to guarantee the images are all drawn.
(5) I'm not sure if the drawing of the picture falls under the Layout category, but you can try calling SuspendLayout() and ResumeLayout() before/after loading the image
(6) Use an array of images, lock a counter, and use the .Image property of the PictureBox to let you pre-load the images. I believe this was suggested in another answer, also
HTH,
James
I don't have a concrete answer for you, but I would approach this by first determining if it's image loading, image display, or both actions that are taking too much time.
I would imagine that image loading is going to be relatively quick, even with pretty large image sizes, provided that the images are local and you have relatively decent hardware. My first attempt would involve loading all images from a thread sequentially so that you application doesn't have to wait for image display to complete before the next image loads.
If image display is taking a long time (and even on my really powerful workstation it's not all that fast for large images), then is it possible for you to scale the images before the application displays everything? Does your application need to deal with full resolution images? With the megapixel cameras these days, I can't image that you'd want to have all of the data present in the image files anyway, since the sizes can easily exceed monitor resolutions by a factor of 6.
Another thing that may be a concern is the size of the images. If the are all 18 Megapixel Images, I can see it taking either a lot of time or a lot of room.
You may want to resize them to the size of your display area when you initially load them up so that you aren't using 2 gigs of ram or waiting to read off the disk depending on how you implement it.
I'm currently working on an app that allows the user to play (automatically scroll) through a series of local images. Usually there will be five or six on screen at once.
The major bottleneck at the moment seems to be the actual loading of the image data from disk. A timer thread calls for the images to be updated every 1/6 of a second and the app is struggling to keep up with that speed. Each image is around 25Kb.
I tried creating a rolling cache to try and preload images but this was also getting caught up with itself so ended up slowing down just as much.
Every beat of the timer, I'm looping through the six image placeholders loading the next image using the standard
Image img = Image.FromFile("filename");
method but thought someone might know of a faster way to get the images off disk.
There are between 500 and 20,000 images in each of the six sets so it's too large to load the whole thing into memory at the start.
If anyone has suggestions for a faster way to pull these images through, it would be greatly appreciated.
Edit to add some more detail of application flow.
Okay, this is what's happening:
User hits 'play' button. Timer thread starts with 1/6 second timeout.
Timer callback:
Update image index (_index++)
for each viewer in list of visible viewers (the forms to display images)
{
get the filename from the id stored in the viewer
check to see if the file exists
if it does exist,
create new bitmap from image
and return that image
otherwise return null
if returned image isn't null, display it on screen
}
That's obviously going across a few layers - the image loading goes on in the services layer and then passes this through to presentation and then to the UI but that's the gist of what's happening.
I came across this page which describes how to use the GDI+ API directly to load images. Very simple to use:
ImageFast.FromFile(#"C:\MyPhoto.JPG");
Added to show speed of ImageFast over Image From File method
This uses the source code found here. The code was copied and pasted and required no changes.
Stopwatch watch = Stopwatch.StartNew();
string filePath = #"C:\TestImage25k.png";
Image fromFile = Image.FromFile(filePath);
watch.Stop();
Console.WriteLine("Image.FromFile Ticks = {0:n}", watch.ElapsedTicks);
long fromFileTicks = watch.ElapsedTicks;
watch.Reset();
watch.Start();
Image fastImage = ImageFast.FromFile(filePath);
watch.Stop();
long fastFileTicks = watch.ElapsedTicks;
Console.WriteLine("ImageFast.FromFile Ticks = {0:n}", watch.ElapsedTicks);
Console.WriteLine("fromFileTicks - fastFileTicks = {0:n}", fromFileTicks - fastFileTicks);
The console output was
Image.FromFile Ticks = 19,281,605.00
ImageFast.FromFile Ticks = 7,557,403.00
fromFileTicks - fastFileTicks = 11,724,202.00
You can see the impact of the ImageFast. Over time those 11 million saved ticks will add up.
Easiest might be to put a 'next' and 'previous' button to limit the number of images and preload.
Check out the concept of double buffering. What you want to be doing is have a second thread that can be loading the next set of images while you are displaying the first set. Once the 1/6 time gate hits, you switch the one set of images out and start loading the next set.
I think concept of double buffering will be useful. Set "Double Buffer" property of the form to True. This will help you little bit. Following links may be useful to you
http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/f15ae586-b63f-4afb-90a7-d9067ccc19d5
How to speed up .NET winforms rendering
If you have 6 images displayed at once, and you change them all every 1/6 of a second, you should be running into performance issues. Loading 150 kb from disk should be a trivial activity even without caching. It sounds like you may be overdoing the file loads. Are you sure you are only loading 6 images at a time? Are you reading images from disk that are not displayed?
If you can you provide a little more detail of the application flow, I may be able to be a little more helpful.
i would probably create a background thread to continously fetch all the images from disk (keeps the ui responsive) and then publish each newly loaded image via an event