I'm developing an app which requires me to record a lot of video data but I don't need to store them all.
What I need to do is to keep just the last X minutes of the recorded stream.
This means that I need a way to remove the oldest sample everytime that I need to store a new one.
So I started working with this article: http://msdn.microsoft.com/library/windowsphone/develop/hh394041%28v=vs.105%29.aspx
The first idea that I had was to just call the StopVideoRecording() and then the StartVideoRecording() using a timer each X minutes.
Now, at first this made sense but it won't work.
The problem is that doing this way will delete the previous data each X minutes.
This means that, if we record 12 minutes and we need to keep the last 5, following this idea we'll delete the first 5 and then the second five, leaving just the last 2 minutes and this is not what I was looking for.
I moved then my attention to the VideoSink class because of the OnSample method.
This seems pretty simple, we intercept every sample and we store it in a fixed size byte array (the size depends on the needed length and the sample's size).
When the buffer is full we just shift everything on the left before adding the new sample.
The problem is that a test video of just 1 minute generated something like 2GB of samples and this makes this way really hard to manage.
I know that those samples are uncompressed, but wouldn't be hard, for a smartphone, to get a sample, compress it, shift a big array, insert the sample and write the array to a file and do it on EVERY sample received?
Yeah, I'm talking about writing the array to a file because we need to persist this video somehow. It may happen that the battery stops working, and having it just in RAM will let us loose everything that we recorded!
The last idea that came to mind was to use a combo of VideoSink and FileSink.
While the FileSink does the compression magic (I even decompiled this class to understand what it does but there's no code inside!), we use the VideoSink's OnSample method to manually remove the unneeded data from the mp4 file used by the FileSink.
This one sounds quite hard because I don't know if I can write to the file with both FileSink and VideoSink without concurrency issues, and I've not found a good c# library to help me working with the mp4 files without having to deal with its structure.
The only library that I found is this one http://basemedia.codeplex.com/ but it totally lacks documentation (each link in the documentation page gives a 404 error).
I'm starting to think that this is something that can't be done, but I'd like to see if there's someone here which can point me to the right direction.
EDIT:
Just to be clear, I used the "recording" word and not the "recorded" one beacuse I'm talking about trimming the video while it's still recording!
This is not about editing it once it has been saved, but something more like removing stuff from the stream while I'm writing it to disk.
I cannot provide a code to you but just an idea. Because you have requirements:
I need to do is to keep just the last X minutes of the recorded stream.
Target platform is windows phone 8
I want to add some modifications to your first idea:
Write each minute of video stream in the separate file
Also you need to leave +1 video file more then a number of minutes. For instance if you need 5 minutes you should always keep 6 files because last file may be not full.
By use DirectShow you will able to join this files into one. Be ready to use C++ (As alternative to this you can use some service or make own back-end for this)
Related
I found myself being stuck on a certain problem. Currently I am writing a program in C#, that reads in .txts. These .txts are constantly changing, as in content is being added to them.
I created a FileSystemWatcher, that hands the name of the file to the method reading in my txt. Now I would like to have something in between, that remembers the last position I read in the txt and then only passes on the new part.
It also needs to remember it the next time I start the program.
I thought about storing the last line in a xml or txt and then letting my method search that file for the last line noted there.
The only similar question I found was this: Read log file from last read position . I don't really understand it though.
Is there anyway how to do this more efficient or elegant?
Edit: I already linked the suggested question and no, it is not similar to mine. I am looking to permanently store the information on how far I am into a .txt, not just on runtime.
When you need to store a finite amount of information on program state on the Windows platform in between runtimes, the Windows Registry is usually the way to go. Here's a stackoverflow question that will show you how. Use HKEY_CURRENT_USER so that you don't have UAC/Admin Rights issues:
Writing to registry in a C# application
.NET 4.0
Will this help? One way could be to store the line number instead of storing the content of the last line read.
Since .NET 4.0, it is possible to access a single line of a file directly. For instance, to access line 15:
string line = File.ReadLines(FileName).Skip(14).Take(1).First();
This will return only the line required
Okay so my overall goal is to create a UWP notes app that doesn't require the end-user to manually save each note they write; this would be done automatically for them.
So what I'm looking to do is create a C# class that will detect changes to the document the user is currently writing and constantly update the underlying text file (This will eventually be written to a row within the database, but I hear it is less efficient to constantly update records within a DB than to deal with text files for this matter?).
But yeah, this is pretty much what apps like OneNote do in the background for the user, and so the user have to never worry about saving the file or losing data in situations where the computer loses power or the app terminates unexpectedly.
So if I created a class that detected changes to the document and then update the underlying file, is the WHOLE file rewritten or just the particular parts (bytes?) that were changed within (or appended to) the text?
I'm just looking for the most efficient way to constantly update a file because if a user is a fast typist, the system will have to be able to keep up with every single keystroke input.
Last, would the entire file have to be rewritten if the user makes random changes to the text at random locations (rather than append to the end of the file)? Does any of this even make sense. I tend to write a lot to ask a simple question. I have problems....
I would do a timertick event and have it automatically save every 3 to 5 seconds. I do this alot. I understand what your doing, but automatically saving every key stroke, would be putting a lot of stress on the program.
I would automatically save every few seconds on a if basis,
If a change is detected then it will save. Think about this answer, it hs been saved almost 100 times if done by keystroke.
Imagine there is a game with a lot of content, like car models.
I don't want to have them in the RAM all the time to save memory and want to load them only when needed. This would be easily when having one file per car - but I would have so many files at the end and the project would become hard to share etc.
But when I store everything into one file, I don't know where what is.
Is there a way storing everything into one file and navigate to the content as easily as if I do one file per content entry? Only thing I can imagine is saving the byte positions where something begins in a 2nd file (or as header in the content file) but I'm very unsure about that solution.
A simple way to do it is when you write the file you keep track (in memory) where stuff is. Then, at the end of the file you write an index. So your file looks like this:
offset 0: data for object 1
offset 0x0473: data for object 2
offset 0x1034: data for object 3
etc.
You can write this file using BinaryWriter. Before you write each object, you query writer.BaseStream.Position to get the current position of the file. You save that information in memory (just the object name and its position).
When you're done writing all of the objects, you save the current position:
indexPosition = writer.BaseStream.Position;
Then write the index at the end of the file:
name: "object 1", position: 0
name: "object 2", position: 0x0473
etc.
Write an empty index entry to signify the end of objects:
name: "", position: 0xFFFFFFFF
And the last thing you do is write the index position at the end of the file:
writer.Write(indexPosition);
Now, you can open the file with a BinaryReader. Seek to end-of-file minus 8 bytes, read the long integer there. That gives you the position of the index. Seek to the index and start reading index entries forward until you get to one that has a position of 0xFFFFFFFF.
You now have the index in memory. You can create a Dictionary<string, long> so that, given an object name, you can find its position in the file. Get the position, seek there, and read the object.
This kind of thing was pretty common when we were writing games in the late '90s. You can still do it, although you're probably better off going with a simple database.
There are quite a few different compression and archiving methods you could use to hold your files if you're looking to store them temporarily in a larger file for transport. Almost any compression method could work, which you choose is entirely up to you.
Example .zip compression can be found here:
http://msdn.microsoft.com/en-us/library/ms404280.aspx
There's also the .cab file format that you can easily pack multiple files into and unpack later when you have need for them. There's an interesting article on creating .cab files in C# found here:
http://mnarinsky.blogspot.com/2009/11/creating-cab-file-in-c.html
It does require that you add references to Microsoft.Deployment.Compression.Cab.dll and Microsoft.Deployment.Compression.dll but the code itself is fairly simple after that. If you find none of those to be a suitable answer to your question, my only other suggestion is that you better organize the files rather than cramming them all into a single folder as that can make it quite difficult to navigate.
Also try using a collection to keep track of the file names if that helps too. You could define files in the XML and load everything into a dictionary or hash table if it needs to be more dynamic or define it in the code itself if you prefer that.
EDIT:
You can also try using a third party installer for transport. They offer many functions outside of compressing and packing files and will handle the data compression for you. I prefer NSIS personally as I find it to be highly user friendly but any installer can work. A few example installers are:
Installshield: http://www.installshield.com/ (integrates with Visual Studio)
WIX: http://wix.sourceforge.net/ (also integrates with Visual Studio, good if you're looking for something more XML based)
NSIS: http://nsis.sourceforge.net/Main_Page (scriptable, doesn't integrate with Visual Studio, easy guided design with Nsisqssg if you'd prefer not to do the bulk of the scripting on your own)
They all function differently but essentially achieve the same end result. It all depends on exactly what you're looking for.
As many other question about this topic, I still didn't find something that could avoid my issue.
I'd like to know what are the limitations of the clipboard in term of copy paste processing in time and restrict its copy paste functionality for specific usage and program ID.
Because, I've been developping a software for my company that takes a template in Word/Excel and PowerPoint to make auto generated reports by replacing the picture every day and pasting the new graph and the picture which are in the template.
But, I'm afraid, because it seems to exist some limitations about the copy to clipboard
CopyBitmapToClipboard
ActiveWindow.View.PasteSpecial()
When I copy a table/image into my clipboard and paste it in Word/Excel/PowerPoint it is fine, but if I have now 10 parallel reports which are generated at the same time and use the mechanism of copy paste, it will happen that it will copy it in the Word/Excel/PowerPoint that is currently being used by another report.
Taking in consideration, I have 1 document, and the copy to clipboard of a table that is huge into powerpoint, would take the best case 1 second( which doesn't ), this would mean that in 1 day, I can generate a maximum of
1 copy paste procedure = 1 second
1minute = 60 second means 60 copy paste
1hour = 60min x 60 copy paste
1day = 24hours x 3600 copy paste
Means I have a total of 86400 copy paste/reports. Which is impossible. A document will never take minimum of 1 second to be complete( for reports which are about 20 pages, powerpoint with 30 slides, excel worksheet with 6sheets ). How to avoid that the content copied into clipboard will be pasted in the wrong document, since both documents use the paste fonction.
So, I'd like to know, if it is possible to give a reference into my clipboard, to tell him, to copy only the content inside his word/excel/powerpoint and not to copy what I just copied doing CTRL+C and to do CTRL+V in the wrong document?
At the moment, we have about 50 reports daily to generate( taking in consideration that few months ago we had 2 reports to generate ), which are scheduled in interval of 5 minutes, but what will happen the day we will have 86400 daily reports to generate? The copy paste fonction will screw up all reports and paste in the wrong report. I might not be there to assist it, but I'd like to prevent that impact.
I was writing my software in C#/.NET, but I can't write inside it to catch if a current schedule/report is being generated, because I run a .bat that does the creation of the report with the program I wrote.
**Edited:
Content of my .bat is:
myprogram.exe /objectsourceprogram="" /sourcefile="my template.doc/xls/ppt" /destinationfile="my destination.doc/xls/ppt"
I'm only scheduling my batch file, the only thing that can be done is, waiting that one scheduling is being completed before starting the next one, but this will create intervales
I've dealt with auto-generated reports in Word and Excel as well. You're doing it the slow way, no wonder it's slow - .NET COM interop is quite slow as it its and then your process utilizes other threads, so now you have to take marshalling and synchronizing between threads since Office is single-threaded.
Copy/paste is a high-level, user function and you can use it as a hack but relying on it as a primary way of executing your task is a poor choice.
Better choice: Office APIs (VSTO, anyone?) - I'm pretty sure whatever you've come up with in terms of reports is reproducible through APIs. Beware - too many API calls and your functions can work slower.
Best choice: OpenXML SDK. The learning curve here will likely be steep since you're still using Copy/Paste but the payoff is that your document processing time will be reduced a couple orders of magnitude.
I'm using System.Windows.Media.MediaPlayer to play some sounds, and I would like to load these sounds from a ZIP file. It would be nice to be able to load these files as a stream directly from the zip file instead of having to unzip to a temp directory. However, MediaPlayer.open only accepts an URI.
So, is there a way to create a URI that will reference the contents of a stream? Something like an in-memory localhost? Is there any connector from Stream to URI?
System.Media.SoundPlayer should do what you need (you can skip MediaPlayer and URIs altogether). It has a constructor that takes a stream.
Since you need to support polyphony, one approach is to PInvoke into the waveOutXXXX Windows API in order to play the sounds. Here is a good example of how to do this in C#:
https://www.codeproject.com/KB/audio-video/cswavplay.aspx
This example also has code for reading info like duration, sample rate, bits per sample etc.
If you search, you may find claims that the waveOutXXXX API can only play one sound at a time. This was true in Windows 95/98, but is not true any longer.
By the way, SoundPlayer is probably the most frustrating .NET class. The .Play() method automatically stops playback of any other sound played by your process (it might be any other sound played by any .NET app) before starting, which is why you can't do polyphony with it. It would have taken Microsoft's worst intern less than a minute to add a .DontStopJustPlay() method or a StopFirst bool parameter to the .Play() method. It might have taken him until lunch time to add a Duration property.
Although waveOutXXXX is trickier than you would want from a well-designed modern API (and using it in .NET introduces additional problems), the one unmatched advantage it has is that it's come pre-installed on every single Windows computer since Windows 95, including Windows Mobile devices. Every other option (including MediaPlayer) means somebody will always have to install something.