Code samples related with the article: C
Sharp Windows Media Format SDK Translation
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR
FITNESS FOR A PARTICULAR PURPOSE.
Response
to message: Re:
Great stuff - Can you help me...
I got it working. Thanks.
All I need now is to be able to convert
the mp3 to asf
Pete
Papapet |
The following code create a 128 Kbps WMA file from your a
MP3 file and if the bit rate of the MP3 file is greater than
128 Kbps then a recompressed 128 Kbps MP3 file is created
at the same time.
using (WmaStream str = new WmaStream("File.mp3",
new WaveFormat(44100, 16, 2))
{
byte[] buffer = new byte[str.SampleSize*2];
IWMProfile profile = null;
Guid WMProfile_V80_128StereoAudio = new Guid("{407B9450-8BDC-4ee5-88B8-6F527BD941F2}");
WM.ProfileManager.LoadProfileByID(ref WMProfile_V80_128StereoAudio, out profile);
AudioWriter[] writers = new AudioWriter[2];
try
{
writers[0] = new WmaWriter(new FileStream("File.wma", FileMode.Create),
str.Format,
profile);
if ( OrigBitRate > 128000 )
{
writers[1] = new Mp3Writer(new FileStream("File-128.mp3", FileMode.Create),
str.Format,
new Yeti.Lame.BE_CONFIG(str.Format, 128));
}
int read;
while ( (read = str.Read(buffer, 0, buffer.Length)) > 0)
{
foreach( AudioWriter writer in writers )
{
if (writer != null)
writer.Write(buffer, 0, read);
}
}
}
catch (Exception e)
{
}
finally
{
foreach( AudioWriter writer in writers )
{
if (writer != null)
{
try
{
writer.Close();
}
catch
{
}
}
}
}
} |
Response
to message: Capture
frame from ASF file and store to disk as .jpg
Hi, great article, and probably
the closest I've come to finding a solution to a problem that
I have: By using Windows Media
Format SDK (or Windows Media Encoder SDK, if it's possible)
and C# I want to simply load an ASF file (.asf/.wmv/.wma....
), grab a frame from a specified time ( hh:mm:ss ) into the
file and save that frame to disk as a .jpg file. How can this
be done - can you help ? Preferably I want the code to be
as simple as possible, a bare bones sample...
I've tried some quick tests with your
code, with no luck, and I'm not good enough with the format
SDK to know how this should be done by extending your wrapper
classes... hmm Any help would greatly be appreciated !
Regards,
Kurt Grønbech
Software Architect |
The following function shows how take a snapshot image from
a video ASF file at specific time position: /// <summary>
///
/// </summary>
/// <param name="AsfVideoFileName"></param>
/// <param name="ImageTime"></param>
/// <param name="JpgFileName"></param>
public static void WMVImageToJpg(string AsfVideoFileName, ulong ImageTime, string JpgFileName)
{
IWMSyncReader Reader;
uint VideoOuput = uint.MaxValue;
uint VideoStream = uint.MaxValue;
uint OutputCount;
WM_MEDIA_TYPE mtype = new WM_MEDIA_TYPE();
WMVIDEOINFOHEADER InfoHeader = new WMVIDEOINFOHEADER();
Reader = WM.CreateSyncReader(WMT_RIGHTS.WMT_RIGHT_NO_DRM);
Reader.Open(AsfVideoFileName);
Reader.GetOutputCount(out OutputCount);
ushort[] StreamNumbers = new ushort[OutputCount];
WMT_STREAM_SELECTION[] StreamSelections = new WMT_STREAM_SELECTION[OutputCount];
for (uint i = 0; i < OutputCount; i++)
{
IWMOutputMediaProps Props = null;
Guid mt;
ushort StreamNumber;
Reader.GetOutputProps(i, out Props);
Reader.GetStreamNumberForOutput(i, out StreamNumber);
StreamNumbers[i] = StreamNumber;
StreamSelections[i] = WMT_STREAM_SELECTION.WMT_OFF;
Props.GetType(out mt);
if ( mt == MediaTypes.WMMEDIATYPE_Video )
{
uint FormatCount;
VideoOuput = i;
StreamSelections[i] = WMT_STREAM_SELECTION.WMT_ON;
Reader.GetOutputFormatCount(i, out FormatCount);
uint BufferSize = (uint)(Marshal.SizeOf(typeof(WM_MEDIA_TYPE)) +
Marshal.SizeOf(typeof(WMVIDEOINFOHEADER)));
IntPtr buffer = Marshal.AllocCoTaskMem((int)BufferSize);
try
{
for (uint j = 0; j < FormatCount; j++)
{
uint Size = 0;
Reader.GetOutputFormat(i, j, out Props);
Props.GetMediaType(IntPtr.Zero, ref Size);
if ( Size > BufferSize )
{
BufferSize = Size;
Marshal.FreeCoTaskMem(buffer);
buffer = Marshal.AllocCoTaskMem((int)BufferSize);
}
Props.GetMediaType(buffer, ref Size);
mtype = (WM_MEDIA_TYPE)Marshal.PtrToStructure(buffer, typeof(WM_MEDIA_TYPE));
if ( mtype.formattype == MediaTypes.WMFORMAT_VideoInfo )
if ( (mtype.subtype == MediaTypes.WMMEDIASUBTYPE_RGB555) ||
(mtype.subtype == MediaTypes.WMMEDIASUBTYPE_RGB24) ||
(mtype.subtype == MediaTypes.WMMEDIASUBTYPE_RGB32) )
{
VideoStream = StreamNumber;
InfoHeader = (WMVIDEOINFOHEADER)Marshal.PtrToStructure(mtype.pbFormat,
typeof(WMVIDEOINFOHEADER));
Reader.SetOutputProps(i, Props);
break;
}
}
}
finally
{
Marshal.FreeCoTaskMem(buffer);
}
}
}
if ( VideoOuput == uint.MaxValue)
{
throw new ArgumentException(string.Format("No video stream found in: {0}",
AsfVideoFileName),
"AsfVideoFileName");
}
if ( VideoStream != uint.MaxValue )
{
INSSBuffer Sample = null;
IntPtr SampleBuff;
ulong SampleTime, Duration;
uint Flags, OutputNum;
ushort StreamNum;
Bitmap bmap;
PixelFormat pixelfmt = PixelFormat.DontCare;
Reader.SetStreamsSelected((ushort)OutputCount, StreamNumbers, StreamSelections);
Reader.SetRange(ImageTime, 0);
Reader.GetNextSample( (ushort)VideoStream,
out Sample,
out SampleTime,
out Duration,
out Flags,
out OutputNum,
out StreamNum );
Sample.GetBuffer(out SampleBuff);
if ( mtype.subtype == MediaTypes.WMMEDIASUBTYPE_RGB555 )
{
pixelfmt = PixelFormat.Format16bppRgb555;
}
else if ( mtype.subtype == MediaTypes.WMMEDIASUBTYPE_RGB24 )
{
pixelfmt = PixelFormat.Format24bppRgb;
}
else if( mtype.subtype == MediaTypes.WMMEDIASUBTYPE_RGB32)
{
pixelfmt = PixelFormat.Format32bppRgb;
}
int stride = InfoHeader.bmiHeader.biWidth *
InfoHeader.bmiHeader.biPlanes *
InfoHeader.bmiHeader.biBitCount / 8;
bmap = new Bitmap(InfoHeader.bmiHeader.biWidth,
InfoHeader.bmiHeader.biHeight,
stride, pixelfmt, SampleBuff);
bmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
bmap.Save(JpgFileName, ImageFormat.Jpeg);
bmap.Dispose();
}
else
throw new ArgumentException(string.Format("No valid uncompressed video format found in: {0}",
AsfVideoFileName),
"AsfVideoFileName");
}
The previous function receives time in 100-nanosecond units.
To use time in HH:MM:SS you can use a function like this one:
/// <summary>
///
/// </summary>
/// <param name="hours"></param>
/// <param name="minutes"></param>
/// <param name="seconds"></param>
/// <param name="mseconds"></param>
/// <returns>100-nanosecond </returns>
public static ulong HMSmS2WMTime(int hours, int minutes, int seconds, int mseconds)
{
return (ulong)((hours*3600000) + (minutes*60000) + (seconds*1000) + mseconds)*10000;
}
WMVImageToJpg("Video.wmv", HMSmS2WMTime(0, 0, 5, 0), "image.jpg");
|
Respose
to message: What
about Video? Greate
samples, but what about video? Do you have any samples on creating
wmv files programmatically using C#? Anyway,
thanks alot |
Demo source project: Avi2Wmv.zip,
updated: June 2, 2004
Article sources: ManWMF.zip,
updated : June 2, 2004
(the demo project needs this version, the version at http://www.thecodeproject.com/ManWMF.asp
is not up to date)
I've developed a project named Avi2Wmv inspired
in the WMF sample UncompAVIToWMV , you can check
that sample to better understand the code that I show here.
Is a reduce version, I didn't include all the features of the
UncompAVIToWMV sample
The main classes in this sample are:
AVIFileReader : Allows to read Audio and Video
streams and formats from an AVI file using the Win32 AVIFile
functions. This class is use by AviToASF class.
You don't need to use it directly but checking its implementation
could help in a better understanding of the rest of the code.
AviToAsf : is the AVI to ASF(WMV) converter.
It's constructor receives as parameter the AVI file name,
the ASF file name (result), the Windows Media Profile describing
the desired output format and an optional array of WM_Attr
structures defining metadata information of output file. NOTE:
THIS CLASS ONLY ACCEPTS UNCOMPRESSED AVI STREAM.
The following code shows how to use AviToAsf :
try { IWMProfile Profile; WM.ProfileManager.LoadSystemProfile(0, out Profile); using(AviToAsf converter = new AviToAsf("somefile.avi", "somefile.wmv", Profile, null) ) { converter.Progress += new ProgressEventHandler(OnProgress); / converter.Start(); } } catch(System.Runtime.InteropServices.COMException cex) { MessageBox.Show(WM.ErrorDescription(cex.ErrorCode), "Error"); } catch(Exception ex) { MessageBox.Show(string.Format("Error message: {0}", ex.Message), "Error"); }
You can find a similar code in the demo project. The UI is
not the best of the demo, here the steps to follow: select
the AVI file, optionally select different output ASF file,
select the WM profile to use and finally click Convert. |
Response to message: Re:
Implementing fast edit with IWMSyncReader
....
Obviously, reading decompressed samples all the way to the
end works fine, but it is relatively slow. My aim is to reduce
time required to process the file, that is why switching from
decompressed to compressed samples.
I do use WMFSDK sample methods for
copying input properties and stream attributes. I also copy
sample time and flags. It all works fine till i start feeding
decompressed and compressed samples to IWMWriter.
It seems to me than IWMWriter has
problem switching from decompressed to compressed samples
and produces files that are not valid: video sample order
is not correct somewhere around switch point.
When I try to produce two files: one
from decompressed samples and one from compressed and glue
them together using wmvappend from SDK it also does not work
correctly: video in second piece gets distorted.
|
I have written the following function and it works for me. I
don’t use uncompressed samples at all and if you don’t
need to edit the streams but just copy I think that the best
idea would be to use only compressed samples. There are some
issues that commented in the code.
/// <summary>
///
///
///
///
///
///
///
///
/// /// </summary>
/// <param name="InputASFFile"></param>
/// <param name="OutputASFFile"></param>
/// <param name="StartTime"></param>
/// <param name="Duration"></param>
public static void CopyWMV(string InputASFFile, string OutputASFFile, ulong StartTime, long Duration)
{
IWMSyncReader Reader;
IWMWriter Writer;
IWMWriterAdvanced WriterAdvanced;
IWMProfile Profile;
uint StreamCount;
uint InputCount;
ushort[] StreamNumbers;
WMT_STREAM_SELECTION[] StreamSelections;
Reader = WM.CreateSyncReader(WMT_RIGHTS.WMT_RIGHT_NO_DRM);
Writer = WM.CreateWriter();
Reader.Open(InputASFFile);
Profile = (IWMProfile)Reader;
Profile.GetStreamCount(out StreamCount);
StreamNumbers = new ushort[StreamCount];
StreamSelections = new WMT_STREAM_SELECTION[StreamCount];
for (uint i = 0; i < StreamCount; i++)
{
IWMStreamConfig StreamConfig;
Profile.GetStream(i, out StreamConfig);
StreamConfig.GetStreamNumber(out StreamNumbers[i]);
StreamSelections[i] = WMT_STREAM_SELECTION.WMT_ON;
Reader.SetReadStreamSamples(StreamNumbers[i], true);
}
Reader.SetStreamsSelected((ushort)StreamCount, StreamNumbers, StreamSelections);
Writer.SetProfile(Profile);
Writer.GetInputCount(out InputCount);
for (uint i = 0; i < InputCount; i++)
{
Writer.SetInputProps(i, null);
}
Writer.SetOutputFilename(OutputASFFile);
WriterAdvanced = (IWMWriterAdvanced)Writer;
Writer.BeginWriting();
Reader.SetRange(StartTime, Duration);
for (uint StreamsRead = 0; StreamsRead < StreamCount; )
{
INSSBuffer Sample = null;
ulong SampleTime;
ulong SampleDuration;
uint Flags;
uint OutputNumber;
ushort StreamNumber;
try
{
StreamNumber = 0;
Reader.GetNextSample(0, out Sample, out SampleTime, out SampleDuration, out Flags,
out OutputNumber, out StreamNumber);
WriterAdvanced.WriteStreamSample(StreamNumber, SampleTime, 0, SampleDuration, Flags, Sample);
}
catch (COMException e)
{
if (e.ErrorCode == WM.NS_E_NO_MORE_SAMPLES)
{
StreamsRead++;
}
else throw;
}
}
Writer.EndWriting();
Reader.Close();
}
The following code use the previous function and the function
HMSmS2WMTime to copy the last part
of a video file to another starting at 5th minute.
ulong StartTime = HMSmS2WMTime(0, 5, 0, 0);
long Duration = 0;
CopyWMV("SomeFile.wmv", "Result.wmv", StartTime, Duration);
|
|
|