This project is read-only.

AviFileRenderer Fails to render when Audio present

Topics: User Forum
Feb 20, 2007 at 1:15 PM
Hi,

I creatred an audio group, added a track tothat group and then added an audio file to that track.

I then render this timeline using avifilerenderer (yes the timeline has video tracks).
I get the following error:
"No Combination of intermediate filters could be found to make the connection."

object AudSource = null;

Guid iidVid = typeof(IBaseFilter).GUID;
Guid iidAud = typeof(IBaseFilter).GUID;

foreach (DsDevice d in DsDevice.GetDevicesOfCat(FilterCategory.AudioCompressorCategory))
{
if (d.Name.CompareTo("MPEG Layer-3") == 0)
//if (d.Name.CompareTo("Windows Media Audio V2")==0)
//if (d.Name.CompareTo("PCM") == 0)
{
d.Mon.BindToObject(null, null, ref iidAud, out AudSource);
break;
}
}
IBaseFilter AudComp = (IBaseFilter)AudSource;
.
.//Get video compressor using the same way (which works like a charm)
.
Splicer.Renderer.IRenderer re = new Splicer.Renderer.AviFileRenderer(sTL, outputfile, VidComp,AudComp, null, null);

Does anyone know how to fix this little problem? (in other words, it won't render if i have any audio in the timeline, other than that it runs fine)

Thanks
Feb 21, 2007 at 3:43 PM
It may be an issue with how the filter graph is attempting to connect.

In Splicer.Utilities.FilterGraphTools.ConnectFilters()

Replace the line

destPin = DsFindPin.ByDirection(downFilter, PinDirection.Input, 0);

with

destPin = null;
IEnumPins iEnum;
IPin[] pins = new IPin1;
downFilter.EnumPins(out iEnum);

int fetched;
iEnum.Next(1, pins, out fetched);
while (fetched == 1)
{
PinDirection pinDir;
IPin pPin;
destPin = pins0;
destPin.QueryDirection(out pinDir);
destPin.ConnectedTo(out pPin);
if (pPin == null && pinDir == PinDirection.Input)
break;

if(pPin != null)
Marshal.ReleaseComObject(pPin);

iEnum.Next(1, pins, out fetched);
}

And also add the following line in the finally block:
Marshal.ReleaseComObject(iEnum);


This helped me out with an MP4 encoder and it may solve your problem. I have not figured out why the other code works for other video files though. Just starting out with this stuff.


Feb 22, 2007 at 10:16 AM
mille562,

You are a life saver :).
thank you very much for the quick fix.
(if you look at your self as "starting out with this stuff",
then I guess I am illetrate in this stuff :p)

Do u have any material that might be usefull to get me started with
the fundementals of DirectShow and DES?
(I still don't understand graphs and filters and pins!)

For example, I have this problem for a while now and I don't know how to do it.
I used some sample code to display the property page of a video compressor.
The DV Video Encoder, and it shows a simple box where you either select NTSC or PAL.
I want to select pal programatically so that the user doesn't always select it.

No luck. I guess I need to query the device or compressor and do something to the output pin right?
(you see I am totally lost here).

Any help would be appreciated.

Thanks
Feb 22, 2007 at 11:53 AM
:)
I am really wondering why is the info about directshow poorly distributed in many places :s.
I googled on DV Encoder and came across MSDN2 page
(http://msdn2.microsoft.com/en-us/library/ms783496.aspx)
which helped me to get to the IDVEnc interface which enables me
to modify the parameters without displaying the properties box.

But my question still stands :) do u have any good resources to learn/understand
directshow and graphs/pins..etc?

Thank you again for all your help.

Regards...
Feb 22, 2007 at 7:32 PM
Hi FadiK & mille562 - would you be interested in contributing this bug fix to the source code (I've promoted you both the developer role, check out this discussion here: http://www.codeplex.com/splicer/Thread/View.aspx?ThreadId=7520 )

Cheers,

- Alex
Feb 23, 2007 at 12:47 AM
FadiK-

I'm glad that you were able to find a solution to your problem.

As far as how I figured out how to work with directshow, it was more trial and error. I worked starting from DirectShowLib.Net examples and my goal was to create a MP4 based encoder. It took me a week of trying different things to figure it out.

I don't think there is very good documentation on DirectShow development. I found I got the farthest by looking at the properties and methods on an object (w/intellisense) and then using Google Code Search to see how other people used those methods and properties in their application.

I would also suggest graphedit.exe (from microsoft). Its a great tool to visualize what is happening with the graph and pins.



Feb 23, 2007 at 12:51 AM
Alex-

I would be happy to add my code but I am hesitant for 2 reasons-

1)The MP4 encoder uses a commercial encoder from 3IVX, although it is only $20 to buy.
2)The changes I made to the ConnectFilters method work, but I am not 100% sure they are the right way to do things. And to be honest, I don't know how I would find out if it is the right way or the 'best practice.' I would be more than happy to add my changes when I get some free time.

