Click here to Skip to main content
15,949,686 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hi,
Please give guidance to , How to improve video quality using WMEncoder. In our project i want to use customs profile that is to be file .prx extension , according .prx file the video out put will change. I am going to convert image to video file... lastly i have download project from this site, it is good but the video output is too pooooor quality please see below the code which i am using.

----------------Form.cs-------------------------
C#
Cursor.Current = Cursors.WaitCursor;

        // Profile id for "Windows Media Video 8 for Dial-up Modem (No audio, 56 Kbps)"
        Guid g = new Guid("0F10D9D3-3B04-4fb0-A3D3-88D4AC854ACC");

        CwmvFile f = new CwmvFile(textBox1.Text, ref g, (int)numericUpDown1.Value);
        Bitmap b;
        int x = 1;
        bool bDone = false;

        do
        {
           string s = string.Format(@"C:\chetan\screen" + x +".jpg", textBox2.Text, x);

            if (File.Exists(s) == true)
            {
                b = new Bitmap(s);
                f.AppendNewFrame(b);
                b.Dispose();
                x++;
            }
            else
            {
                bDone = true;
            }
        } while (!bDone);

        f.Close();

        Cursor.Current = Cursors.Default;

        MessageBox.Show(string.Format("Added {0} frames", x-1), "Done");


