Discussion:
Creating a video from still images
(too old to reply)
msnews.microsoft.com
2009-10-16 14:44:23 UTC
Permalink
Does anyone have sample c# code showing how to use the Windows Media Video 9 Image v2 codec to create a video from still images? (Like Photostory).

I need to be able to do what photostory does, but do it progrmatically. It looks like this is the codec that Photostory uses, but I'm not really sure where to start and my web searches for inofrmation on the topic have not been very successful.

I found this page on MSDN:

http://msdn.microsoft.com/en-us/library/dd743972(VS.85).aspx

This looks like what I need but I'm not sure how to use it.

-Eric
Alessandro Angeli
2009-10-16 19:22:24 UTC
Permalink
From: "msnews.microsoft.com"
Post by msnews.microsoft.com
Does anyone have sample c# code showing how to use the
Windows Media Video 9 Image v2 codec to create a video
from still images? (Like Photostory).
A codec is pretty much useless by itself: it compresses the
pictures but it doesn't create a file to store the
compressed data.

To create WMV files containing images compressed with the
WMV9 Image v2 codec, you need to WMWriter object in the
WindowsMediaFormat, which creates WMV files and (optionally)
compresses the data according to a WMProfile (in which you
can specify the codecs to use).

The WMWriter only has a C/C++ COM API, but the open source
WindowsMedia.NET library provides a C# wrapper for it.

The WMASFWriter filter wraps the WMWriter in DirectShow and
the ASF components do the same in MediaFoundation. Again,
they are C/C++ COM APIs, but DirectShow.NET and
MediaFoundation.NET come to the rescue of the lost C#
programmer. However, the DS and MF APIs are harder to use
than the direct WMF API. Actually, MF comes with API 2
layers: a harder one similar to DS and a simpler one similar
to WMF. Be warned that MF only exists in Vista or newer
versions of Windows.

There is also a higher level component you can use: the free
WindowsMediaEncoder9. WME9's API is automation-aware (that
is, ActiveX) and it provides its own C# wrapper (documented
in the WME9 SDK). Using WME9 to compress image sequences
however is a little bit convoluted (search for sample code
by Neil Smith) and WME9 only supports file sources, not
memory buffers.
--
// Alessandro Angeli
// MVP :: DirectShow / MediaFoundation
// mvpnews at riseoftheants dot com
// http://www.riseoftheants.com/mmx/faq.htm
Eric Paul
2009-10-16 20:50:46 UTC
Permalink
Thanks for your prompt reply.

I did see the directshow and Windoiws Media Foundation stuff--it seemed like
that was moving in the right direction.
I couldn't find any relavent articles by Neil smith on how to use the
encoder.
Is there an example that's close to what I'm looking for on the WMF site?

Thanks,

Eric
Alessandro Angeli
2009-10-16 22:15:03 UTC
Permalink
From: "Eric Paul"
Post by Eric Paul
I did see the directshow and Windoiws Media Foundation
stuff--it seemed like that was moving in the right
direction. I couldn't find any relavent articles by Neil
smith on
how to use the encoder.
Is there an example that's close to what I'm looking for
on the WMF site?
If you plan on using WMF, DS or MF, then any sample that
encodes video is what you want to do (a video is just a
sequence of pictures). You will most likely need to
configure a different codec in the encoding profile.

There is no sample to encode sequences of pictures with WME9
but Neil Smith posted one here a long time ago (try
groups.google.com to search the archive).
--
// Alessandro Angeli
// MVP :: DirectShow / MediaFoundation
// mvpnews at riseoftheants dot com
// http://www.riseoftheants.com/mmx/faq.htm
Eric Paul
2009-10-19 00:38:08 UTC
Permalink
Thanks for the advice.
I will search for neils article and start by going through the provided
samples.
If I come up with the answer I'll post my code back here.

Thanks again for your help.
Neil Smith [MVP Digital Media]
2009-10-19 16:21:20 UTC
Permalink
On Sun, 18 Oct 2009 20:38:08 -0400, "Eric Paul"
Post by Eric Paul
Thanks for the advice.
I will search for neils article and start by going through the provided
samples.
If I come up with the answer I'll post my code back here.
Thanks again for your help.
Hi, I'm still here occasionally ;-)
This is the thread Alessandro is referring to :