Thanks-
mille562
Feb 23, 2007 at 9:16 AM
Hi mille562,

It would be great to have your contributions - I would assume your code can be compiled without the 3IVX codec installed?

As you've probably noticed the projectis split across the core and contrib projects - I did this so that we could have a solid core implementation, and potentially collect contributed renderers and other components which were either untested, difficult to test (i.e. relied on commercial codecs) or were in the early stages of development before being migrated into the core implementation, sounds like the perfect place for your MP4 renderer!

I've applied the fix to the ConnectFilters() method, and am in the process of running the test suite to ensure everything is still working as expected before committing the results.

Chez,

- Alex
Feb 25, 2007 at 8:01 AM
mille562,

I see what you mean, hehe thats the kind of path I am following at the moment and its very time consuming. I am glad that I found people like you and Alex who share their info so that other developers won't re-invent the wheel.
Feb 25, 2007 at 8:03 AM
Alex,

Thanks for the initiative.
In theory I don't have any problems to help out and contribute.

I will see how I can fit my time with all this and see what I can do or
help out in.

Thanks again.

Fadi .K
Mar 15, 2007 at 4:13 PM
Hi!

i'm completly new in these matters.. so I ask with a little knowledge about the issue.
I'm trying to write a code that encode a video (sometimes fullscreen) in some avi format.. i alreade made the change that millie562 and I still have the exception Fadik wrote in the begining (well, I didn't found the function with that signature, so I replaced all the DsFindPin.ByDirection with the code indicated up in the thread.

I already try combining the next list
WMVideo Encoder DMO
MSScreen encoder DMO
WMVideo9 Encoder DMO
MSScreen 9 encoder DMO
DV Video Encoder
ffdshow video encoder
Indeo® video 5.10 Compression Filter
MJPEG Compressor
Cinepak Codec by Radius
DivX® 6.2.5 Codec (2 Logical CPUs)
ffdshow Video Codec
Intel 4:2:0 Video V2.50
Intel Indeo(R) Video R3.2
Intel Indeo® Video 4.5
Indeo® video 5.10
Códec Intel IYUV
Microsoft H.261 Video Codec
Microsoft H.263 Video Codec
Microsoft RLE
Microsoft Video 1
TechSmith Screen Capture Codec
Microsoft Windows Media Video 9
x264 - H264/AVC encoder
XviD MPEG-4 Codec

but no one among them really function... If someone can help, it will be too appreciate
thanks in davance :D
Mar 19, 2007 at 12:28 AM
Hi,

You should not change all of them, i'll try to find at which line exactyly and let u know,
but I am at home now, maybe tom when I am at work.

Rgds,

Fadi
Mar 20, 2007 at 3:28 PM
thank's I'll wait, and try to make it work.
thank's again 8D
Mar 22, 2007 at 12:28 PM
Hi George,
seems my memory had failed me. I didn't only change one method, i changed two methods out of the four
connectFilters() methods.

The first method is located at line 769 of Splice.Utilities.FilterGraphTools.cs
I have copied and pasted the two functiosn so that you know how they were and how they look like now.
I also comment all the modifications that has been done so that I know whats original and whats my moidifcations
incase things start to give errors I know that any addition is probably the problem :).

Tell me how it goes with u.

====================================

