Set H264 Encoder Properties Directshow

Set H264 Encoder Properties Directshow

Can anybody help me with a bit of code? I'm trying to set the h264 encoding properties in managed directshow. I've come up with this

IKsPropertySet setProperty = pIntelMediaSDKH264Encoder as IKsPropertySet;

and thats as far as I got.

How can I set the property values that graphedit exposes in c#?

Note: C++ sample is ok as well, prefer C# but converting it is possible.

Thanks, cheers.

~Marty
17 post / 0 nuovi
Ultimo contenuto
Per informazioni complete sulle ottimizzazioni del compilatore, consultare l'Avviso sull'ottimizzazione

Hi Martin,

The MediaSDK and its samples are developed and validated using C++. We have little or no experience using managed DirectShow, or using C# with our filters. The idea does sound compelling. If you get it working please share with the rest of us on the forum.

The filters implement their properties through the IConfigureVideoEncoder interface GetParms(), SetParams(). How these map to your environment is unclear from this side.

Does anyone out there reading this have any experience with this? Please speak up and help Martin out.

Thanks!

-Eric

Actually I found that the filter opens up access to the ISpecifyPropertyPages which I can use to query the property pages, select the page, and the modify the property. Completely doable with managed C# code. Cheers.

~Marty

Hi Martin,
you can access this interfaceby creating it's analong in managed code. Then you need todeclare your interface with attribute[ComImport], and use casting from previously created Com object(Encoder Filter in your case).

Here is an simple example. Also please set target platform in c# project settings to x86 if you are using 32 bits filters.

Allegati: 

AllegatoDimensione
Download Program.cs8.06 KB

Ah,I should have known to ask Eugene! Thanks Eugene.

Thanks Eugene! I was able to pull up the property page with ISpecifyProperty however it wasn't ideal. This is perfect, thank you!!

~Marty

Hi Eugene,

One last thing I'm hoping you can help me with. I'm not sure if I have the right GUID for IConfigureVideoEncoder as I get this error when trying to cast the encodefilter to the interface:

+ $exception {"Unable to cast COM object of type 'EncodeFilter' to interface type 'IConfigureVideoEncoder'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{6BABAF70-864B-486B-B471-CC4E9AFF931B}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE))."} System.Exception {System.InvalidCastException}

Any insight?

Cheers.

~Marty

Cracked open the manual and found the right guid -

[Guid("4CBE79AB-EEDA-4AB6-B8F2-80286BEDAC4A"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IConfigureVideoEncoder
{
void SetParams(ref Params param);
void GetParams(ref Params param);
void GetRunTimeStatistics(ref Statistics param);
};

Works perfect.

Thanks again for your help.

~Marty

You are right, I used newer guid,weswitched to this one recently. We will either mention this in documentationo roll back changes, to maintain backward compatibility, so please check that again when new Mediasdk package will be available.

Hi Eugene,

One last issue, I'm not sure how to convert a line of c++ to c# as I'm sure why this is why I'm erroring. I forgot to mention that I'm working with the H264 Encoder but noticed in the documentation that it inherits from the video encoder anyways. I get a com exception when setting the parameters, this is what it currently looks like without the video encoder structures:

[Guid("4CBE79AB-EEDA-4AB6-B8F2-80286BEDAC4A"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IConfigureVideoEncoder
{
void SetParams(ref Params param);
void GetParams(ref Params param);
void GetRunTimeStatistics(ref Statistics param);
};

[Guid("46F60C41-6809-432E-8D0E-293C34DECFDD"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IConfigureH264Encoder : IConfigureVideoEncoder
{
};

And how I'm setting the parameters:

// Set up encoding parameters.
EncodeFilter enc = new EncodeFilter();
IConfigureH264Encoder configure = (IConfigureH264Encoder)enc;
Params param = new Params();
configure.GetParams(ref param);
configure.SetParams(ref param);

The part of code I'm not sure how to convert is this:

struct H264Params: IConfigureVideoEncoder::Params

I believe this is my last barrier, any suggestions?

Cheers.

~Marty

Hello Martin,

since c# doesnt support structures inheritance you may declare parent structure Params as a first member of H264Params structure.

Actually as i mentioned interface that you are using changed, together with its guid, so in my first post you can see how it will look like in Beta5, there won't be any structures inheritance, as well as IConfigureH264Encoder interface.

I'm attaching whole c# console class that works, i checked that such layout of c# H264Params structure normally marshaled to unmanaged code and back.

Allegati: 

AllegatoDimensione
Download Program.cs8.06 KB

Hi Eugene,

I replaced the prior code with the proper structures for the H264 interface and all seemed well except when I set the parameters the function SetParams fails:

System.Runtime.InteropServices.COMException (0x80004005): Error HRESULT E_FAIL has been returned from a call to a COM component.

I understand that its accessing unmanaged memory but not sure how to work around this as the error is a bit vague. Any ideas? Thanks!

Cheers.

~Marty

Hello Martin,
in my first post I alreadymentioned that setparams internally resulted in calls to graph manager, and actually it has no checks for that zero pointer. So any attempts on filter that not in a filter graph will result in such exception.
Here is exact place

\beta4\samples\sample_dshow_plugins\video_enc_filter\src\mfx_video_enc_filter.cpp line : 1030

hr = m_pGraph->QueryInterface(IID_IFilterGraph, (void**)&pGraph);

So you may comment this line and rebuild/register h264 encoder filter, and see whether it helps.

I didnt try to add filters to graph manager, but you may do it since it required to perform any processing.

Hi Eugene,

I did see the comment above that line your post, but wasn't sure if it was the cause. I am adding the filter to the graph prior to setting the parameters however It was being done before by using just the GUID to instantiate the filter... I figured because the EncodeFilter class has the same guid it shared the same instance.

Do I have to recreate the graph using the Class GUID and not a private field?

Currently it is being add like this:

private static Guid CLSID_IntelMediaSDKH264Encoder = new Guid("{71183C45-F4FA-4B10-9E04-F9040CB19139}"); //h264_enc_filter.dll

pIntelMediaSDKH264Encoder = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_IntelMediaSDKH264Encoder));
hr = pGraph.AddFilter(pIntelMediaSDKH264Encoder, "Intel Media SDK H.264 Encoder");

My problem is I can't put The comimport class into that structure. I'll keep at it, any more ideas are most grateful.

Thanks Eugene.

~Marty

Ah I figured it out, instead of activating the filter I create an instance of the comimport and simply declare it as IBaseFIlter when needed. Set params works! Thanks for all your help. :)

Cheers.

~Marty

I don't think the versions of "program.cs" in this thread work with the final released Intel Media SDK 2012, since various fields have been renamed and the structures have been reordered since versions referenced earlier in this thread.

Attached is an updated version (only lightly tested):

Allegati: 

AllegatoDimensione
Download IntelH264EncoderSettings.cs8.27 KB

Hi there, you are absolutely right. Thank you for contributing this update to the community!
regards,Nina

Lascia un commento

Eseguire l'accesso per aggiungere un commento. Non siete membri? Iscriviti oggi