http://www.tech-archive.net/Archive/Media/microsoft.public.windowsmedia.encoder/2007-11/msg00019.html

I've got a copy of that ZIP file here, I don't think any of the web
based newsgroup lists archive the file.

If you can reply and provide a munged email address (to avoid
newsgroup spam), I can send over the code sample

It's javascript which operates a WME ActiveX object in the browser, so
you'd need IE6 or later (haven't tested in more recent versions) but
could be adapted to C# if you use the right references.

The key is just to set the encoder to broadcast (I think it was ChrisP
suggested that) which means the image is encoded in real-time for the
specified duration, rather than as a single frame

Cheers - Neil
------------------------------------------------
Digital Media MVP : 2004-2009
http://mvp.support.microsoft.com/mvpfaqs
Eric Paul
2009-10-19 17:23:42 UTC
Permalink
The email address listed for me is a good one.
Unless its a huge Zip file that would be fine.

Thanks for chiming in--you probably saved me hours of work :)
Neil Smith [MVP Digital Media]
2009-10-25 15:43:35 UTC
Permalink
On Mon, 19 Oct 2009 13:23:42 -0400, "Eric Paul"
Post by Eric Paul
The email address listed for me is a good one.
Unless its a huge Zip file that would be fine.
Thanks for chiming in--you probably saved me hours of work :)
Sent to email in case you still want to inspect the code

HTH
Cheers - Neil
------------------------------------------------
Digital Media MVP : 2004-2009
http://mvp.support.microsoft.com/mvpfaqs
Thinqer
2009-12-28 01:51:01 UTC
Permalink
Hi Neil,

I was wondering if you could send me a copy of the file/code too as I've not
been able to download it from the newsgroup anywhere. The email address I'm
registered with on here should work just fine.

Is there no easy way to embed a jpg/bmp in a WMV for, say, 5 seconds?

Many thanks,

Thinqer
Neil Smith [MVP Digital Media]
2009-12-28 12:12:13 UTC
Permalink
On Sun, 27 Dec 2009 17:51:01 -0800, Thinqer
Post by Thinqer
Hi Neil,
I was wondering if you could send me a copy of the file/code too as I've not
been able to download it from the newsgroup anywhere. The email address I'm
registered with on here should work just fine.
Thinger, the email address is showing as "@discussions.microsoft.com"
- is that a real email address ? I thought it was just a made-up
identifier for posting and not something you could receive file
attachments at.

If possible, post a real but obviously-munged email address.
Post by Thinqer
Is there no easy way to embed a jpg/bmp in a WMV for, say, 5 seconds?
Sure - MovieMaker can put an image on a timeline, then set its
duration for 5 seconds ? Isn't that all you need here ?

Cheers - Neil
------------------------------------------------
Digital Media MVP : 2004-2009
http://mvp.support.microsoft.com/mvpfaqs

Eric Paul
2009-10-20 04:02:50 UTC
Permalink
OK, Here is what I've come up with so far:

string appPath = @"C:\Users\ericp\Documents\Visual Studio
2008\Projects\EncodeStillImageTest\";

