Registration-Free COM dependencies and COM reference isolation

Visual Studio offers COM reference isolation to applications so that COM dependency is used in a usual way, and in the same time there is no need in its registration or another copy of the COM server might be registered system wide, or using per-user registration, and the application would still prefer a local copy of COM server.

Isolated Property

The advantage is obvious: no more COM registration hell, and the application can be distributed with lowered risk of conflicts with other installed software, without a risk to affect other applications by registering an unwanted piece of software. Also, with an option to use COM dependency without need of elevated privileges to perform COM registration.

The feature is using reg-free COM and is not new. Articles on internet on using the feature date back to 2007 and earlier (e.g. Isolated COM), reg-free COM existed earlier. The feature is cool and offers a one click access to an incredibly powerful option with complicated technology underneath.

Problem 1: It is 2015 fall today and Visual Studio 2013 still does not have this – as complicated as Enabled/Disabled option – working right.

Once enabled, the option has the following effect on the project:

  1. the manifest file is detached from the binary and is written to external file (Client.exe + Client.exe.manifest as opposed to Client.exe with manifest embedded as resource)
  2. the manifest receives assembly/file elements that establish a registration-free link to COM dependency; the content of the element is repeating registration of the COM dependency normally written into registry system wide
  3. the compiler uses RegOverridePredefKey and friends API to check COM dependency registration keys and update the manifest file (see previous item) respectively

Apparently the COM server has to be registered at compile time, so that compiler could convert the registration into manifest file. For whatever reason, Visual Studio 2013 looks for 32-bit COM server when it is doing 64-bit build. That is, building x64 configuration with x64 COM server registered and supposed to be used further fails if you don’t have a similar Win32 COM server registered. Bummer.

This simple solution ComIsolation01 (Trac, SVN) has two projects: C++ COM server with 32 and 64 bit configurations, and C# client consumer. A build of Debug/Release x64 configuration successfully builds Server.dll, registers it, then attempts to build Client.exe and fails:

2>C:\Program Files (x86)\MSBuild\12.0\bin\Microsoft.Common.CurrentVersion.targets(2234,5): warning MSB3284: Cannot get the file path for type library “ae2714e3-e8be-44c7-b737-5510e5f8abed” version 1.0. Library not registered. (Exception from HRESULT: 0x8002801D (TYPE_E_LIBNOTREGISTERED))
2>D:\Projects\Alax.Info\Repository-Public\Utilities\Miscellaneous\ComIsolation01\Client\Program.cs(14,13,14,22): error CS0246: The type or namespace name ‘ServerLib’ could not be found (are you missing a using directive or an assembly reference?)
2>D:\Projects\Alax.Info\Repository-Public\Utilities\Miscellaneous\ComIsolation01\Client\Program.cs(14,51,14,60): error CS0246: The type or namespace name ‘ServerLib’ could not be found (are you missing a using directive or an assembly reference?)

TYPE_E_LIBNOTREGISTERED, really? Because it looks for 32-bit type library and there is only 64-bit one registered. Build Win32 configuration once, and x64 builds are fixed. In other aspects, x64 build of Server.dll is correctly picked up.

Problem 2: Inflexible. The only COM reference isolation offered is a link with size and hash specification of the dependency.

Strict dependency check in manifest file

Why on earth? Okay it might be good for some people, perhaps. The only scenario I want to ever use is a link without checks for whether dependency is exactly as at build time. It is already isolated and the isolated file will be picked up. I would like to retain an option to patch it quickly by simply substituting a new file there, without an annoying need to patch manifest respectively. I don’t have an option like this.

Another post soon will show a solution for the problem, as well as easy way to apply isolation to C++ clients as well.

Lync (Skype for Business) and H.264

A blog reader asked an interesting question a question about H.264 support in Lync. There have been a number of announcements on H.264 integration with multiple pieces of software:

Fantastic news! I will just leave the links here (perhaps they are not even all quite relevant) for the time I would want to revisit this pile of issues (or this would hopefully never happen). Some of them are from quite some past. Presently, however people having really hard time getting stuff working well one with another:

Let’s just make one thing clear. I do have Windows 8.1 system which is supposed to pick up UVC 1.5 compliant camera, and I do have “1st of New Generation of UVC 1.5 H.264 WebCams” Logitech Webcam C930e camera.

More to that, I do see it does do H.264 (in a weird way but still – and the camera itself is really cool, I like it!):

H.264 Video Capture with Logitech C930e

