0

Is it possible to determine the duration of a media file?

When I say media (video) file I mean files of the following types: .wmv, .avi. .mp4, .flv, .mkv. And when I say duration I mean determine how long in minutes and seconds a video file is.

I understand each file is encoded/packed differently, but maybe each file stores their duration in the header? Are there native WinAPI functions that may allow me to read any of these files into memory or at least inspect the header? I know that native WinAPI doesn't provide any API functions for .png's so it's a long shot for movie files as well, but you never know.

If the native WinAPI doesn't have any functions able to do this, would you recommend a C++ video API/Library or would you just open the file and search the header for the duration manually (ie, using fopen())?

Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
sazr
  • 24,984
  • 66
  • 194
  • 362

2 Answers2

1

There are many different APIs out there for video. It has been a while since I have looked into it, but I found this link from a google search of "open source C++ video libraries"

As far as a windows API they seem to come and go so I personally wouldn't rely on them. They also are very unlikely to be portable. If you must you can take a look at something like Direct 3D 11. I know a popular option for games is Bink.

Any of these libraries should provide the information you require as many of the formats do contain this information in a header of some kind.

Community
  • 1
  • 1
Matthew Sanders
  • 4,875
  • 26
  • 45
  • 1
    *"As far as a windows API they seem to come and go"* - I wouldn't know of a **single** Windows API that ever went away. Which one do you have in mind? – IInspectable Apr 10 '17 at 21:13
1

If you want to do it using pure windows API (like windows browser does) you should do it with help of the propsys.dll.

Also it can be done with DirectShow. Like this:

REFERENCE_TIME GetMediaDuration(CString filePath)
{
     CComPtr<IGraphBuilder> graphBuilder;
     if (SUCCEEDED(CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC,
                                IID_IGraphBuilder, reinterpret_cast<void**>(&graphBuilder))))
     {
          CComPtr<IBaseFilter> pSource;
          HRESULT hr = graphBuilder->AddSourceFilter(filePath, L"Source", &pSource);    

          CComPtr<IPin> pPin;
          pSource->FindPin(L"Output", &pPin);   

          if (SUCCEEDED(graphBuilder->Render(pPin)))
          {
            CComPtr<IMediaSeeking> mediaSeeking;
            hr = graphBuilder->QueryInterface( IID_IMediaSeeking, reinterpret_cast<void**>(&mediaSeeking));

            REFERENCE_TIME rtDur = 100;
            if (SUCCEEDED(mediaSeeking->GetDuration(&rtDur)))
            return rtDur;
          }
      }
      return 100;
}