/// <summary>
/// Connects the first output pin of the upfilter to the first input pin of the downfilter.
/// </summary>
/// <param name="graphBuilder"></param>
/// <param name="sourcePin"></param>
/// <param name="downFilter"></param>
SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)
public static void ConnectFilters(IGraphBuilder graphBuilder, IPin sourcePin, IBaseFilter downFilter,
bool useIntelligentConnect)
{
if (graphBuilder == null)
throw new ArgumentNullException("graphBuilder");

if (sourcePin == null)
throw new ArgumentNullException("sourcePin");

if (downFilter == null)
throw new ArgumentNullException("downFilter");

IPin destPin;

//Commented out and modified as seen below
//destPin = DsFindPin.ByDirection(downFilter, PinDirection.Input, 0);

//Modified from original splicer src upon time of download -edited by fadi.k
destPin = null;
IEnumPins iEnum;
IPin[] pins = new IPin1;
downFilter.EnumPins(out iEnum);

int fetched;
iEnum.Next(1, pins, out fetched);
while (fetched == 1)
{
PinDirection pinDir;
IPin pPin;
destPin = pins0;
destPin.QueryDirection(out pinDir);
destPin.ConnectedTo(out pPin);
if (pPin == null && pinDir == PinDirection.Input)
break;

if (pPin != null)
Marshal.ReleaseComObject(pPin);

iEnum.Next(1, pins, out fetched);
}
//endby fadi.k

if (destPin == null)
throw new ArgumentException("The downstream filter has no input pin");

try
{
ConnectFilters(graphBuilder, sourcePin, destPin, useIntelligentConnect);
}
finally
{
Marshal.ReleaseComObject(destPin);
Marshal.ReleaseComObject(iEnum);//by fadi.k
}
}

/// <summary>
/// Connects the first output pin of the upfilter to the first input pin of the downfilter.
/// </summary>
/// <param name="graphBuilder"></param>
/// <param name="upFilter"></param>
/// <param name="downFilter"></param>
SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)
public static void ConnectFilters(IGraphBuilder graphBuilder, IBaseFilter upFilter, IBaseFilter downFilter,
bool useIntelligentConnect)
{
if (graphBuilder == null)
throw new ArgumentNullException("graphBuilder");

if (upFilter == null)
throw new ArgumentNullException("upFilter");

if (downFilter == null)
throw new ArgumentNullException("downFilter");

IPin sourcePin, destPin;

sourcePin = DsFindPin.ByDirection(upFilter, PinDirection.Output, 0);

if (sourcePin == null)
throw new ArgumentException("The source filter has no output pin");

//destPin = DsFindPin.ByDirection(downFilter, PinDirection.Input, 0);

//by fadi.k
destPin = null;
IEnumPins iEnum;
IPin[] pins = new IPin1;
downFilter.EnumPins(out iEnum);

int fetched;
iEnum.Next(1, pins, out fetched);
while (fetched == 1)
{
PinDirection pinDir;
IPin pPin;
destPin = pins0;
destPin.QueryDirection(out pinDir);
destPin.ConnectedTo(out pPin);
if (pPin == null && pinDir == PinDirection.Input)
break;

if (pPin != null)
Marshal.ReleaseComObject(pPin);

iEnum.Next(1, pins, out fetched);
}
//endby fadi.k


if (destPin == null)
throw new ArgumentException("The downstream filter has no input pin");

try
{
ConnectFilters(graphBuilder, sourcePin, destPin, useIntelligentConnect);
}
finally
{
Marshal.ReleaseComObject(sourcePin);
Marshal.ReleaseComObject(destPin);
Marshal.ReleaseComObject(iEnum);//by fadi.k
}
}

Mar 23, 2007 at 6:19 PM
Thanks Fadik :D

I tryed, I'm still having problems, it allows to finish the work in some cases (with a few codecs) but doesn't compress the video, I'm beggining to look for another option to complete the program I'm doing (I only have 3 more days), I'm really thankfull for your help.

I have these 2 exceptions:
A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in DirectShowLib-2005.dll
A first chance exception of type 'System.Runtime.InteropServices.InvalidComObjectException' occurred in Splicer.dll

thanks again, I'm going to continue trying to use it for my own purposes, so I'm going to be in touch
Mar 23, 2007 at 8:29 PM
Hi George,

Oh, I wish I was more of help.
Just one thought, I didn't know that you were trying to
make all/most of the codecs work.
in that case you have another issue :).

Ok I am somehwat new to all this so what I might say here could be
non-sense, but here goes a try.
I believe that if the intellegent connect feature of the graph can't
find the correct intermediate filters, it will give you errors,
so your best best is to use graphedit.exe (comes with the sdk)
and try to manually encode/decode a file, this way you know
which filters work with which intermediate filters and then
build it using splicer.

I am sorry but I dunno what more I can say at the moment, or if even
what I said already is correct :).

Let us know how it goes with u.

Regards,

Fadi .K
Apr 14, 2009 at 9:52 PM
Changes proposed in this thread for ConnectFilters methods have been applied to the source code - available in [release:49146].