As a user, I expect that Lync 2013 (Skype for Business 2015) somehow figure the H.264 support out and do the thing out of the box. This is what the original question I was asked was about. What I do see – and this is what I was able to “touch” myself to avoid guesswork – is that a preview video feed from the device is NOT using H.264:

Video Preview with Lync 2013 and Logitech C930e

Well, maybe it is leveraging H.264 in real conference? Not sure.

Perhaps Skype can capture H.264? Oops, not it cannot (this is from real video call session):

Skype Video Call and Logitech C930e

Okay, it simply does not all work yet. As a guess, this worked with Windows 7 style of H.264 webcam and then the way Windows 8 offered support for UVC 1.5 devices broke it (if it at all ever worked!).

Reference signal source for DirectShow

Every so often there are tasks that need certain reference video or video/audio footage with specific properties: resolution, frame rate, frame accuracy with content identifying specific frame, motion in view, amount of motion which is “hard” for processing with encoder tuned for natural video, specific video and audio synchronization.

There is of course some content available, and sometimes it’s really nice:

Bipbopbipbop video on Youtube

However once in a while you need 59.94 fps and not 60, and another time you’d go with 50 so that millisecond time is well-aligned and every second has equal number of frames, then next time you need specific aspect ratio override and then you’d prefer longer clip to a short one.

I converted one of my sources for reference signal into DirectShow filters, which might be used to produce infinite signal, or otherwise they might be used to generate a file of specific format with specific properties.

The filters are Reference Video Source and Reference Audio Source, regular filters registered in a separate category (not virtual video/audio source devices – yet?), available for instantiation programmatically or in GraphStudioNext/GraphEdit.

DirectShowReferenceSource filters in GraphStudio

The filters are in both 32- and 64-bit versions, with hardcoded properties (yet?): 1280×720@50 32-bit RGB for video and 16-bit PCM mono at 48 kHz for audio. Programmatically, however, the filters can be tuned flexibly using IAMStreamConfig::Format call:

  • Video:
    • Any resolution
    • 32-bit RGB, top-to-bottom only (the filter internally uses Direct2D/WIC to generate the images)
    • Any positive frame rate
    • Aspect ratio can be overridden using VIDEOINFOHEADER2 format, e.g. to force SD video to be 4:3
  • Audio:
    • Any sample rate
    • 16-bit PCM or 32-bit IEEE floating point format
    • Mono

Video filter generates image sequence with properties burnt in, with frame number, 100ns time, time with frame number within second, and a circle with a sector filled to reflect current sub-second time. There is Uh/Oh text inside the circle at sharp second times and the background color is in continuous transition between colors.

Audio filter beeps every second during the first 100 ms of a second, with a tone different for every fifth and every tenth second.

DirectShowReferenceSource fitlers running in GraphStudio

Both filters support IAMStreamControl interface, and IAMStreamControl::StopAt method in particular, which allows to limit signal duration and be used for time accurate file creation.

This comes with a sample project that demonstrates ASF file generation for specific properties and duration. Output file generated by the sample is Output.asf.

ASF file format and WM ASF Writer are chosen for code brevity and to reference stock multiplexer. This has a downside that multiplexer re-scales video to profile’s resolution and frame rate, of course. Those interested in generation of their own content would use something like their favorite H.264 and AAC encoders with MP4 or MKV multiplexer perhaps. And a nicer output would look like Output.mp4 then.

A good thing about publishing these filters is that while preparing test project, I hit a thread safety bug in GDCL MP4 multiplexer, which is presumably present in all/most version of the mp4mux.dll out there: if filter graph is stopped at the time of video streaming, before reaching end-of-stream on video leg (which is often the case because upstream connection would be H.264 encoder having internal queue of frames draining then on worker threads processing stop request), multiplexer might generate a memory access violation trying to use NULL track object, which is already gone.

Download links

 

CLSID_FilterGraphNoThread and IMediaEvent::WaitForCompletion

An interesting find about CLSID_FilterGraphNoThread version of DirectShow fitler graph implementation is that its WaitForCompletion method available through IMediaEvent and IMediaEventEx interfaces is not implemented: the immediately returned value is E_NOTIMPL.

CLSID_FilterGraphNoThread itself is not well documented and is rather a spin off the baseline implementation (which is – my guess would be – was introduced at some later stage and was necessary for windowless filter graphs running in worker threads; perhaps Windows Media Player team requested this at some point of WMP development):

