Something went terribly wrong in x64 build of Windows Media Video 9 Decoder

Unfortunately, 64-bit version of Windows Media Video 9 Decoder is not as good as its 32-bit sister. 32-bit version is user an order of magnitude more frequently and does not give troubles, nevertheless 64-bit version offers similar feature set it is pretty hard to see it in action since it takes a 64-bit media application to host it and most of media applications are 32-bit (there is often a good reason for this), and even Windows SDK 7.0 topoedit comes pre-built as Win32 application only (provided with source code though, so one can built x64 peer – after fixing buildability issues and adding x64 configuration manually).

Decoder is available as dual DMO/MFT which enabled it for both DirectShow and Media Foundation APIs and similarly exposes the problem in both as well.

Once in a while, 64-bit version of the decoder might be producing incorrect output, adding white dots where they are not supposed to be.

02

Because the problem resides supposedly in the decoder itself, it affects everything decoding Windows Media Video of this flavor, including

  • Windows Media Player 64-bit
  • GraphEdit x64 from Windows SDK
  • TopoEdit x64 from Windows SDK (built manually)

The only exception is DXVA-accelerated decoding where bug is worked around by hardware assisted decoding and the output is correct.

Image002

One of the ways to easily see and reproduce the problem in action is to re-encode the content in 64-bit version of GraphEdit into anything else: video decoder there will decode in software and burn the artifacts in.

See also:

DirectShow Spy: Integration with GraphStudioNext

DirectShow Spy is introducing integration with GraphStudioNext (and GraphEdit too) to let a developer quickly open a filter graph through Running Object table with external inspection tool.

Note that you need a revision 301 GraphStudioNext or later, prebuilt versions available for download here: graphstudionext.exe (Win32), graphstudionext64.exe (x64).

DirectShow Filter Graph list window offers context menu items and hotkeys to launch GraphStudioNext with command line parameters to open specific filter graph.

GraphStudioNext Integration in Filter Graph List

DirectShow Filter Graph Property Frame dialog’s actions view has a button and a hotkey to open current filter graph in GraphStudioNext:

GraphStudioNext Integration in Filter Graph Actions

When invoked from DirectShowSpy UI, GraphStudioNext opens immediately at view of interest:

A Filter Graph in Graph Studio Next

Spy is looking for GraphStudioNext in last used location (stored in registry), in current spy’s directory, in GraphStudioNext registry subkey and if none of the mentioned works then prompts user to locate the binary.

Similar functionality is also available programmatically using one of the following ways:

  • ISpy::OpenGraphStudioNext([in] LONG nParentWindowHandle, [out, retval] VARIANT_BOOL* pbResult);
  • IFilterGraphHelper::OpenGraphStudioNext([in] LONG nParentWindowHandle, [in] BSTR sMonikerDisplayName, [out, retval] VARIANT_BOOL* pbResult);

Download links

DirectShow Spy: Filter Graph Data and Properties UI

Summary

DirectShow Spy receives a set of new powerful updates helping to develop and troubleshoot DirectShow applications:

  • UI combining Markdown formatted filter graph details as well as property pages for all participating filters
    • available interactively via filter graph list
    • available via helper COM class letting DirectShow application integrate incredible troubleshooting capabilities
  • Option to email filter graph details

On of the next posts should be summarizing all DirectShowSpy capabilities currently split across posts.

Filter Graph Details UI

Filter graph list window received a new button Properties with the associated action duplicated on double click handler for the list item. Once clicked, a new UI pops up to bring information about the entire graph.

Properties Button in the Filter Graph List

The window contains a tree control on the left, items of which show the following elements:

  1. Top “Filters” item shows Markdown formatted text, mentioned in an earlier post
  2. Second level items are one per each filter participating in the filter graph
    • a double click of such item brings up standard OleCreatePropertyFrame property sheet with filter properties
    • an edit control to the right lists filter specific information, with connections and media types
  3. Third level items are property pages of the filter, the property pages are integrated into the window; all together, the window provides access to all property pages of all filters in the graph
  4. Bottom first level “Email” items provides a convenient way to send the information via email

The picture below shows a property page integrated into the UI:

Integrated Filter Property Page

Email interface adds basic information about the system, and also provides space to enter a note about the graph. Email information (From, To etc) is put on registry for further reuse.

Email Filter Graph

Programmatic Interface

Additionally to interactive access from filter graph list, the new UI is also accessible viaFilterGraphHelper COM class. This lets applications integrate new capability right into the application as a troubleshooting option.

While accessing the graph through ROT using GraphStudioNext/GraphEdit application remains the most convenient interactive way to work with the graph, the helper’s advantage is access to the graph without crossing process boundaries: this, in particular, provides smooth access to property pages not implemented well for marshaling, such as, for example, Audio Renderer related property pages.

