Home » Windows OSRSS

How to stuff raw video into a container format (MPEG2 -> AVI, H264 ->MP4)

Hello!

I have a raw video stream (h264) that I would like to stuff into a container format (MP4).

From what I understand about DirectShow, there are no H264 -> MP4 filters that come standard with the Windows SDK download, thus I would have to use an extension already written by someone else, or write my own.  Is this correct?  Or have there been some recent filter additions that I am missing here?

Secondly, I have heard integrating extensions is less than friendly for someone who is green when it comes to DirectShow....so I have been attempting to stuff an mpeg2 raw video stream into a ASF file container just so that I can get my feet wet with the whole DirectShow Dev Environment and get used to calling the various COM objects and their respective interfaces.  Again, my reasoning behind doing this, is because I believe ALL the necessary filters to accomplish this, are available right out of the DirectShow box (no extension required).  Unfortunately, I haven't seen any intuitive sample code that is doing something similar anywhere on the MSDN websites. 

So my #1 question would be - how do I build this filter graph to do this mpeg2 -> ASF or AVI container?  (whichever is easier to do).

I have been trying to do the following using GraphEdit...

File Async Reader ->MPEG-2 Splitter -> AVI MUX -> File Writer

However, I cannot get the MPEG-2 Splitter Filter to connect to the AVI-MUX filter ?!  Why???

Am I even on the right path here?

Okay...so let's assume I eventually get this working...I would like to eventually go from h264 to mp4, but 1 step at a time.

Can someone please help me understand how to get my first scenario working!

 

Thank you!

 = )

 

BTW - I am only dealing with VIDEO streams - NO AUDIO.

 

 

5 Answers Found

 

Answer 1

Hi there,

I've found what you're looking for on Geraint Davies site.  He/they have written and open sourced an MP4 multiplexor (and also a demultiplexor) DirectShow filter that multiplexes an H.264 stream (along with an audio stream if you like) into an MP4 file.

See http://www.gdcl.co.uk/mpeg4/ for details.   The actual download for the projects is here: http://www.gdcl.co.uk/mpeg4/mpeg4.zip

 

You could also check out MainConcept dot com, as they do a variety of directshow filters and low level SDKs for dealing with video  of many different format  types.

hope this helps.

 

Answer 2

Hey there!  Thanks for getting back to me.  Yes, I already downloaded this source code and integrated it with my solution.

Okay, so I need to start building my filter graph now.  I need a source filter to read my h264  file from local disk, so I'll use File Async Reader.

According to the less than adequate documentation on the Geraint Davies site, I am having to make an assumption that I can just feed the Mux Filter this raw  h264 bit stream.  So I need to connect the File Source Filter to the Mpeg4Mux Filter, right? 

After that, do I just connect up the Mpeg4MuxFilter to a File Writer and voila????

Would you recommend I use RenderStream to connect the pins or would you recommend I use IGraphBuilder::Connect to connect the 3 filters?

 

Thanks again!

 

Answer 3

Hi russian_bear,

I've never tried to mux a file async reader, so I can't really comment.  I use a source filter that grabs video  and audio frames from a network source.

RenderStream or Connect should work equally well.  I guess RenderStream allows you to be more precise in what you mean - .e.g. if a filter has multiple outputs, it'd be best (IMHO) to use RenderStream to specify exactly which output pins connect to which input pins.

I've pasted some code below to show usage of RenderStream:

HRESULT H264ArchiveGraph::Render()
 {
	// connect the filters of the graph together
	HRESULT hr = S_OK;	
	CString sError;
	TCHAR	szErr[MAX_ERROR_TEXT_LEN];
	
	CComPtr<IPin> spVideoPin;
	CComPtr<IPin> spAudioPin;

	try
	{	
		// video to mux
		TFAIL( m_spSource->FindPin(L"1", &spVideoPin) );

		if( spVideoPin.p )			
			TFAIL( m_spCGBuilder2->RenderStream( 0, &MEDIATYPE_Video, spVideoPin, 0, m_spMuxFilter ) )	

		// audio to mux
		m_spSource->FindPin(L"2", &spAudioPin);
		if( spAudioPin.p )			
			TFAIL( m_spCGBuilder2->RenderStream( 0, 0, spAudioPin, 0, m_spMuxFilter) );
					
		// mux to file writer				
		TFAIL( m_spCGBuilder2->RenderStream(0, 0, m_spMuxFilter, 0, m_spFileWriterFilter) );
	}
	catch ( HRESULT hrErr )
	{
		AMGetErrorText(hrErr, szErr, MAX_ERROR_TEXT_LEN);
		sError.Format( _T("Exception in H264ArchiveGraph::Render()\r\nHRESULT (0x%2x): %s"), hrErr, szErr);

		ReportMessage(sError);
		hr = hrErr;
		Reset();
	}

	return hr;
}

hope this helps!

 

Answer 4

Thanks freeFallAddict.

Here's what I did for my async file source (based on your sample code) -

// --- #1 Connection - File Async Reader Output Pin to MP4 Mux Input Pin
hr = p_SC->FindPin(L"1", &videoPin);

if (videoPin.p)			
  hr = p_BD2->RenderStream( 0, &MEDIATYPE_Video, videoPin, 0, p_MP4);	

if (hr == S_OK)
  printf("Successfully connected File Async Reader Output Pin to MP4 Mux Input Pin.\n");
else {
  printf("Failed to connect the File Async Reader Output Pin to MP4 Mux Input Pin.\n");
  printf("Error Code: %x, good luck! =(", hr);
  exit(1);
}//end else statement

The above code compiles and when I run it it says this -

Failed to connect the File Async Reader Output Pin to MP4 Mux Input Pin.
Error Code: 80040216, good luck! =(

80040216 => "An object or name was not found."

Here is how I initialize my source filter ->

hr = p_GB->AddSourceFilter(L"C:\\Users\\Pictures\\videoEncoder\\testImages2\\out.h264"
, L" Source Filter"
, &p_SC);

where p_SC is declared like the following:

IBaseFilter *p_SC = NULL;

Your thoughts ?

- the bear

 

Answer 5

It wont work, because the AsyncFileReader expects a parser filter downstream (pullling data with a CPullpin input pin), and therefore cannot connect to the mp4 mux (which has IMemInput pins, which expect data to be pushed to them).

You need to find an appropriate parser for your h264  stream, or write your own filereader/parser in push mode, so it can connect to the mp4 mux.


Michel Roujansky, http://www.roujansky.com
 
 
 

<< Previous      Next >>


Microsoft   |   Windows   |   Visual Studio   |   Follow us on Twitter