DirectShowSpy: Automated Media Sample Traces, Load Trace from File

Some time ago DirectShowSpy received a capability to record media sample traces (in specific points of the pipeline). DirectShowSpy UI visualized the chronology of the streaming which facilitated detection of various problems, especially out of order media samples, lost or late delivered samples, thread racing conditions.

A developer can easily integrate his filters with DirectShowSpy media sample tracing, and example of this is a fork of MP4 filters where this powerful option is integrated.

This time DirectShowSpy is improved to offer automated traces. Typical use scenario is automatic creation of media sample trace file so that it could be logged/attached to specific export process and be available for further review. More specifically, an application could run a transcoding session and generate a detailed media sample trace alogn with the output in order to troubleshoot specific issues (dropped frame etc).

DirectShowSpy’s IFilterGraphHelper (implemented by FilterGraphHelper class) object received new additional methods:

interface IFilterGraphHelper : IDispatch
{
    [...]
    [id(7)] HRESULT ResetMediaSampleTrace([in] VARIANT vProcessIdentifier);
    [id(8)] HRESULT LockMediaSampleTrace([out, retval] IUnknown** ppLockUnknown);
    [id(9)] HRESULT GetMediaSampleTrace([in] VARIANT vProcessIdentifier, [out, retval] BSTR* psText);

ResetMediaSampleTrace clears currently recorded in-memory trace. The method is similar to pressing Backspace key in media sample trace UI. Optional argument allows cleanup for specific process (not implemented, everything is reset).

LockMediaSampleTrace creates a COM object which internally references newly created traces so that they don’t get freed with the respective filter graph release. Traces are owned by respective filter graphs and even though are accessible across process boundaries they are disposed with the release of graphs-creators. Unless anyone else accesses and references the traces, in which case they are available for review even is originating graph is already gone. This is the behavior of media sample trace UI, which is automatically referencing new traces as long as UI is visible. Developer can review traces for graphs already terminated (even crashed!). LockMediaSampleTrace method returns an interface pointer which owns an internals thread monitoring and referencing new traces. Once the interface pointer is releases, all referenced traces are released as well.

GetMediaSampleTrace obtains a copy of media sample trace for all or for specific process, in multi-line TSV format similar to text created by user interactively when data is copied to clipboard or saved into file with the help of UI.

All together, a controlling application can create a trace automatically using the following code:

#import "libid:B9EC374B-834B-4DA9-BFB5-C1872CE736FF" raw_interfaces_only // AlaxInfoDirectShowSpy

// ...

CComPtr<AlaxInfoDirectShowSpy::IFilterGraphHelper> pFilterGraphHelper;
pFilterGraphHelper.CoCreateInstance(__uuidof(AlaxInfoDirectShowSpy::FilterGraphHelper));
ULONGLONG nAlaxInfoDirectShowSpyFileVersion = 0;
CComPtr<IUnknown> pMediaSampleTraceLock;
if(pFilterGraphHelper)
{
    const CComQIPtr<AlaxInfoDirectShowSpy::IModuleVersionInformation> pModuleVersionInformation = pFilterGraphHelper;
    if(pModuleVersionInformation)
        _V(pModuleVersionInformation->get_FileVersion((LONGLONG*) &nAlaxInfoDirectShowSpyFileVersion));
    if(nAlaxInfoDirectShowSpyFileVersion >= _VersionInfoHelper::MakeVersion(1, 0, 0, 2060)) // Available in 1.0.0.2060+
    {
        _V(pFilterGraphHelper->ResetMediaSampleTrace(CComVariant((LONG) GetCurrentProcessId())));
        _V(pFilterGraphHelper->LockMediaSampleTrace(&pMediaSampleTraceLock));
    }
}

// DirectShow filter graph runs go here

if(pFilterGraphHelper && nAlaxInfoDirectShowSpyFileVersion >= _VersionInfoHelper::MakeVersion(1, 0, 0, 2060))
    _ATLTRY
    {
        CComBSTR sText;
        __C(pFilterGraphHelper->GetMediaSampleTrace(CComVariant((LONG) GetCurrentProcessId()), &sText));
        if(sText && *sText)
        {
            CPath sPath = Combine(m_sOutputDirectory, _T("MediaSampleTrace.tsv"));
            CAtlFile File;
            __C(File.Create(sPath, GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS));
            // SUGG: UTF-8 BOM
            CStringA sTextA = Utf8StringFromString(CStringW(sText));
            __C(File.Write(sTextA, (DWORD) sTextA.GetLength()));
        }
    }
    _ATLCATCHALL()
    {
        _Z_EXCEPTION();
    }

Additionally, interactive UI for reviewing media sampla traces (DoMediaSampleTracePropertySheetModal DLL export, see respective BAT file) reviewed a new command to load external TSV file (such as generated with the help of code above!) for review:

DirectShowSpy Media Sample Trace

Once data loaded from file, disabled Refresh link indicates use of non-live data. Context menu command offers option to switch back to live data.

Download links

Leave a Reply