FilterGraphHelper‘s FilterGraph property accepts filter graph interface pointer (from now on, it is also possible to supply any filter or pin interface, and helper will walk up to the graph automatically).

IFilterGraphHelper::DoPropertyFrameModal method shows the UI modal window introduced above.

Two samples are demonstrating programmatic access to the new helper method.

  1. Sample\FilterGraphHelperDialog (SVN) C# application (code snippet) shows it straightforward way: to build a graph, to initialize helper, to show modal UI:
    IFilterGraph2 graph = new FilterGraph() as IFilterGraph2;
    graph.RenderFile(@"E:\Media\GoPro 2010 Highlights - You in HD - 1920x1080.mp4", "");
    FilterGraphHelper helper = new FilterGraphHelper();
    helper.FilterGraph = graph;
    helper.DoPropertyFrameModal(0);
    
  2. Sample\RegistrationFreeFilterGraphHelper (SVN) C++ application features an advanced technique to leverage new capability in application, without need to COM-register the Spy.

Registration of the DirectShowSpy requires, generally speaking, administrative privileges. Then in addition spy hooks the system which might be not desirable.

The application however load the Spy directly using LoadLibrary API and instantiates the helper directly bypassing COM registration. This is sufficient to start the new UI feature and access the graph interactively.

    CComPtr<IFilterGraphHelper> pFilterGraphHelper;
    #if TRUE
        const HMODULE hModule = LoadLibrary(_T("DirectShowSpy.dll"));
        [...]
        ATLENSURE_SUCCEEDED(pClassFactory->CreateInstance(NULL, __uuidof(IFilterGraphHelper), (VOID**) &pFilterGraphHelper));
        // TODO: FreeLibrary against hModule
    #else
        ATLENSURE_SUCCEEDED(pFilterGraphHelper.CoCreateInstance(__uuidof(FilterGraphHelper)));
    #endif
    ATLENSURE_SUCCEEDED(pFilterGraphHelper->put_FilterGraph(pFilterGraph));
    ATLENSURE_SUCCEEDED(pFilterGraphHelper->DoPropertyFrameModal(0));

The alternate #if code path shows the COM registration equivalent for the code.

Download links

The case of incorrect behavior of stock DirectX Media Objects

Since Microsoft Windows Vista, Media Foundation API offers a set of convenient Digital Signal Processors for video and audio processing. These include conversion helpers for video and audio, dual interfaced as Media Foundation Transforms (MFTs) and DirectX Media Objects (DMOs). Earlier posts shed some light on DMO interfaces, and use of DMOs in DirectShow graphs with the help of DMO Wrapper Filter.

It appears, however, that some of the stock DMOs are exhibiting unexpected behavior in part of setting media types for input and output streams. IMediaObject::SetInputType and IMediaObject::SetOutputType methods are not only expected to set media types, but also test and clear them depending on flags passed in arguments:

There are three modes defined, depending on value of dwFlags parameter:

  • 0 – [test and] set media type
  • DMO_SET_TYPEF_TEST_ONLY – test only media type
  • DMO_SET_TYPEF_CLEAR – clear media type already set

When the DMO backs a DirectShow filter through DMO Wrapper Filter, there might be (and there definitely are in case of interactive operation in GraphEdit-like application) tests and sets, and resets too during pipeline building stage, and correct support for all flags is important for proper operation.

Unfortunately, some DMOs do not honor the flags and implement incorrect behavior. In particular,

  • Color Converter DSP (CLSID_CColorConvertDMO) does not do it right withDMO_SET_TYPEF_TEST_ONLY and is unable to test media types – instead it sets them
  • Video Resizer DSP (CLSID_CResizerDMO) does it even worse: it ignores both DMO_SET_TYPEF_TEST_ONLY and DMO_SET_TYPEF_CLEAR and attempts to set the media type even if the request was to clear

The project below (SVN, Trac) demonstrates the problem in action.

An attempt to test and print current media type shows that testing actually sets the media type:

const HRESULT nTrySetInputTypeResult = pMediaObject->SetInputType(0, &InputMediaType, DMO_SET_TYPEF_TEST_ONLY);
_tprintf(_T("nTrySetInputTypeResult 0x%08x\n"), nTrySetInputTypeResult);
PrintInputType(pMediaObject, DMO_E_TYPE_NOT_SET, _T("we only tested, we did not set it"));

Output:

nTrySetInputTypeResult 0x00000000
nGetInputCurrentTypeResult 0x00000000 <<--- Incorrect, we only tested, we did not set it
Input: biWidth 1920, biHeight 1080

An attempt to clear produces a failure, since it is treated as an attempt to set and no real media type was passed as an argument:

