extracting single frame from MediaElemet or FFmpegInterop - c#

I am writing app (Windows Phone 8.1 Store App) that allows user to connect to IP Camera. I am using FFmpeg Interop library for ffmpeg which allows me to play eg. rtsp streams in media element. I need now a way to somehow extract a single frame from stream or from media element.
I have tested other application wchih allows connecting to IP cameras - IP Centcom, and they have working snapshots only for mjpeg streams as far as I now (they were not working for rtsp). Becouse of that I belive that it is impossible or at very least very hard to export frame from media element.
I have different question - if anyone has ever used FFmpeg Interop and would like to help/explain me how could I modify/extend FFmpegInteropMSS to add method called 'GetThumbnailForStream' that would work similary to 'GetMediaStreamSource' but would return single frame (bitmap or jpg) instead of MediaStreamSource?
Every help would be appreciated
EDIT:
I have found something;
in MediaSampleProvider in method WriteAVPacketToStream (line ~123) there is line
auto aBuffer = ref new Platform::Array<uint8_t>(avPacket->data, avPacket->size);
and I belive that this is the place that stores single frame data that is needed to convert into bitmap - now since I do not know c++ too much I have a question : how can I convert it into a form that I could return via public method ?
When returning:
Platform::Array<uint8_t>^
I get
'FFmpegInterop::MediaSampleProvider' : a non-value type cannot have any public data members
EDIT2:
Ok I am doing approprate projection to byte according to this microsoft information, now I need to check if this is correct data.

Related

Calling NvAPI_GPU_SetEDID on Nvidia card

How do you call this method on Nvidia GPU:
NVAPI_INTERFACE NvAPI_GPU_SetEDID (
NvPhysicalGpuHandle hPhysicalGpu,
NvU32 displayOutputId,
NV_EDID * pEDID
)
Src: http://docs.nvidia.com/gameworks/content/gameworkslibrary/coresdk/nvapi/group__gpu.html#ga6a41b31dd9743120213435d985f8fbcf
I need to execute the above command to remove all EDID set on all DisplayOutputs on our new Quadro Graphics Cards. Based on the API documentation, I tried searching for NvPhysicalGpuHandle and came across this project/library:
https://github.com/openhardwaremonitor/openhardwaremonitor/blob/master/Hardware/Nvidia/NVAPI.cs
This does not have the method I need NvAPI_GPU_SetEDID
I am not hardware programmer, I just need to be able to call this one command. any ideas? Can this be achieved using nvapi.dll/nvapi64.dll via pinvoke or something?
I personally didn't test this, but you can try the library and see if it can set EDID information without any problem, if it fails, please open an issue.
https://github.com/falahati/NvAPIWrapper
Here is how you should do it,
First, you need to find the right DisplayDevice or GPUOutput that you want to write EDID information to. There are multiple ways to do so.
Get a list of all PhysicalGPUs in the system using the NvAPIWrapper.GPU.PhysicalGPU.GetPhysicalGPUs() static method, then select the PhysicalGPU you desire based on your logic. After finding the right PhysicalGPU, use the NvAPIWrapper.GPU.PhysicalGPU.GetDisplayDevices() method to get a list of all connected DisplayDevices to that GPU and store the right one in a variable.
Instead of searching for connected DisplayDevices, you can also go for the GPUOutputs. Just like before, you first need to find the right PhysicalGPU and then you can get a list of all GPUOutputs using the NvAPIWrapper.GPU.PhysicalGPU.ActiveOutputs property and store the right GPUOutput in a variable.
Another way to find the right DisplayDevice is to go for a list of all Displays. To do so, you need to use the NvAPIWrapper.Display.Display.GetDisplays() static method. This returns an array of Displays. Then using the NvAPIWrapper.Display.Display.DisplayDevice property, you can get the corresponding DisplayDevice of a Display.
After finding the right DisplayDevice or GPUOutput, you should use the NvAPIWrapper.GPU.PhysicalGPU.WriteEDIDData() method. This method allows you to write EDID data stored in a byte array to the DisplayDevice or the GPUOutput you selected before.
Note: Make sure to capture NVIDIAApiException and check for the NVIDIAApiException.Status property in case something went wrong.

Issue with printing an arbitrary sequence of strings and images in C#

So, long story short: I'm writing a POS program, and I have a receipt printer connected and the Windows Forms printing API works great with it, much easier than I expected.
However, searching through the API, it seems that the easiest (or perhaps only) way to programmatically print something is to use the Graphics object inside the PrintPageEventArgs object in the printer's event handling method.
Every overloaded parameter list for the Graphics.DrawXXX() method requires some kind of coordinate pair to use as a reference point for where to start drawing the object passed to it.
So my question is, let's say I want to print some string value, and then an Image. Doing it the other way around (first the Image, then the string) would be easy because the reference point to start drawing the string would be (0, Image.Size.Height). However, since a string does not have a "size" associated with it, what is the best way to go about telling the printer where to start drawing an image after a string has been printed?
Let me know if this is confusing or needs additional clarification.

Decode H264 frames C#

I am using Managed Media Aggregation in C# - https://net7mma.codeplex.com/.
I have a Rtsp Client that receives RTP Frames encoded in h264 (payload type 96).
I want to be able to save the frames into a video file, and also be bale to tell when the video starts\ends.
I did some reading and I read that its a problem to decode h264 frames one-by-one.. didn't really understand why.
Here is the method that is raised for each RTP frame that I receive
void Client_RtpFrameChanged(object sender, Media.Rtp.RtpFrame frame)
{
// Decode
}
Can someone explain why its a problem to decode h264 frames one-by-one?
Is there a open source/library/dll for this?
Thanks a lot!
There is an included class in the RtspServer project.
The class is RFC6184Media, it contains methods for packetization and depacketiation and handles all defined Nal Unit types.
After you call Depacketize there is a Buffer which contains the Raw Bit Stream Payload, you will have to add a start code consisting of 0x000001 and then the data contained in the raw bitstream.
There are several examples in the Discussion area for the project.
After that you can feed the stream to a decoder for decoding and only then can the frames can be displayed; usually by conversion from Yuv to Rgb respective to the sub sampling used when encoding.
I can see about adding a small demo for a few static packets which corresponds to a frame and show how to achieve the desired result.
In the future if you make a discussion on the project page I will probably get to it much quicker.