… creates the Filter Graph Manager on the application’s thread. If you use this CLSID, the thread that calls CoCreateInstance must have a message loop that dispatches messages; otherwise, deadlocks can occur. Also, before the application thread exits, it must release the Filter Graph Manager and all graph objects (such as filters, pins, reference clocks, and so forth).

The filter graph does not have its internal worker window and is unable to wait for completion in its usual manner. Hence the error. Those who are using CLSID_FilterGraphNoThread version of the filter graphs are supposed to handle EC_COMPLETE events to detect the completion.

I suppose it is not intended and not even somehow foreseen behavior, but who uses CLSID_FilterGraphNoThread anyway except Windows Media Player and those who can cope with the problem.

IMediaObject::Discontinuity while Windows Media Video 9 Encoder has data to process

This is presumably a bug in Windows Media Video 9 Encoder in versions up to Windows 7 included (fixed in Windows 8.1 at the very least – wmvencod.dll 6.3.9600.17415).

A IMediaObject::Discontinuity call destroys input the DMO it already holds: it reports success, and handles discontinuity correctly. It even drains output as it should, but if in the same time it already has input to process – this input is gone and the typical outcome is that a frame (or possibly more?) in the end of the stream is trimmed away.

The call itself is legal and reports S_OK. The method should have returned DMO_E_NOTACCEPTING if it is too early to report discontinuity, and the DMO does not do it.

Good news it’s fixed in its most recent version and it is not a cold case.

GDCL MPEG-4 filters update

As mentioned recently in DirectShowSpy media sample trace update, I uploaded a fork of MPEG-4 filters developed by Geraint Davies, which includes a few updates made over time. They are worth mentioning in a separate post:

  • the projects received type libraries and it is easier to reference filters now by #importing the type library into your project, with class and interface definitions
  • added support for seeking to key frame, positioning loop without thread re-creation, ability to query for all frame times in the file including frame flags – all together this makes a base for playback with good scrubbing performance and user experience
  • fixed a few bugs (resulting file might be not playable in WMP, seeking esp. when scrubbing results in media samples set off by small amount of time, maybe other)
  • ability to affect multiplexer memory allocator and its properties
  • support for raw video formats, so that MP4 container could be used as a temporary storage for raw captured video (it’s a good choice because the container format is not bloated and has no file size constraints unlike e.g. AVI implementations)
  • ability to write a secondary helper temporary file to keep important data, which lets one fix broken capture sessions; an incomplete MP4 file is typically a piece of garbage but with this file it can be restored up to crash point (think of multi-hour recordings) – this needs to be elaborated and some time in future there could possibly be a tool that does the job
  • last but not least, DirectShowSpy integration; the code is easy to remove or disable because it is put inside #if defined(ALAXINFODIRECTSHOWSPY_AVAILABLE) sections; integration serves both as example of how to leverage DirectShowSpy media sample traces and also to provide pre-built filters with enabled tracing

Source

Range-based for with ATL Collections

ATL collection classes did not receive an update related to new C++11 range-based fors and other fancy features. Well it’s a pity because writing

for(auto&& pPin: AudioPinList)
  pPin-> //...

compared to

for(POSITION Position = AudioPinList.GetHeadPosition(); Position; AudioPinList.GetNext(Position))
{
  IPin* pPin = AudioPinList.GetAt(Position);
  pPin-> //...

is indeed a relief. Namespace std is, of course, good but ATL is still here as well. Here is a take on adding range-based for loops to ATL collection classes.

  • CRoIterativeCollectionT class is a traits-based uniform base for lists and arrays, adding (again, uniform) helpers to iterate through collection:
    • GetCountThat, GetThat, RemoveThat, RemoveFirst, RemoveLast
    • Find, FindThat, FindFirst, FindLast, FindFirstThat, FindLastThat
    • ForEach
    • begin, end implementing for range based for loops
  • CRoArrayT is a class extending CAtlArray, adding mentioned above through inheriting from CRoIterativeCollectionT
  • CRoListT is a class extending CAtlList, adding mentioned above through inheriting from CRoIterativeCollectionT
  • CRoAssignableListT, CRoAssignableArrayT, CRoAssignableMapT to inherit collections and allow assignment operators on those (through duplication of elements), esp. to be able to easily put the collections as members of classes, eligible for assignment operator copies
  • CRoFixedArrayT, CRoFixedMapT are compatible collection classes backed by stack memory only, no allocations (old stuff as is, was used somewhere in handler where immediate response assumed no memory allocation operations)
  • CRoMapT is essentially an thin extension of CAtlMap, however also adds GetPositions() and GetValues() methods, which can be used for range-based for loops

Download