How to read using C++ (C#) sound stream sent by flash? - c#

I need to read sound stream sent by flash audio in my C++ application (C++ is not a real limitation, it may be C# or any other desktop language).
Now flash app sends audio to another flash app but I need to receive the same audio by desktop application.
So, is there a standard or best way how to do it?
Thank you for your answers.

How is the sound actually sent? Via the network?
Edit: You'd be either capturing the audio from an HTTP stream, or an RTMP stream. Run Wireshark to find out, but I suspect you're doing something slightly shady...

You could try using the sound system from the Gnash project.

So basically you want to connect to RTMP sound stream from flash media server from an arbitrary non-flash application? Have you taken a look at http://en.wikipedia.org/wiki/Real_Time_Messaging_Protocol ?

Unfortunately, Adobe IS relatively proprietary (hence the apple-adobe wars happening lately), but for several languages, there are projects to help out with RTMP.
WebOrb is commercial, for .NET, Java, PHP:
http://www.themidnightcoders.com/products.html
FluorineFX is open source for .NET only:
http://www.fluorinefx.com/
I haven't used either myself for RTMP, but I have used FluorineFX to connect to a flash remoting (AMF) gateway. I imagine it may do what you need for receiving the audio stream from a .NET-enabled client.

Getting the frames, frame rate and other attributes of video clip
If you have experience with writing applications in Microsoft DirectShow Editing Services (codename Dexter), this will sound very familiar to you. In the Windows environment, traditionally capturing still frames has been done using C++ and Dexter Type Library to access DirectShow COM objects. To do this in .NET Framework, you can make an Interop assembly of DexterLib which is listed under COM References in VS 2005. However it takes you a good amount of work to figure out how to convert your code from C++ to C# .NET. The problem occurs when you need to pass in a pointer reference as an argument to a native function, CLR does not directly support pointers as the memory position can change after each garbage collection cycle. You can find many articles on how to use DirectShow on the CodeProject or other places and we try to keep it simple. Here our goal is to convert a video file into an array of Bitmaps and I tried to keep this as short as possible, of course you can write your own code to get the Bitmaps out of a live stream and buffer them shortly before you send them.
Basically we have two option for using the DirectShow for converting our video file to frames in .NET:
Edit the Interop assembly and change the type references from pointer to C# .NET types.
Use pointers with unsafe keyword.
We chose the unsafe (read fast) method. It means that we extract our frames outside of .NET managed scope. It is important to mention that managed does not always mean better and unsafe does not really mean unsafe!
MediaDetClass mediaClass = new MediaDetClass();
_AMMediaType mediaType;
... //load the video file
int outputStreams = mediaClass.OutputStreams;
outFrameRate=0.0;
for (int i = 0; i < outputStreams; i++)
{
mediaClass.CurrentStream = i;
try{
//If it can the get the framerate, it's enough,
//we accept the video file otherwise it throws an exception here
outFrameRate = mediaClass.FrameRate;
.......
//get the attributes here
.....
}catch
{ // Not a valid meddia type? go to the next outputstream }
}
// No frame rate?
if (outFrameRate==0.0)
throw new NotSupportedException( " The program is unable" +
" to read the video file.");
// we have a framerate? move on...
...
//Create an array to hold Bitmaps and intilize
//other objects to store information...
unsafe {
...
// create a byte pointer to store the BitmapBits
...
while (currentStreamPos < endPosition)
{
mediaClass.GetBitmapBits(currentStreamPos, ref bufferSize,
ref *ptrRefFramesBuffer,
outClipSize.Width, outClipSize.Height);
...
//add frame Bitmap to the frameArray
...
}
}
...
Transfer extracted data over HTTP
So far we have converted our video to an array of Bitmap frames. The next step is to transfer our frames over HTTP all the way to the client�s browser. It would be nice if we could just send our Bitmap bits down to the client but we cannot. HTTP is designed to transport text characters which mean your browser only reads characters that are defined in the HTML page character set. Anything else out of this encoding cannot be directly displayed.
To accomplish this step, we use Base64 encoding to convert our Bitmap to ASCII characters. Traditionally, Base64 encoding has been used to embed objects in emails. Almost all modern browsers including Gecko browsers, Opera, Safari, and KDE (not IE!) support data: URI scheme standard to display Base64 encoded images. Great! Now, we have our frames ready to be transferred over HTTP.
System.IO.MemoryStream memory = new System.IO.MemoryStream();
while (currentStreamPos < endPosition)
{
...
// Save the Bitmpas somewhere in the (managed) memory
vdeoBitmaps.Save(memory, System.Drawing.Imaging.ImageFormat.Jpeg);
//Convert it to Base64
strFrameArray[frameCount] = System.Convert.ToBase64String(memory.ToArray());
//Get ready for the next one
memory.Seek(0, System.IO.SeekOrigin.Begin);
}
memory.Close();
...
But we cannot just send out the encoded frames as a giant string. We create an XML document that holds our frames and other information about the video and then send it to the client. This way the browser can receive our frames as a DOM XML object and easily navigate through them. Just imagine how easy it is to edit a video that is stored in XML format:
14.9850224700412
{Width=160, Height=120}
6.4731334
/9j/4AAQSkZJRgABAQEAYAB....
....
This format also has its own drawbacks. The videos that are converted to Base64 encoded XML files are somewhere between 10% (mostly AVI files) to 300 % or more (some WMV files) bigger than their binary equivalent.
If you are using an XML file, you even don't need a web server , you can open the HTML from a local directory and it should work! I included an executable in the article's download file that can convert your video file to XML document which later can be shown in the browser. However using big files and high resolution videos is not a good idea!
OK, now we can send out our �Base64 encoded video� XML document as we would do with any other type of XML files. Who says XML files always have to be boring record sets anyway

Related

get image from video stream in C#

I am trying to get image from a stream (MemoryStream to be more precise). I can not find anything from Microsoft that can solve my problem.
I am getting my streams from SQL so if there is some way to get an image from there, it will be OK.
I have checked ffmpeg and the problem is that I need to save the video files. The files can reach up to 2GB and if there is a way not writing to the disk it will be helpful. If there is a way to read only the first 10MB or other limited size and read the image from it, that can also be a solution.
Video feed might be as simple as raw uncompressed video frames side by side to more complex multiplexed file format compatible chunk of data, e.g. .MP4 file. While the former case might be pretty simple, the latter requires you to demultiplex the file, seek within the stream, start decoding, possibly skip a few frames, then grab the frame of interest. The point is that it might be not as simple as it seems.
Video processing APIs in Windows are DirectShow, Media Foundation. With DirectShow it is possible to create a custom data source on top of SQL backed data stream and stream from there fetching DB data on demand, using API interfaces components (stock and third party) to do the rest of the task.
It is possible to capture frames with free VideoConverter for .NET that actually is a wrapper to FFMpeg tool. The idea is using live streaming capabilities (to C# Stream) of VideoConverter for special FFMpeg format "rawvideo" that actually is bitmap stream that can be processed by C# program, something like that:
var videoConv = new FFMpegConverter();
var ffMpegTask = videoConv.ConvertLiveMedia(
"input.mp4",
null, // autodetect live stream format
rawBmpOutputStream, // this is your special stream that will capture bitmaps
"rawvideo",
new ConvertSettings() {
VideoFrameSize = "320x200", // lets resize to exact frame size
CustomOutputArgs = " -pix_fmt bgr24 ", // windows bitmap pixel format
VideoFrameRate = 5, // lets consume 5 frames per second
MaxDuration = 5 // lets consume live stream for first 5 seconds
});
VideoConverter can read live streams from another .NET Stream (if input format can be used with live stream conversion).

How to play non-PCM file or convert it to PCM on the fly ?

The following code works with some wav files, but with others I get, "InvalidOperationException was unhandled. Message=Sound API only supports playing PCM wave files."
var webClient = new WebClient();
webClient.DownloadFile(url, fileName);
var fileSound = new SoundPlayer(fileName);
fileSound.PlaySync();
Is there a way to programmatically check if a wav file is "bad" (not a PCM wave file) and then convert it as necessary?
What is odd is that the code works in the legacy Delphi app - all of the wav files play just fine. Here's the Delphi code:
filename := GetEnvironmentVariable('TEMP')+'\archieAndDingbat.wav';
URLDownloadToFile(nil, PChar(url), PChar(filename), 0, nil);
PlaySound(filename);
I looked at the properties of the two files in Explorer, and I see that there is, indeed, a difference. For the file that does play, its audio format is PCM; the one that won't play is CCITT u-Law.
So...I either need a way to convert from CCITT u-Law to PCM on the fly after downloading these files (they are download from an url and then played locally) OR perhaps a different way of playing these files than PlaySync() ...
Look at audiolab library from mitov. It works great
So, do you want to PLAY the file or CONVERT it ? What is the primary goal ? Do you play it as a prove you can convert it, or do you convert it because you don't know how to play not-converted file ?
http://www.catb.org/esr/faqs/smart-questions.html#goal
Your question's title claims "convert" but the body claims "Play"
This answer is about playing files.
You also may try to use FFDShow codecs directly without DirectX intermediate.
http://en.wikipedia.org/wiki/Libavcodec and http://libav.org/ and http://ffmpeg.org/ (they recently had a schism)
Googling for "FFDShow dotnet", "libav dotnet", "ffmpeg dotnet" shows a bunch of libraries to use it, such as
https://github.com/ermau/libav.net
Controlling ffdshow from .Net
Solid FFmpeg wrapper for C#/.NET
There is also BASS library. It is targeted as sound playback during gaming, so it probably has less range of formats and not much for re-coding. Still many music players are built on top of it. Some says it is the most simple API to use. So it worth considering. http://www.un4seen.com/
http://MediaInfo.sf.net is a library (native win32/win64 DLL) allowing to check most multimedia formats content.
I don't know if using tis C or C++ APis is easy from C# side.
The way to do it is to use newkie's code at: http://www.codeproject.com/Articles/175030/PlaySound-A-Better-Way-to-Play-Wav-Files-in-C?msg=4366037#xx4366037xx
In my case, at least, I had to change all of the lowercase x's to uppercase x's, though, to get it to work.

Get Stream and save as jpeg (image) file from IP Camera using ffmpeg

How i can get stream from Ip Camera, Its using RTP, stream is MPEG4, i have multicast address and port,and i have ip camera's IP address and Port Number. And I cant reach via http forexample (http://ip/jpeg) And I cant reach stream with VLC Player too. forexample (rtp://ipadressofcam:port) and (rtp://multicastaddress:port)
So What is ffmpeg command of that?
I have windows OS, I only write code with C# right now.
But producer created their own ocx which used for viewing cam,that plugin can work on .net but i dont want to use it becouse it doesnt have much funcionality, I mean you cant get current picture or snapshot of cams, thats why i have to do it myself.
Are you sure the stream is not password-protected?
Try to see why your camera rejects VLC requests. And this is how to do it: Install Wireshark, start it, and put a filter for the camera address, like: ip.addr == camera_ip (xxxx.xxxx.xxxx.xxxx). Then, try to connect with VLC, and look there at the messages exchanged. If you see a DROP, UNAUTH, or something that tells you to use a passwd, introduce it. (VLC will first try to connect using an unauthenticated procedure, and if it fails, will ask for a passwd.)
Wireshark will give you clues if the failure reason is something different.
And keep in mind that if VLC can't access it, the chance to find some other way to do it is almost zero. Unless you're a video guru.
Hope it helps!
You can use VLC for such a thing ,and it's ActiveX control which is available for .NET also ,just need to install VLC Media Player and you can set it's control on VS toolbox
http://forum.videolan.org/viewtopic.php?f=32&t=54969
UPDATE
If you are ready to pay for this stuff you can use http://www.mainconcept.com/products/sdks/video.html this Company product's to advance with Decoding and Encoding ,where you can find a huge Library .
So you want to receive video stream from camera and convert individual frame into JPEG file. This sounds good and actually sounds natural: why not? there is a video feed being sent on network and we don't need much, just to pick individual frame.
The original stream is MPEG-4 (Part 2) and desired target encoding is JPEG. This breaks the task into parts of getting MPEG-4 video feed, decoding it into uncompressed images, and encoding into JPEG. Let us go through these from the last one backwards.
JPEG is a popular encoding and there are various codecs with different interface capable of compressing into JPEG. Options include GDI+ API, IJG JPEG library libjpeg, JPEG libraries and codecs for video with DirectShow and other interfaces.
MPEG-4 decoder is a complicated component, however is luckily well standardized and available in different interfaces and from several sources. In particular MPEG-4 Part 2 Video Decoder is shipped as DMO (and also through ) with Windows 7. Decoder is also available as DirectShow filter in ffdshow, Intel Media SDK.
Back to the first step, you need to reach MPEG-4 stream from network. First of all you indicated that the camera is available on multi-cast UDP address. This makes you open a socket and put into onto multi-cast group in order to start receiving RTP data. The data you would receive is not pure MPEG-4 yet, and is formatted according to RTP Payload Format for MPEG-4 Audio/Visual Streams and as you receive RTP stream of messages you will have to be prepared to receive out of order fragments, packet losses etc. You are supposed to receive what you can receive, check the RTP headers, and do your best in reconstructing MPEG-4 feed.
Eventually you need to cover these steps (not necessarily directly, you would rather use third party libraries including those mentioned in other answers) from your application and build a pipeline which stitches together receiving from network and transcoding.
So until now, I saw VLC cant open it but if we create .sdp file and play it with ffplay only a black screen appears.
vlc -vvv dshow:// --sout-keep --sout-all --sout=#rtp{dst=multicastaddress,port=portNo,sdp=file:///C:/test/my.sdp}
Of course this is not pure solution but there is little bit hope.
But obsolute solution can be like that;
There is no way to use just c# to achive what i intend. There are few c++ library components that i can use, but i can use it along with Managed c++ to write interop services and use those dlls in my c# code.Here is what i need:
1-I need an RTP Library, http://research.edm.uhasselt.be/~jori/page/index.php?n=CS.Jrtplib or live555 but live555 has certain limitations.
2-RTP Library is the transport for the MPEG4 stream i pull from my encoder. But i need ways to control the stream, those are provided producer's WSDLs.
3-After that i need a decoder; Libavcodec, I can use libavcodec to convert an Iframe to a jpeg image in .net.

Audio output from Silverlight

I'm looking to develop a Silverlight application which will take a stream of data (not an audio stream as such) from a web server.
The data stream would then be manipulated to give audio of a certain format (G.711 a-Law for example) which would then be converted into PCM so that additional effects can be applied (such as boosting the volume).
I'm OK up to this point. I've got my data, converted the G.711 into PCM but my problem is being able to output this PCM audio to the sound card.
I basing a solution on some C# code intended for a .Net application but in Silverlight there is a problem with trying to take a copy of a delegate (function pointer) which will be the topic of a separate question once I've produced a simple code sample.
So, the question is... How can I output the PCM audio that I have held in a data structure (currently an array) in my Silverlight to the user? (Please don't say write the byte values to a text box)
If it were a MP3 or WMA file I would play it using a MediaElement but I don't want to have to make it into a file as this would put a crimp on applying dynamic effects to the audio.
I've seen a few posts from people saying low level audio support is poor/non-existant in Silverlight so I'm open to any suggestions/ideas people may have.
The simple answer is that there is no support for PCM playback from Silverlight in version 2. So unless you want to write a fully managed PCM to MP3 converter you are stuck. Even then I'm not sure you could get the MediaElement to play from isolated storage.
Is there any chance you could use a web service to perform the conversion?
See also this question:
Where's the sound API in Silverlight? Or, how do I write a music app to run in the browser?
Update: Silverlight 3 supports your custom audio sources. However, it won't let you intercept samples to perform effects on WMA or MP3, presumably for DRM reasons, so you would still potentially need to write your own decoder.
Short answer is use a MediaElement + a MediaStreamSource
Check out these:
http://blogs.msdn.com/gillesk/archive/2009/03/23/playing-back-wave-files-in-silverlight.aspx
http://code.msdn.microsoft.com/wavmss/Release/ProjectReleases.aspx?ReleaseId=2417
Basically, write a decoder in managed code to convert G.711 a-Law to PCM, then do whatever modifications you want to the raw values, then pass those into a MediaStreamSource.
Looks like Silverlight 3 supports direct PCM output now, or will when released. I don't see anything in the docs about the raw AV pipeline yet.
Mark Heath's answer is correct - only certain formats are supported - mp3 and certain flavours of WMA (unfortunately not WMA lossless which would be 'closer' to PCM).
To play PCM data in Silverlight, you could do the following:
* Convert the PCM into mp3 data, and store it in memory.
* Play the mp3 data using the technique presented at ManagedMediaHelpers. The idea here involves a class called Mp3MediaStreamSource (derived from System.Windows.Media.MediaStreamSource) that provides mp3 chunks to a MediaElement to play. The chunks will need to be in a stream, but of course a memory stream will do.
I initially thought you might be able to provide PCM chunks via MediaStreamSource, but this does not work. It's a real shame as it would solve your problem (and the one I was facing - making a Speex audio file player) really easily!

Creating an MJPEG video stream in c#

I have images being sent to my database from a remote video source at about 5 frames per second as JPEG images. I am trying to figure out how to get those images into a video format so I can stream a live video feed to Silverlight.
It seems to make sense to create a MJPEG stream but I'm having a few problems. Firstly I was trying to stream via an HTTP request so I didn't have a deal with sockets but maybe this is breaking my code.
If I try surf to my stream from QT I get a video error, Media player shows the first frame image and Silverlight crashes :)
Here is the code that streams - since I content type used this way can only be sent once I know that it isn't ideal and might be the root cause. All images are coming in via a LINQ2SQL object.
I did already try simply updating the image source of an image control in Silverlight but the flicker isn't acceptable. If Silverlight doesn't support MJPEG then no point even continuing but it looks like it does. I do have access to the h.264 frames coming in but that seemed more complicated via MP4.
Response.Clear();
Response.ContentType = "multipart/x-mixed-replace; boundary=--myboundary";
ASCIIEncoding ae = new ASCIIEncoding();
HCData data = new HCData();
var videos = (from v in data.Videos
select v).Take(50); // sample the first 50 frames
foreach (Video frame in videos)
{
byte[] boundary = ae.GetBytes("\r\n--myboundary\r\nContent-Type: image/jpeg\r\nContent-Length:" + frame.VideoData.ToArray().Length + "\r\n\r\n");
var mem = new MemoryStream(boundary);
mem.WriteTo(Response.OutputStream);
mem = new MemoryStream(frame.VideoData.ToArray());
mem.WriteTo(Response.OutputStream);
Response.Flush();
Thread.Sleep(200);
}
Thanks!
EDIT: I have the stream working in firefox so if I surf to the page I see video! but nothing else accepts the format. Not IE, SL, Media player - nothing.
I did MJPEG a long time ago (3-4 years ago) and I'm scratching my head trying to remember the details and I simply can't. But, if its possible, I would suggest finding some kind of web site that streams MJPEG content and fire up wireshark/ethereal and see what you get over the wire. My guess is you are missing some required HTTP headers that firefox is little more forgiving about.
If you can't find a sample MJPEG stream over the internet, a lot of web cams have software that give you an MJPEG stream. The app I worked on it with was a console for multiple security cameras, so I know that is a common implementation for cams of all types (if they support a web interface).
I'm far from being an expert in MJPEG streaming, but looking at the source of mjpg-streamer on sourcefourge I think you should send each frame separately, writing the boundary before and after each of them. You should of course not write the content-type in the closing boundary.
First, write your mjpeg frames out to separate files. You should then be able to open these in Phototshop (this will independently verify that you are parsing the stream correctly). If this fails, by bet is that you have HTTP headers embedded in your image data.
Have you looked at various web cam setups that exist on the net? A lot of them do some sort of low res update without flicker. You should be able to reverse engineer these types of sites for additional clues to your problem.
Some sites create a GIF animation, maybe that is an option so that the user can see the past minute or so.
About your edit: MJPEG is supported by Firefox and Safari. However other applications do not, like Explorer or Silverlight depending on what you are doing with it.

Categories