How to remove metadata from jpg and png images

This should be a pretty trivial programming task in C#, however after I have searched a while I simply cannot find anything relevant on how to remove metadata.
I want to remove jpg and png image metadata such as: folder path, shared with, owner and computer.
My application is an MVC 4 application. In my website users can upload an image I get this image at this ActionResult method
if (image != null)
{
photo.ImageFileName = image.FileName;
photo.ImageMimeType = image.ContentType;
photo.PhotoFile = new byte[image.ContentLength];
image.InputStream.Read(photo.PhotoFile, 0, image.ContentLength);
}
Photo is a property in the model, goes like this.
public byte[] PhotoFile { get; set; }
I imagine the way to remove above mentioned metadata or just all metadata, would be to use some coding like this
if (image != null)
{
image = image.RemoveAllMetaData; !!!
I dont mind using some 3rd party dll as long as it is compatible with NET 4.
Thanks.
'Metadata' here is a bit ambiguous--Do you mean the data which is required for a viewer to properly determine the image format so it can be displayed, saving only the raw image data? Or, more likely, do you mean the extra information, such as author, camera type, GPS location, etc, that is often added via the EXIF tags?
If you mean something like the EXIF data, there's a lot of programming material already on the web about how to add/modify/remove EXIF tags, and even some apps which already strips such tags: http://www.steelbytes.com/?mid=30 for example.
If you mean you just want the raw image data, you'll probably have to read and process the image first, since both JPEG and PNG do not contain simply the raw image data; It's encoded with various methods--which is why they contain metadata to tell you how to decode it in the first place. You'll have to learn/explore the JPEG and PNG data formats to extract the original raw image data (or a reasonable facsimile in the case of a "lossy" encoding).
All the above is well-documented on various websites which can be found on Google, and many include image manipulation libraries which can handle these chores for you. I suspect you just didn't know to search for something like "JPEG PNG EXIF METADATA".
BTW, EXIF applies to JPEG's, where EXIF is, loosely (and not fully technically correct) an addition of data (extension) to the end of the JPEG file, which can usually simply be truncated to remove. A quick Google search for me turned up something like libexif.sourceforge.net and other similar results.
I'm not entirely certain about the PNG format, but I believe the PNG format (which does call such items "metadata" as well) was written to include such data as part of the file format rather than an "extension" tagged on after the fact like EXIF is. PNG, however, is open source, and you can obtain libraries and code for manipulating them from the PNG website (www.libpng.org).
There's an app for that but it's written in Perl. It doesn't recompress the image and it's here http://www.sno.phy.queensu.ca/~phil/exiftool
Found it in this thread
How to remove EXIF data without recompressing the JPEG?
Do what all the social media websites do. Create a new image file, stream in the image byte data and use the file you created than the original one that was uploaded. Of course, now you will need to find out the original image's color depth and so on so that the image you create is not of a lower quality -- unless you need to do a disk or image resize as well.

Plotting geocoordinates in a Windows 8/Bing maps app

I'm making a C#/XAML Windows 8 app using Bing Maps. I'm copying a bunch of Windows Phone 7 code over, and I'm having a problem simply plotting geocoords. Here's the WP7 code:
GeoCoordinate mapCenter = new GeoCoordinate(37.784, -122.408);
map1.Center = mapCenter;
However, when I try to instantiate mapCenter in Win 8, (and I do use lowercase Geocoordinate instead of GeoCoordinate) I get an error saying that "Windows.Devices.Geolocation.Geocoordinate does not contain a constructor that takes 2 arguments".
I'm sorta stumped, as I planned on using Geocoordinates quite a bit, and I'm not really sure how to figure out what exactly the Geocoordinate constructor takes.
thanks,
Amanda
Edited to fix code indentation
The Windows.Devices.Geolocation.Geocoordinate class cannot be directly instantiated. Also, keep in mind, that the namespace you are using is used specifically for retrieving location data from the device.
First, you'll need to get an instance of Geoposition via Geolocator.GetGeopositionAsync.
You can then get the Geocoordinate instance from Geoposition.Coordinate.
If you're looking to simply center the map on a given latitude and longitude (and you're using the Bing Maps for Windows Store Apps SDK), it looks like you should be using the Location class instead (as Map.Center is of type Location).
Your code and you error output are saying two different things. I had the same problem make sure you are using the capital C in GeoCoordianate in you code. teh lower case C in geocoordinate is for getting the phones location.
The Center property of the Map control requires a value of type GeoCoordinate from the System.Device.Location namespace. If you are using location services from the Windows.Devices.Geolocation namespace, you have to convert a Windows.Devices.Geolocation.Geocoordinate value to a System.Device.Location.GeoCoordinate value for use with the Map control.
You can get an extension method to do this conversion, along with other useful extensions to the Maps API, by downloading the Windows Phone Toolkit. If you want to write your own code, here is an example of a method that you can use to convert a Geocoordinate to a >GeoCoordinate:
from http://msdn.microsoft.com/en-US/library/windowsphone/develop/jj207045(v=vs.105).aspx#BKMK_converting

Categories