sharpdx / SharpDX

SharpDX GitHub Repository
http://sharpdx.org
MIT License
1.7k stars 639 forks source link

SinkWriter.SetInputMediaType throws SharpDXException #809

Closed DasLouis closed 8 years ago

DasLouis commented 8 years ago

Greetings to all and sundry!

I may well get told off for this, buuut...

I'm trying to port this: https://code.msdn.microsoft.com/windowsapps/How-to-encode-several-to-a-053953d1#content into C#, specifically the PictureWriter class, for use in a .NET 4.6 application.

The problem I have occurs when I try to add a MediaType to the SinkWriter I have created - up until then, everything seemed fine, but this one line of code throws a SharpDXException. Perhaps I'm doing something daft, but I have tried to stay as faithful to the original code as possible. My code looks thusly:

public PictureWriter(Stream outputStream, uint width, uint height)
{
    bufferLength = (int)(width * height * 4);

    ByteStream bs = new ByteStream(outputStream);

    // Which of these startup functions do I need?
    MediaManager.Startup();
    MediaFactory.Startup(MediaFactory.Version, 0);

    // Create the Sink Writer
    MediaAttributes attributes = new MediaAttributes(10);

    // Required???
    attributes.Set(SinkWriterAttributeKeys.ReadwriteEnableHardwareTransforms, 1); 

    sinkWriter = MediaFactory.CreateSinkWriterFromURL(@".mp4", bs.NativePointer, attributes);    

    // Set up the output media type
    MediaType typeOut = new MediaType();
//  MediaFactory.CreateMediaType(typeOut);
    typeOut.Set(MediaTypeAttributeKeys.MajorType, MediaTypeGuids.Video);
    typeOut.Set(MediaTypeAttributeKeys.Subtype, VideoFormatGuids.H264);
    typeOut.Set(MediaTypeAttributeKeys.AvgBitrate, 3000000);
    typeOut.Set(MediaTypeAttributeKeys.InterlaceMode, (int)VideoInterlaceMode.Progressive);
    typeOut.Set(MediaTypeAttributeKeys.FrameSize, width);   // How do I set the height???
    typeOut.Set(MediaTypeAttributeKeys.FrameRate, 10);
    typeOut.Set(MediaTypeAttributeKeys.PixelAspectRatio, 1);

    sinkWriter.AddStream(typeOut, out streamIndex);

    // Set up the input media type
    MediaType typeIn  = new MediaType();
//  MediaFactory.CreateMediaType(typeIn);
    typeIn.Set(MediaTypeAttributeKeys.MajorType, MediaTypeGuids.Video); 
    typeIn.Set(MediaTypeAttributeKeys.Subtype, VideoFormatGuids.Rgb32);
    typeIn.Set(MediaTypeAttributeKeys.InterlaceMode, (int)VideoInterlaceMode.Progressive);
    typeIn.Set(MediaTypeAttributeKeys.FrameSize, width); // How do I set the height???
    typeIn.Set(MediaTypeAttributeKeys.FrameRate, 10);

    sinkWriter.SetInputMediaType(streamIndex, typeIn, null);    // Additional information: HRESULT: [0xC00D36B4], Module: [Unknown], ApiCode: [Unknown/Unknown], Message: Unknown

    sinkWriter.BeginWriting();
}

which is my attempt to port the PictureWriter from the project linked above. The calling function looks like this:

private void OnExportVideoCommand()
{
    // Get the save location from the dialog
        Stream outputStream = new FileStream(@"C:/Users/Louis/Desktop/outputVid.mp4", FileMode.Create, FileAccess.ReadWrite, FileShare.None, 4096);
        CMGraphics.PictureWriter pw = new CMGraphics.PictureWriter(outputStream, 640, 480);
        pw.Finish();
}

The stream creates successfully - the file is created on the desktop.

Any help would be greatly appreciated!

factormystic commented 8 years ago

I don't know precisely what is causing the exception, but I can answer another question from your code, which is how to set some of those attributes. FrameSize, FrameRate, and PixelAspectRatio are longs, with 32 bits for each param (latter two are expressed as ratios, so the easiest thing is to use 1 for the right value, and do 10 << 32 for the left side, for example).