try
{
// Create a WMEncoder object.
WMEncoder Encoder = new WMEncoder();
//Encoder.Broadcast.set_PortNumber(WMENC_BROADCAST_PROTOCOL.WMENC_PROTOCOL_PUSH_DISTRIBUTION,80);

// Specify a file object in which to save encoded content.
IWMEncFile2 File = (IWMEncFile2)Encoder.File;
File.FileDuration = (9000 / 10000);
File.LocalFileName = String.Format("{0}OutputFile.wmv",
appPath);

/* ADDING THIS CODE MAKES THE VIDEO BLANK
//Add audio
IWMEncSourceGroup audioGroup =
Encoder.SourceGroupCollection.Add("AUDIO_GROUP");
audioGroup.set_Profile(profile);
IWMEncAudioSource audioSource =
(IWMEncAudioSource)audioGroup.AddSource(WMENC_SOURCE_TYPE.WMENC_AUDIO);
audioSource.SetInput(appPath + "Audio.wav", "", "");
*/

//Add images
string fileName1 = string.Format("{0}Lady01.bmp", appPath);
string fileName2 = string.Format("{0}Lady02.bmp", appPath);

IWMEncSourceGroup2 frameSourceGroup =
(IWMEncSourceGroup2)Encoder.SourceGroupCollection.Add("SG1");
IWMEncVideoSource2 sourceVideo =
(IWMEncVideoSource2)frameSourceGroup.AddSource(WMENC_SOURCE_TYPE.WMENC_VIDEO);

IWMEncSourceGroup2 frameSourceGroup2 =
(IWMEncSourceGroup2)Encoder.SourceGroupCollection.Add("SG2");
IWMEncVideoSource2 sourceVideo2 =
(IWMEncVideoSource2)frameSourceGroup.AddSource(WMENC_SOURCE_TYPE.WMENC_VIDEO);

frameSourceGroup.SetAutoRollover(-1, "SG2");

sourceVideo.SetInput(fileName1, "", "");
sourceVideo2.SetInput(fileName2, "", "");

IWMEncProfileCollection ProColl = Encoder.ProfileCollection;
ProColl.ProfileDirectory = appPath;
ProColl.Refresh();
IWMEncProfile Pro;
for (int i = 0; i < ProColl.Count; i++)
{
Pro = ProColl.Item(i);
if (Pro.Name == "Test")
{
frameSourceGroup.set_Profile(Pro);
frameSourceGroup2.set_Profile(Pro);
break;
}
}

// Fill in the description object members.
IWMEncDisplayInfo Descr = Encoder.DisplayInfo;
Descr.Author = "Author name";
Descr.Copyright = "Copyright information";
Descr.Description = "Text description of encoded content";
Descr.Rating = "Rating information";
Descr.Title = "Title of encoded content";

// Add an attribute to the collection.
IWMEncAttributes Attr = Encoder.Attributes;
Attr.Add("URL", "IP address");

// Start the encoding process.
// Wait until the encoding process stops before exiting the
application.
Encoder.PrepareToEncode(true);
Encoder.Start();
Thread.Sleep(1000);

for (int index = 0; index <
Encoder.SourceGroupCollection.Count; index++)
{
Encoder.SourceGroupCollection.Active =
Encoder.SourceGroupCollection.Item(index);
Console.WriteLine(Encoder.SourceGroupCollection.Item(index).Name);
Thread.Sleep(3000);
}
Encoder.Stop();
Encoder.Flush();
}
catch (Exception error)
{
Console.WriteLine(error.Message);
Thread.Sleep(2000);
}

This code will fail at "frameSourceGroup.set_Profile(Pro);" with an error:
"The profile's media types must match the media types defined for the
session.". As I understand it this is telling me that the profile I created
is wrong. I have tried adjusting it a bunch of different ways but I can't
seem to find a combination that lets it pass. I have tried with audio and
without. I tried the "Image" codec and several others. I can't seem to get
one to work with the code.

I also found this solution which uses a combination of WMF and the Windows
Media SDK:

http://codebetter.com/blogs/brendan.tompkins/archive/2005/06/29/128620.aspx

It works but can only go down to 1 FPS as a way to extend the time the image
is on screen. It's basic approach is to render each frame and use a timer to
hold the image on screen--or something like that. But the underlying method
(from the wmf wrapper) won't accept anything but ulong as FPS--so .25 or
something like that is out.
I wish I could actually talk to someone who deveolped Photostory--just to
hear them say they didn't use the SDK to make it work :)
So I still have to conquer:

What is the correct profile?
How do I control the time the image is on screen?
How do I use Zooms and Pans on the image while its on screen?

If I find the answers I'll post them here.
Thanks,

-E.
Eric Paul
2009-10-21 02:13:08 UTC
Permalink
OK. I think I've found my answers:

http://www.codeproject.com/KB/audio-video/avifilewrapper.aspx

Is a great project. It has a method to add an image to a video stream--this
looks like the only really practical way to do this. If I take the button
click that creates the video from the image (which is only a single frame)
and alter the for statement I can get it to add the same image over and over
frame after frame. Now if Ican change the rectangle on the bit map in each
frame I should be able to pan the bitmap.

Journey onward...
Loading...