views:

460

answers:

1

Hi,

i want to display thumbnails for videos listed on my site, i want to fetch a single frame from a video (from a particular time) and display them as thumbnails.

Is that possible using .Net ? (C# or VB)

+2  A: 

Yes that is possible. You need to use DirectShow.NET. I found this useful.

EDIT :

OK it looks like the library has changed since I used it... curse open source :)

I just translated to the following code and tested and it works fine for me(note that it assumes there is a wmv in c:\aaa called C4.wmv and the output will go to c:\aaa\out.bmp)

IGraphBuilder graphbuilder = (IGraphBuilder)new FilterGraph();
      ISampleGrabber samplegrabber = (ISampleGrabber) new SampleGrabber();
      graphbuilder.AddFilter((IBaseFilter)samplegrabber, "samplegrabber");

      AMMediaType mt = new AMMediaType();
      mt.majorType = MediaType.Video;
      mt.subType = MediaSubType.RGB24;
      mt.formatType = FormatType.VideoInfo;
      samplegrabber.SetMediaType(mt);

      int hr = graphbuilder.RenderFile("C:\\aaa\\c4.wmv", null);

      IMediaEventEx mediaEvt = (IMediaEventEx)graphbuilder;
      IMediaSeeking mediaSeek = (IMediaSeeking)graphbuilder;
      IMediaControl mediaCtrl = (IMediaControl)graphbuilder;
      IBasicAudio basicAudio = (IBasicAudio)graphbuilder;
      IVideoWindow videoWin = (IVideoWindow)graphbuilder;

      basicAudio.put_Volume(-10000);
      videoWin.put_AutoShow(OABool.False);

      samplegrabber.SetOneShot(true);
      samplegrabber.SetBufferSamples(true);

      long d = 0;
      mediaSeek.GetDuration(out d);
      long numSecs = d / 10000000;

      long secondstocapture = (long)(numSecs * 0.10f);


      DsLong rtStart, rtStop;
      rtStart = new DsLong(secondstocapture * 10000000);
      rtStop = rtStart;
      mediaSeek.SetPositions(rtStart, AMSeekingSeekingFlags.AbsolutePositioning, rtStop, AMSeekingSeekingFlags.AbsolutePositioning);

      mediaCtrl.Run();
      EventCode evcode;
      mediaEvt.WaitForCompletion(-1, out evcode);

      VideoInfoHeader videoheader = new VideoInfoHeader();
      AMMediaType grab = new AMMediaType();
      samplegrabber.GetConnectedMediaType(grab);
      videoheader =
      (VideoInfoHeader)Marshal.PtrToStructure(grab.formatPtr,
      typeof(VideoInfoHeader));


      int width = videoheader.SrcRect.right;
      int height = videoheader.SrcRect.bottom;
      Bitmap b = new Bitmap(width, height, PixelFormat.Format24bppRgb);

      uint bytesPerPixel = (uint)(24 >> 3);
      uint extraBytes = ((uint)width * bytesPerPixel) % 4;
      uint adjustedLineSize = bytesPerPixel * ((uint)width + extraBytes);
      uint sizeOfImageData = (uint)(height) * adjustedLineSize;


      BitmapData bd1 = b.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
      int bufsize = (int)sizeOfImageData;
      int n = samplegrabber.GetCurrentBuffer(ref bufsize, bd1.Scan0);
      b.UnlockBits(bd1);
      b.RotateFlip(RotateFlipType.RotateNoneFlipY);
      b.Save("C:\\aaa\\out.bmp");
      Marshal.ReleaseComObject(graphbuilder);
      Marshal.ReleaseComObject(samplegrabber);

Also be aware that DirectShow is somethign of a framework in limbo... MS kind of recommend that you go to Media Foundation... I am an old school DirectX programmer that frankly doesn't do much with it any more.

Gray Area
Hi,I referenced the DirectShowLib-2005.dll, but I am stuck on line 2 of the example code you linked me to :) Type comtype = Type.GetTypeFromCLSID( Clsid.FilterGraph );What would the ClsId be?
Michel
Yeah! it works. Thanks very much!
Michel
Well, ehm, i hardly dare to ask... i updated the software that comes with my camera, and the GRMBL software now doesn't let me export to WMV, but only to it's native format: MP4. I tried to understand the code to make it work for the MP4 file too (because it crashes at a MP4 file), but i realy don't know how.Can you also help me out with this one?
Michel
I don't have that much experience with MPEG-4 and DS I am afraid. I know(last I heard) that DS does nto support MPEG-4 out of the box and you need to get a third party filter(A quick google finds this http://www.softpedia.com/progDownload/FFDShow-MPEG-Video-Decoder-Download-5527.html But I have not used.). Most of my MPEG-4 experience comes from hackign on ffmpeg to build transcoders. I would suggest that you actually have a look into ffmpeg as a command lien solution that you coudl use to create thumbnails on the server side(I have use this very successfully in some very large video sites).
Gray Area