----------------------------------Cwmvfile.cs-----------------------------------
C#
public class CwmvFile
   {
       #region Member variables

       // Interface used to write to asf file
       private IWMWriter           m_pWMWriter;

       // Used to read and set the video properties
       private IWMInputMediaProps  m_pInputProps;

       private int m_iFrameRate; // # of Frames Per Second for video output
       private int m_dwVideoInput; // Which channel of the asf writer to write to
       private int m_dwCurrentVideoSample; // Count of current frame
       private long m_msVideoTime; // Timestamp of current frame
       private bool m_Init; // Has init been run yet?

       #endregion

       #region APIs
       [DllImport("Kernel32.dll", EntryPoint="RtlMoveMemory")]
       private static extern void CopyMemory(IntPtr Destination, IntPtr Source, [MarshalAs(UnmanagedType.U4)] int Length);
       #endregion

       /// <summary>
       ///  Create filename from specified profile using specified framerate
       /// </summary>
       /// <param name="lpszFileName">File name to create</param>
       /// <param name="guidProfileID">WM Profile to use for compression</param>
       /// <param name="iFrameRate">Frames Per Second</param>
       public CwmvFile(string lpszFileName, ref Guid guidProfileID, int iFrameRate)
       {
           Guid    guidInputType;
           int    dwInputCount;



           IWMProfileManager pWMProfileManager = null;
           IWMProfile pWMProfile = null;

           // Initialize all member variables
           m_iFrameRate = iFrameRate;
           m_dwVideoInput = -1;
           m_dwCurrentVideoSample = 0;
           m_msVideoTime = 0;

           m_pWMWriter = null;
           m_pInputProps = null;
           m_Init = false;

           try
           {
               // Open the profile manager
               WMUtils.WMCreateProfileManager(out pWMProfileManager);

               // Convert pWMProfileManager to a IWMProfileManager2
               IWMProfileManager2 pProfileManager2 = (IWMProfileManager2)pWMProfileManager;

               // Specify the version number of the profiles to use
               pProfileManager2.SetSystemProfileVersion(WMVersion.V8_0);

               // Load the profile specified by the caller
               pProfileManager2.LoadProfileByID(guidProfileID, out pWMProfile);

               // Create a writer.  This is the interface we actually write with
               WMUtils.WMCreateWriter(IntPtr.Zero, out m_pWMWriter);

               // Set the profile we got into the writer.  This controls compression, video
               // size, # of video channels, # of audio channels, etc
               m_pWMWriter.SetProfile(pWMProfile);


               // Find out how many inputs are in the current profile
               m_pWMWriter.GetInputCount(out dwInputCount);

               // Assume we won't find any video pins
               m_dwVideoInput = -1;

               // Find the first video input on the writer
               for (int i=0; i < dwInputCount; i++)
               {
                   // Get the properties of channel #i
                   m_pWMWriter.GetInputProps(i, out m_pInputProps);

                   // Read the type of the channel
                   m_pInputProps.GetType(out guidInputType);

                   // If it is video, we are done
                   if (guidInputType == MediaType.Video)
                   {
                       m_dwVideoInput = i;
                       break;
                   }
               }

               // Didn't find a video channel
               if (m_dwVideoInput == -1)
               {
                   throw new Exception("Profile does not accept video input");
               }

               // Specify the file name for the output
               m_pWMWriter.SetOutputFilename(lpszFileName);
           }
           catch
           {
               Close();
               throw;
           }
           finally
           {
               // Release the locals
               if (pWMProfile != null)
               {
                   Marshal.ReleaseComObject(pWMProfile);
                   pWMProfile = null;
               }
               if (pWMProfileManager != null)
               {
                   Marshal.ReleaseComObject(pWMProfileManager);
                   pWMProfileManager = null;
               }
           }
       }


       /// <summary>
       /// Destructor
       /// </summary>
       ~CwmvFile()
       {
           Close();
       }


       /// <summary>
       /// Close the output and release the variables
       /// </summary>
       public void Close()
       {
           if (m_Init)   //We are currently writing
           {
               if (m_pWMWriter != null)
               {
                   // Close the file
                   try
                   {
                       m_pWMWriter.EndWriting();
                   }
                   catch { }
               }
               m_Init = false;
           }

           if (m_pInputProps != null)
           {
               Marshal.ReleaseComObject(m_pInputProps);
               m_pInputProps = null;
           }
           if (m_pWMWriter != null)
           {
               Marshal.ReleaseComObject(m_pWMWriter);
               m_pWMWriter = null;
           }
       }


       /// <summary>
       /// Add a frame to the output file
       /// </summary>
       /// <param name="hBitmap">Frame to add</param>
       public void AppendNewFrame(Bitmap hBitmap)
       {
           int             hr = 0;
           INSSBuffer      pSample = null;
           Rectangle       r = new Rectangle(0, 0, hBitmap.Width, hBitmap.Height);
           BitmapData      bmd;

           if (!m_Init)
           {
               // Only call this for the first frame
               Initialize(hBitmap);
           }

           // Lock the bitmap, which gets us a pointer to the raw bitmap data
           bmd = hBitmap.LockBits(r, ImageLockMode.ReadOnly, hBitmap.PixelFormat);

           try
           {
               // Compute size of bitmap in bytes.  Strides may be negative.
               int iSize = Math.Abs(bmd.Stride * bmd.Height);
               IntPtr ip;

               // Get a sample interface
               m_pWMWriter.AllocateSample(iSize, out pSample);

               // Get the buffer from the sample interface.  This is
               // where we copy the bitmap data to
               pSample.GetBuffer(out ip);

               // Copy the bitmap data into the sample buffer
               LoadSample(bmd, ip, iSize);

               // Write the sample to the output - Sometimes, for reasons I can't explain,
               // writing a sample fails.  However, writing the same sample again
               // works.  Go figure.
               int iRetry = 0;
               do
               {
                   try
                   {
                       m_pWMWriter.WriteSample(m_dwVideoInput, 10000 * m_msVideoTime, SampleFlag.CleanPoint, pSample);
                       break;
                   }
                   catch (COMException e)
                   {
                       if ((iRetry++ < 3) && (e.ErrorCode != NSResults.E_INVALID_DATA))
                       {
                           continue;
                       }
                       else
                       {
                           throw;
                       }
                   }
               } while (true);

               Marshal.ThrowExceptionForHR(hr);

               // update the time based on the framerate
               m_msVideoTime = (++m_dwCurrentVideoSample*1000)/m_iFrameRate;
           }
           finally
           {
               // Release the locals
               if (pSample != null)
               {
                   Marshal.ReleaseComObject(pSample);
                   pSample = null;
               }

               hBitmap.UnlockBits(bmd);
           }
       }


       /// <summary>
       /// Read the properties of the first bitmap to finish initializing the writer.
       /// </summary>
       /// <param name="hBitmap">First bitmap</param>
       private void Initialize(Bitmap hBitmap)
       {
           AMMediaType mt = new AMMediaType();
           VideoInfoHeader videoInfo = new VideoInfoHeader();

           // Create the VideoInfoHeader using info from the bitmap
           videoInfo.BmiHeader.Size = Marshal.SizeOf(typeof(BitmapInfoHeader));
           videoInfo.BmiHeader.Width = hBitmap.Width;
           videoInfo.BmiHeader.Height = hBitmap.Height;
           videoInfo.BmiHeader.Planes = 1;

           // compression thru clrimportant don't seem to be used. Init them anyway
          /* videoInfo.BmiHeader.Compression = 0;
           videoInfo.BmiHeader.ImageSize = 0;
           videoInfo.BmiHeader.XPelsPerMeter = 0;
           videoInfo.BmiHeader.YPelsPerMeter = 0;
           videoInfo.BmiHeader.ClrUsed = 0;
           videoInfo.BmiHeader.ClrImportant =0;*/

          /*switch(hBitmap.PixelFormat)
           {
               case PixelFormat.Format32bppRgb:
                   mt.subType = MediaSubType.RGB32;
                   videoInfo.BmiHeader.BitCount = 32;
                   break;
               case PixelFormat.Format24bppRgb:
                   mt.subType = MediaSubType.RGB24;
                   videoInfo.BmiHeader.BitCount = 24;
                   break;
               case PixelFormat.Format16bppRgb555:
                   mt.subType = MediaSubType.RGB555;
                   videoInfo.BmiHeader.BitCount = 16;
                   break;
               case PixelFormat.Format48bppRgb:
                   mt.subType=MediaSubType.RGB565;
                   videoInfo.BmiHeader.BitCount = 48;
                   break;
               case PixelFormat.Format64bppPArgb:
                   mt.subType = MediaSubType.RGB565;
                   videoInfo.BmiHeader.BitCount = 64;
                   break;
               default:
                 throw new Exception("Unrecognized Pixelformat in bitmap");
           }*/
           mt.subType = MediaSubType.RGB32;
           videoInfo.BmiHeader.BitCount = 32;

           videoInfo.SrcRect = new Rectangle(0, 0, hBitmap.Width, hBitmap.Height);
           videoInfo.TargetRect = videoInfo.SrcRect;
           videoInfo.BmiHeader.ImageSize = hBitmap.Width * hBitmap.Height * (videoInfo.BmiHeader.BitCount / 8);
           videoInfo.BitRate = videoInfo.BmiHeader.ImageSize * m_iFrameRate;
           videoInfo.BitErrorRate = 0;
           videoInfo.AvgTimePerFrame = 10000 * 1000 / m_iFrameRate;

           mt.majorType = MediaType.Video;
           mt.fixedSizeSamples = true;
           mt.temporalCompression = false;
           mt.sampleSize = videoInfo.BmiHeader.ImageSize;
           mt.formatType = FormatType.VideoInfo;
           mt.unkPtr = IntPtr.Zero;
           mt.formatSize = Marshal.SizeOf(typeof(VideoInfoHeader));

           // Lock the videoInfo structure, and put the pointer
           // into the mediatype structure
           GCHandle gHan = GCHandle.Alloc(videoInfo, GCHandleType.Pinned);

           try
           {
               // Set the inputprops using the structures
               mt.formatPtr = gHan.AddrOfPinnedObject();

               m_pInputProps.SetMediaType(mt);
           }
           finally
           {
               gHan.Free();
               mt.formatPtr = IntPtr.Zero;
           }

           // Now take the inputprops, and set them on the file writer
           m_pWMWriter.SetInputProps(m_dwVideoInput, m_pInputProps);

           // Done with config, prepare to write
           m_pWMWriter.BeginWriting();

           m_Init = true;
       }


       /// <summary>
       /// Copy the bitmap data to the sample buffer
       /// </summary>
       /// <param name="bmd">Source bytes</param>
       /// <param name="ip">Point to copy the data to</param>
       /// <param name="iSize">How many bytes to copy</param>
       private void LoadSample(BitmapData bmd, IntPtr ip, int iSize)
       {
           // If the bitmap is rightside up
           if (bmd.Stride < 0)
           {
               CopyMemory(ip, bmd.Scan0, iSize);
           }
           else
           {
               // Copy it line by line from bottom to top
               IntPtr ip2 = (IntPtr)(ip.ToInt32() + iSize - bmd.Stride);
               for (int x=0; x < bmd.Height; x++)
               {
                   CopyMemory(ip2, (IntPtr)(bmd.Scan0.ToInt32() + (bmd.Stride * x)), bmd.Stride);
                   ip2 = (IntPtr)(ip2.ToInt32() - bmd.Stride);
               }
           }
       }
   }

Q. 1)How to Improve video Quality using WMEncoder SDK
Posted
Updated 3-Mar-13 20:42pm
v3

1 solution

Ask your question in the forum at the bottom of the article you downloaded the code from.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900