I am working on a project in which the video file has non standard header, it is using H264 algorithm and the file is in .avi format. The problem is that file doesn't contain .avi standard header, the header is custom and i want to do the following
Please guide how can i create graph in GraphEditPlus in such scenario, sample image attached
using DirectShowLib;
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
//[STAThread]
//static void Main(string[] args)
//{
// Application.EnableVisualStyles();
// Application.SetCompatibleTextRenderingDefault(false);
// Application.Run(new Form1());
//}
static void checkHR(int hr, string msg)
{
if (hr < 0)
{
Console.WriteLine(msg);
DsError.ThrowExceptionForHR(hr);
}
}
static void BuildGraph(IGraphBuilder pGraph, string srcFile1)
{
int hr = 0;
//graph builder
ICaptureGraphBuilder2 pBuilder = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
hr = pBuilder.SetFiltergraph(pGraph);
checkHR(hr, "Can't SetFiltergraph");
Guid CLSID_Mpeg4sDecoderDMO = new Guid("{2A11BAE2-FE6E-4249-864B-9E9ED6E8DBC2}"); //DMO
Guid CLSID_Mpeg4sDecoderDMO_cat = new Guid("{4A69B442-28BE-4991-969C-B500ADF5D8A8}"); //DMO category
Guid CLSID_MP3DecoderDMO = new Guid("{BBEEA841-0A63-4F52-A7AB-A9B3A84ED38A}"); //DMO
Guid CLSID_MP3DecoderDMO_cat = new Guid("{57F2DB8B-E6BB-4513-9D43-DCD2A6593125}"); //DMO category
Guid CLSID_VideoRenderer = new Guid("{B87BEB7B-8D29-423F-AE4D-6582C10175AC}"); //quartz.dll
Guid CLSID_SampleGrabber = new Guid("{C1F400A0-3F08-11D3-9F0B-006008039E37}"); //qedit.dll
Guid CLSID_Filestreamrenderer = new Guid("{D51BD5A5-7548-11CF-A520-0080C77EF58A}"); //quartz.dll
//add File stream renderer
IBaseFilter pFilestreamrenderer = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_Filestreamrenderer));
hr = pGraph.AddFilter(pFilestreamrenderer, "File stream renderer");
checkHR(hr, "Can't add File stream renderer to graph");
//add File Source (Async.)
IBaseFilter pFileSourceAsync = (IBaseFilter)new AsyncReader();
hr = pGraph.AddFilter(pFileSourceAsync, "File Source (Async.)");
checkHR(hr, "Can't add File Source (Async.) to graph");
//set source filename
IFileSourceFilter pFileSourceAsync_src = pFileSourceAsync as IFileSourceFilter;
if (pFileSourceAsync_src == null)
checkHR(unchecked((int)0x80004002), "Can't get IFileSourceFilter");
hr = pFileSourceAsync_src.Load(srcFile1, null);
checkHR(hr, "Can't load file");
//add AVI Splitter
IBaseFilter pAVISplitter = (IBaseFilter)new AviSplitter();
hr = pGraph.AddFilter(pAVISplitter, "AVI Splitter");
checkHR(hr, "Can't add AVI Splitter to graph");
//connect File Source (Async.) and AVI Splitter
hr = pGraph.ConnectDirect(GetPin(pFileSourceAsync, "Output"), GetPin(pAVISplitter, "input pin"), null);
checkHR(hr, "Can't connect File Source (Async.) and AVI Splitter");
//add Mpeg4s Decoder DMO
IBaseFilter pMpeg4sDecoderDMO = (IBaseFilter)new DMOWrapperFilter();
var pMpeg4sDecoderDMO_wrapper = pMpeg4sDecoderDMO as IDMOWrapperFilter;
if (pMpeg4sDecoderDMO_wrapper == null)
checkHR(unchecked((int)0x80004002), "Can't get IDMOWrapperFilter");
hr = pMpeg4sDecoderDMO_wrapper.Init(CLSID_Mpeg4sDecoderDMO, CLSID_Mpeg4sDecoderDMO_cat);
checkHR(hr, "DMO Wrapper Init failed");
hr = pGraph.AddFilter(pMpeg4sDecoderDMO, "Mpeg4s Decoder DMO");
checkHR(hr, "Can't add Mpeg4s Decoder DMO to graph");
//add MP3 Decoder DMO
IBaseFilter pMP3DecoderDMO = (IBaseFilter)new DMOWrapperFilter();
var pMP3DecoderDMO_wrapper = pMP3DecoderDMO as IDMOWrapperFilter;
if (pMP3DecoderDMO_wrapper == null)
checkHR(unchecked((int)0x80004002), "Can't get IDMOWrapperFilter");
hr = pMP3DecoderDMO_wrapper.Init(CLSID_MP3DecoderDMO, CLSID_MP3DecoderDMO_cat);
checkHR(hr, "DMO Wrapper Init failed");
hr = pGraph.AddFilter(pMP3DecoderDMO, "MP3 Decoder DMO");
checkHR(hr, "Can't add MP3 Decoder DMO to graph");
//connect AVI Splitter and MP3 Decoder DMO
hr = pGraph.ConnectDirect(GetPin(pAVISplitter, "Stream 01"), GetPin(pMP3DecoderDMO, "in0"), null);
checkHR(hr, "Can't connect AVI Splitter and MP3 Decoder DMO");
//add Video Renderer
IBaseFilter pVideoRenderer = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_VideoRenderer));
hr = pGraph.AddFilter(pVideoRenderer, "Video Renderer");
checkHR(hr, "Can't add Video Renderer to graph");
//add Default DirectSound Device
IBaseFilter pDefaultDirectSoundDevice = (IBaseFilter)new DSoundRender();
hr = pGraph.AddFilter(pDefaultDirectSoundDevice, "Default DirectSound Device");
checkHR(hr, "Can't add Default DirectSound Device to graph");
//connect MP3 Decoder DMO and Default DirectSound Device
hr = pGraph.ConnectDirect(GetPin(pMP3DecoderDMO, "out0"), GetPin(pDefaultDirectSoundDevice, "Audio Input pin (rendered)"), null);
checkHR(hr, "Can't connect MP3 Decoder DMO and Default DirectSound Device");
//add SampleGrabber
IBaseFilter pSampleGrabber = (IBaseFilter)Activator.CreateInstance(Type.GetTypeFromCLSID(CLSID_SampleGrabber));
hr = pGraph.AddFilter(pSampleGrabber, "SampleGrabber");
checkHR(hr, "Can't add SampleGrabber to graph");
ISampleGrabber _sampleGrabber = ((ISampleGrabber)pSampleGrabber);
_sampleGrabber.SetOneShot(false);
_sampleGrabber.SetBufferSamples(false);
SampleGrabberCallback _sampleGrabberCallback = new SampleGrabberCallback();
//hr = ((ISampleGrabber)pSampleGrabber).SetBufferSamples(false);
//if (hr == 0)
//{
// hr = ((ISampleGrabber)pSampleGrabber).SetOneShot(false);
//}
//if (hr == 0)
//{
// hr = ((ISampleGrabber)pSampleGrabber).SetCallback(_sampleGrabberCallback, 0);
//}
//if (hr < 0)
//{
// Marshal.ThrowExceptionForHR(hr);
//}
//set callback
hr = _sampleGrabber.SetCallback(new SampleGrabberCallback(), 0);
checkHR(hr, "Can't set callback.");
AMMediaType pSampleGrabber_pmt = new AMMediaType();
pSampleGrabber_pmt.majorType = MediaType.Video;
pSampleGrabber_pmt.subType = MediaSubType.YUY2;
pSampleGrabber_pmt.formatType = FormatType.VideoInfo;
pSampleGrabber_pmt.fixedSizeSamples = true;
pSampleGrabber_pmt.formatSize = 88;
pSampleGrabber_pmt.sampleSize = 4147200;
pSampleGrabber_pmt.temporalCompression = false;
VideoInfoHeader pSampleGrabber_format = new VideoInfoHeader();
pSampleGrabber_format.SrcRect = new DsRect();
pSampleGrabber_format.TargetRect = new DsRect();
pSampleGrabber_format.AvgTimePerFrame = 400000;
pSampleGrabber_format.BmiHeader = new BitmapInfoHeader();
pSampleGrabber_format.BmiHeader.Size = 40;
pSampleGrabber_format.BmiHeader.Width = 1920;
pSampleGrabber_format.BmiHeader.Height = 1080;
pSampleGrabber_format.BmiHeader.Planes = 1;
pSampleGrabber_format.BmiHeader.BitCount = 16;
pSampleGrabber_format.BmiHeader.Compression = 844715353;
pSampleGrabber_format.BmiHeader.ImageSize = 4147200;
pSampleGrabber_pmt.formatPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(pSampleGrabber_format));
Marshal.StructureToPtr(pSampleGrabber_format, pSampleGrabber_pmt.formatPtr, false);
hr = ((ISampleGrabber)pSampleGrabber).SetMediaType(pSampleGrabber_pmt);
DsUtils.FreeAMMediaType(pSampleGrabber_pmt);
checkHR(hr, "Can't set media type to sample grabber");
//connect AVI Splitter and Mpeg4s Decoder DMO
hr = pGraph.ConnectDirect(GetPin(pAVISplitter, "Stream 00"), GetPin(pMpeg4sDecoderDMO, "in0"), null);
checkHR(hr, "Can't connect AVI Splitter and Mpeg4s Decoder DMO");
//connect Mpeg4s Decoder DMO and SampleGrabber
hr = pGraph.ConnectDirect(GetPin(pMpeg4sDecoderDMO, "out0"), GetPin(pSampleGrabber, "Input"), null);
checkHR(hr, "Can't connect Mpeg4s Decoder DMO and SampleGrabber");
//add AVI Decompressor
IBaseFilter pAVIDecompressor = (IBaseFilter)new AVIDec();
hr = pGraph.AddFilter(pAVIDecompressor, "AVI Decompressor");
checkHR(hr, "Can't add AVI Decompressor to graph");
//connect SampleGrabber and AVI Decompressor
hr = pGraph.ConnectDirect(GetPin(pSampleGrabber, "Output"), GetPin(pAVIDecompressor, "XForm In"), null);
checkHR(hr, "Can't connect SampleGrabber and AVI Decompressor");
//connect AVI Decompressor and Video Renderer
hr = pGraph.ConnectDirect(GetPin(pAVIDecompressor, "XForm Out"), GetPin(pVideoRenderer, "VMR Input0"), null);
checkHR(hr, "Can't connect AVI Decompressor and Video Renderer");
}
static void Main(string[] args)
{
try
{
IGraphBuilder graph = (IGraphBuilder)new FilterGraph();
Console.WriteLine("Building graph...");
BuildGraph(graph, @"Panasonic_HDC_TM_700_P_50i.avi");
Console.WriteLine("Running...");
IMediaControl mediaControl = (IMediaControl)graph;
IMediaEvent mediaEvent = (IMediaEvent)graph;
int hr = mediaControl.Run();
checkHR(hr, "Can't run the graph");
bool stop = false;
while (!stop)
{
System.Threading.Thread.Sleep(500);
Console.Write(".");
EventCode ev;
IntPtr p1, p2;
System.Windows.Forms.Application.DoEvents();
while (mediaEvent.GetEvent(out ev, out p1, out p2, 0) == 0)
{
if (ev == EventCode.Complete || ev == EventCode.UserAbort)
{
Console.WriteLine("Done!");
stop = true;
}
else
if (ev == EventCode.ErrorAbort)
{
Console.WriteLine("An error occured: HRESULT={0:X}", p1);
mediaControl.Stop();
stop = true;
}
mediaEvent.FreeEventParams(ev, p1, p2);
}
}
}
catch (COMException ex)
{
Console.WriteLine("COM error: " + ex.ToString());
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.ToString());
}
}
static IPin GetPin(IBaseFilter filter, string pinname)
{
IEnumPins epins;
int hr = filter.EnumPins(out epins);
checkHR(hr, "Can't enumerate pins");
IntPtr fetched = Marshal.AllocCoTaskMem(4);
IPin[] pins = new IPin[1];
while (epins.Next(1, pins, fetched) == 0)
{
PinInfo pinfo;
pins[0].QueryPinInfo(out pinfo);
bool found = (pinfo.name == pinname);
DsUtils.FreePinInfo(pinfo);
if (found)
return pins[0];
}
checkHR(-1, "Pin not found");
return null;
}
}
class SampleGrabberCallback : ISampleGrabberCB
{
public int BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
{
//Console.WriteLine("Time : " + SampleTime + " " + BufferLen);
return 0;
}
public int SampleCB(double SampleTime, IMediaSample pSample)
{
Console.WriteLine("Time : " + SampleTime + " " + pSample.GetActualDataLength().ToString());
if (pSample == null) return -1;
int len = pSample.GetActualDataLength();
IntPtr pbuf;
if (pSample.GetPointer(out pbuf) == 0 && len > 0)
{
byte[] buf = new byte[len];
Marshal.Copy(pbuf, buf, 0, len);
for (int i = 0; i < len; i += 2)
buf[i] = (byte)(255 - buf[i]);
Marshal.Copy(buf, 0, pbuf, len);
}
Marshal.ReleaseComObject(pSample);
return 0;
}
}
User contributions licensed under CC BY-SA 3.0