Forums

Full Version: Play video from Memory Stream
You're currently viewing a stripped down version of our content. View the full version with proper formatting.

BReeves

Kinda the same question as CapeCodGunny posted but different.

I am working with the Canon SDK and trying to display a live view image. The camera and SDK sends the live view image out as a JPEG stream. I need to decompress and display it as it comes in. All I have to work with is a pointer to the beginning of the memory stream and a size variable. I'm not exactly sure what the size variable is telling me, may contain the size of each frame.

I know I will need a VLDSImageDisplay control but not sure what I need to put in front of it to grab the stream and decompress the JPEG video so I can display it.

I'm researching exactly what encoding is used for the JPEG stream but am thinking whatever control we end up using will be able to handle whatever it is. I will also look at the Buffer control suggested in the other thread but suspect it won't decode the video.

Any ideas and Thanks...

EDIT: May have a bigger issue with trying to use Video Lab for this. I'm using an older version (4.5 ) with Builder 5 and looks like I don't have a IVLImageBuffer component. Can any of the controls in version 4.5 accept input from a memory stream?

Dave

I bet it has the TVLCVideoBuffer, perhaps if you put a VLGenericFilter or VLGenericGen in front of an ImageDisplay and feed the VideoBuffer.

Regards,
Dave

BReeves

Looked again and none of the component names say "Buffer". When I search for "buffer" in the help file it brings up several topics on various components but no "....Buffer".

I do have BuilderXE7 and the latest version of Video Lab but haven't used it yet. Too lazy to learn the new user interface, so far Builder 5 has done everything I need and I know how to use it.

Nothing is ever easy is it....

A little more looking and found TVLFrameQueue which is the closest to a Buffer I could find. It only shows an input pin property which I don't know how to point to an incoming video stream. Again the question is... Can any of the controls in version 4.5 accept input from a memory stream? If not, guess I'm stuck between a rock and a hard place...

Thanks for trying to help...

Dave

You have a VLGenericFilter right? Place one on a form and doubleclick it, you should get something like:

void __fastcall TForm1::VLGenericFilter1ProcessData(TObject *Sender, TVLCVideoBuffer InBuffer,
TVLCVideoBuffer &OutBuffer, bool &SendOutputData)

there's the TVLCVideoBuffer, or do you get something different?

Although expected very soon the labs aren't ready for XE7 yet so at this time it's not really an option.

I went from builder 3,4,6 to 2009 (up to XE6) which has the new interface and it didn't take long to get used to. You could keep builder5 on your system and have XE7 next to it so you can slowly get used to it.

BReeves

Sorry, tried to log into the forum from my laptop last night and it just put me in a loop saying I was logged in but then telling me I wasn't when I went back to the forum, weird...

Looks like we may be getting someplace.. I do have the Filter and see exactly what you posted for the ProcessData event. However this leaves several questions for an idiot like me, as I am missing the knowledge of what to do with it.

When does this event fire and how would one point the InBuffer to the buffer the SDK creates.

OH! Not sure what I was thinking, I have XE5 not XE7. I played with it a bit yesterday but the Windows 7 computer I have it on was frustrating me with Microsoft's idea of what it should do verses what I wanted to do. One of these days I'll hack around and get it working like I need but for right now I'll stick with Builder 5 and XP.

Dave

If User Account Control (UAC) is bugging you on windows 7 you can turn that off, easy google.

In your case you want to decompress the JPEG-stream, how where or when you do this is up to you. That ought to produce frames, probably in some buffer, then you read that framebuffer into a TVCLVideoBuffer and you make the VLGeneric-Gen/Filter send it to an ImageDisplay.

A VLGenericGen is probably the easiest, in the OnGenerate event you'd get something like:

------------------------
Read+decompress stream
Frame ready? No - return (do nothing)
Yes
|
TVLCVideoBuffer myBuffer(320,240,vfRGB24); // your frame width, height and videoformat
unsigned char *ptr=myBuffer.Write();
CopyMemory(ptr,(void *)JPegFrame,sizeof(JPegFrame)); // might need some different casting
OutBuffer=myBuffer;

Hope that gets you somewhere. Perhaps if you read the JPegFrame directly into myBuffer, if possible, it could even save some time.

Regards,
Dave

BReeves

Thanks, been involved trying other options and so far no joy.. I'll play with this over the next week or so and see if I can come up with anything.

Just to wrap this up, I ended up not using Video Lab at all. For anyone else that may be looking for Live View with the Cannon ESDK with C++ Builder here is the code I ended up with. This is only the function that gets and displays the image, most everything else needed is outlined in the SDK docs. Have to thank Remy Lebeau for his help on the Builder Developers Journal form heading me in the proper direction.

//---------------------------------------------------------------------------
void TCameraCtrl::DownloadLiveView(void)
{
EdsError err = EDS_ERR_OK;
EdsEvfImageRef image = NULL;
EdsStreamRef stream = NULL;
unsigned char *data = NULL;
unsigned long size = 0;
int Trys;

err = EdsCreateMemoryStream(0, &stream);
while(IsLiveViewOn) {
Application->ProcessMessages();
err = EdsCreateEvfImageRef(stream, &image);
if(err == EDS_ERR_OK){
// Download the liveview data
for(Trys = 10; Trys > 0; Trys--){
err = EdsDownloadEvfImage (EosCamera, image);
if(err == EDS_ERR_OBJECT_NOTREADY)
Sleep(250);
else
break;
}
}
err = EdsGetPointer(stream, (EdsVoid**)&data);
err = EdsGetLength(stream, &size);
if(err == EDS_ERR_OK){
if(image != NULL)
EdsRelease(image);
TMemoryStream* ImageStream = new TMemoryStream;
TJPEGImage *jpg = new TJPEGImage();
ImageStream->WriteBuffer(data, size);
ImageStream->Position = 0;
jpg->LoadFromStream(ImageStream);
Image1->Picture->Assign(jpg);
delete ImageStream;
delete jpg;
}
}
if (stream != NULL) {
EdsRelease(stream);
stream = NULL;
}
if (image != NULL) {
EdsRelease(image);
image = NULL;
}
data = NULL;
EndLiveView();
}
//---------------------------------------------------------------------------
Reference URL's