const HRESULT nResetInputTypeResult = pMediaObject->SetInputType(0, NULL, DMO_SET_TYPEF_CLEAR);
_tprintf(_T("nResetInputTypeResult 0x%08x%s\n"), nResetInputTypeResult, FAILED(nResetInputTypeResult) ? _T(" <<--- Incorrect") : _T(""));

Output:

nResetInputTypeResult 0x80004003 <<--- Incorrect

The problem is posted to Microsoft Connect as Digital Signal Processors do not honor flags arguments on DMO interface IMediaObject when setting input/output types where you can upvote it if you suffer from the bug, and also read back from Microsoft when they follow up.

Assembla is removing Trac. What does this mean for the blog?

Assembla, which have been hosting some of the files referenced by earlier posts, will be removing Trac from their toolset. This means that some [older] posts here will point to missing source code, and some content is not going to be available anymore.

This should not be a big issue overall, since content in question is at least a few years old. There will be no link fixing for old posts and those interested in unavailable content can get in touch with me – I will fix specific missing files/links on request.

ConnectivityWatchdog: Inaccessible TCP based Service Notification via Email

This is dual “yet another…” and utility clearance series. Once again an attempt to easily automate network availability check for a service.

The application is doing periodic TCP connectivity check and sends an email to notify on inaccessible service. If you got systems running at 2+ sites, they can be set up to check one another and inform timely on network issues.

ConnectivityWatchdog Screenshot

Configuration is provided through ConnectivityWatchdog.ini file to be put into the directory of the binary. Sample file is as follows:

[General]

[Host]
$(SomeUniqueIdentifer)=$(FriendlyName), tcp, $(TcpHostOrIpAddress), $(TcpPort)
$(SomeUniqueIdentifer)=$(FriendlyName), tcp, $(TcpHostOrIpAddress), $(TcpPort)

[Probe.TCP]
Connection Time=45 ; Timeout for TCP connection attempt, seconds
Success Idleness Time=60 ; Next attempt in case of successful connection, seconds
Failure Idleness Time=10 ; Next attempt in case of failed connection, seconds
Notification Failure Count=3, 33, 333 ; Numbers of failure attempts which trigger email notification 

[Notification]
Delay=450 ; Delay in notification in order to combine messages into single email, seconds 

[Notification.SMTP]
Host=smtp.gmail.com
Sender=$(UserName)@gmail.com
To=$(UserName)@gmail.com
TLS=1
Authentication Methods=login
Authentication Name=$(UserName)@gmail.com
Authentication Password=$(Password)

Once the application notices TCP connectivity issues, it updates UI status and as configured (see “Notification Failure Count” value above) it will trigger a notification email:

The following are the updates on $(Host) system:

 * Remote host $(FriendlyName) connection SUCCEEDED after 8 failures [2013-12-12 02:15:06 - 4 minutes ago]
 * Remote host $(FriendlyName) connection FAILED 3 times in a row (A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond - 0x8007274c) [2013-12-12 02:12:21 - 7 minutes ago]

--
  System: $(Host)
  Time: 2013-12-12 02:19:51
  Agent: Alax.Info ConnectivityWatchdog Application/1.0.0.58

All $(…) values above are placeholders.

The application has a convenient option to enable automatic startup with user logon.

ConnectivityWatchdog Current User Startup

Download links

Breaking Windows Update of Windows Media Video 9 Decoder

One of the recent updates delivered via automatic Windows Update is breaking video decoding for Windows Media Video streams (four character code WMV3). It’s hard to trace things back, however the most likely issue is the update of WMVDECOD.DLL file which is dated 6 May 2013 delivered with MS13-057: Description of the security update for Windows Media Format Runtime 9 and 9.5 (wmvdmod.dll), and for Windows Media Player 11 and 12: July 9, 2013, and it could be one or more versions before as well. The breaking update also affects Windows XP systems.

The problem is affecting both Win32 and x64 systems, and Windows XP and later, however it might be affecting them differently. While in Windows 7 the top half of the video is damaged, in Windows XP the output is totally black. There might be other factors affecting the output though.

Broken WM Video Decoding

The problem is only taking place when WM Video decoder is set to decode into 32-bit RGB format. This limits the impact to application forcing output to RGB for grabbing purposes, or use post processing in RGB domain. Decoding into YUV and 24-bit RGB formats looks correct.

The problem is easy to repeat and it is only necessary to force the feed to decode into 32-bit RGB, for instance using Sample Grabber Filter:

Filter Graph

The workaround is not to avoid decoding into 32-bit RGB. In particular, in Windows Vista one can decode into something else and then convert to 32-bit RGB using Color Converter DSP.

Links