Quantcast
Channel: Fooling Around
Viewing all 249 articles
Browse latest View live

Encoding H.264 video using hardware MFTs

$
0
0

Some time ago there were some pictures explaining performance and other properties of software H.264 encoder (x264). At this time, it is a turn of hardware H.264 encoders and more to that, two of them and side by side. Both encoders are nothing new: Intel® Quick Sync Video H.264 Encoder and NVIDIA H.264 Encoder already have been around for a while. Some would say it is already time for H.265 encoders.

Either way, on my test machine both encoders are available without additionally installed software (that is, no need for Intel Media SDK, Nvidia NVENC, redistributable files etc.). Out of the box, Windows 10 offers stock software only encoder, and hardware encoders in form factor of Media Foundation Transform (MFT).

Environment:

  • OS: Windows 10 Pro
  • CPU: Intel i7-4790
  • Video Adapter 1: Intel HD Graphics 4600 (on-board, not connected to monitors)
  • Video Adapter 2: NVIDIA GeForce GTX 750

It is not convenient or fun to do things with Media Foundation, but good news is that Media Foundation components are well-separable. A wrapper over MFT that converts them into DirectShow filters, make them available to DirectShow where it is already way easier to run various test runs. The pictures below show metrics for encoder defaults (bitrate, profiles and many other options that create a great deal of encoding modes). Still the pictures do show that both encoders are well usable for many scenarios including HD processing, simultaneous data processing etc.

Video Encoder MFT Wrapper in GraphStudioNext

Test runs are as simple as taking reference video source signal of different properties, pushing it through encoder filter and either writing to a file (to inspect the footage) or to Null Renderer Filter to measure performance.

Intel® Quick Sync Video H.264 Encoder produces files like these: 720×480.mp4, 2556×1440.mp4, which are of decent quality (with respect to low bitrate and “hard to handle” background changes). NVIDIA H.264 Encoder produces somewhat better output supposedly by choosing higher bitrate. Either way, both encoders have a number of ways to fine tune the encoding process. Not just bitrate, profile, GOP length, B frame settings but even more sophisticated parameters.

Intel® Quick Sync Video H.264 Encoder MFT

CODECAPI_AVEncCommonRateControlMode: VT_UI4 0, default VT_UI4 0, modifiable // eAVEncCommonRateControlMode_CBR = 0
CODECAPI_AVEncCommonQuality: minimal VT_UI4 0, maximal VT_EMPTY, step VT_EMPTY
CODECAPI_AVEncCommonBufferSize: VT_UI4 3131961357, default VT_UI4 0, modifiable
CODECAPI_AVEncCommonMaxBitRate: default VT_UI4 0
CODECAPI_AVEncCommonMeanBitRate: VT_UI4 3131961357, default VT_UI4 2222000, modifiable
CODECAPI_AVEncCommonQualityVsSpeed: VT_UI4 50, default VT_UI4 50, modifiable
CODECAPI_AVEncH264CABACEnable: modifiable
CODECAPI_AVEncMPVDefaultBPictureCount: VT_UI4 0, default VT_UI4 0, modifiable
CODECAPI_AVEncMPVGOPSize: VT_UI4 128, default VT_UI4 128, modifiable
CODECAPI_AVEncVideoEncodeQP: 
CODECAPI_AVEncVideoForceKeyFrame: VT_UI4 0, default VT_UI4 0, modifiable
CODECAPI_AVLowLatencyMode: VT_BOOL 0, default VT_BOOL 0, modifiable
CODECAPI_AVEncVideoLTRBufferControl: VT_UI4 65536, values { VT_UI4 65536, VT_UI4 65537, VT_UI4 65538, VT_UI4 65539, VT_UI4 65540, VT_UI4 65541, VT_UI4 65542, VT_UI4 65543, VT_UI4 65544, VT_UI4 65545, VT_UI4 65546, VT_UI4 65547, VT_UI4 65548, VT_UI4 65549, VT_UI4 65550, VT_UI4 65551, VT_UI4 65552 }, modifiable
CODECAPI_AVEncVideoMarkLTRFrame: 
CODECAPI_AVEncVideoUseLTRFrame: 
CODECAPI_AVEncVideoEncodeFrameTypeQP: default VT_UI8 111670853658, minimal VT_UI8 0, maximal VT_UI8 219046674483, step VT_UI8 1
CODECAPI_AVEncSliceControlMode: VT_UI4 0, default VT_UI4 2, minimal VT_UI4 2, maximal VT_UI4 2, step VT_UI4 0, modifiable
CODECAPI_AVEncSliceControlSize: VT_UI4 0, minimal VT_UI4 0, maximal VT_UI4 8160, step VT_UI4 1, modifiable
CODECAPI_AVEncVideoMaxNumRefFrame: minimal VT_UI4 0, maximal VT_UI4 16, step VT_UI4 1, modifiable
CODECAPI_AVEncVideoTemporalLayerCount: default VT_UI4 1, minimal VT_UI4 1, maximal VT_UI4 3, step VT_UI4 1, modifiable
CODECAPI_AVEncMPVDefaultBPictureCount: VT_UI4 0, default VT_UI4 0, modifiable

NVIDIA H.264 Encoder MFT

CODECAPI_AVEncCommonRateControlMode: VT_UI4 0
CODECAPI_AVEncCommonQuality: VT_UI4 65
CODECAPI_AVEncCommonBufferSize: VT_UI4 8923353
CODECAPI_AVEncCommonMaxBitRate: VT_UI4 8923353
CODECAPI_AVEncCommonMeanBitRate: VT_UI4 2974451
CODECAPI_AVEncCommonQualityVsSpeed: VT_UI4 33
CODECAPI_AVEncH264CABACEnable: VT_BOOL -1
CODECAPI_AVEncMPVGOPSize: VT_UI4 50
CODECAPI_AVEncVideoEncodeQP: VT_UI8 26
CODECAPI_AVEncVideoForceKeyFrame: 
CODECAPI_AVEncVideoMinQP: VT_UI4 0, minimal VT_UI4 0, maximal VT_UI4 51, step VT_UI4 1
CODECAPI_AVLowLatencyMode: VT_BOOL 0
CODECAPI_AVEncVideoLTRBufferControl: VT_UI4 0, values { VT_I4 65537, VT_I4 65538 }
CODECAPI_AVEncVideoMarkLTRFrame: 
CODECAPI_AVEncVideoUseLTRFrame: 
CODECAPI_AVEncVideoEncodeFrameTypeQP: VT_UI8 111670853658
CODECAPI_AVEncSliceControlMode: VT_UI4 2, minimal VT_UI4 0, maximal VT_UI4 2, step VT_UI4 1
CODECAPI_AVEncSliceControlSize: VT_UI4 0, minimal VT_UI4 0, maximal VT_UI4 3, step VT_UI4 1
CODECAPI_AVEncVideoMaxNumRefFrame: VT_UI4 1, minimal VT_UI4 0, maximal VT_UI4 16, step VT_UI4 1
CODECAPI_AVEncVideoMeanAbsoluteDifference: VT_UI4 0
CODECAPI_AVEncVideoMaxQP: VT_UI4 51, minimal VT_UI4 0, maximal VT_UI4 51, step VT_UI4 1
CODECAPI_AVEncVideoROIEnabled: VT_UI4 0
CODECAPI_AVEncVideoTemporalLayerCount: minimal VT_UI4 1, maximal VT_UI4 3, step VT_UI4 1

Important property of hardware encoder is that even that it does consume some of CPU time, the most of the complexity is offloaded to video hardware. In all single stream test runs, the eight-core CPU was loaded not more than 30% including time required to synthesize the image using WIC and Direct2D and convert it to YUV format using CPU. That is, offloading video encoding to GPU is a convenient way to free CPU for real time video processing applications.

I was mostly interested in how the encoders are in terms of being able to process real time data, esp. so that they are applied to record lengthy sessions. Both encoders appear to be fast enough to crack 1920×1080 HD video at frame rates up to 60 and higher. The test did encoding at highest rate possible and 100% number on the charts corresponds to situation that it took one second to synthesize and encode one second of video no matter what effective CPU/GPU load is. That is, values less than 100% indicate ability to encode video content in real time right away.

Intel and NVidia Hardware H.264 Encoders Side by Side

Basically, the numbers show that both encoders are fast enough to reliably encode 1080p60 stream.

Looking at it from another standpoint of being able to process two or more H.264 encoding sessions at once, encoder from NVidia has an important limitation of two sessions per system (supposedly related thread – for this or another reason test run with three streams fails).

Intel and NVidia H.264 Encoders in Concurrent Encoding

Both encoders are hardly suitable for reliable encoding of two 1080p60 streams simultaneously (or perhaps some fine tuning might make things faster by choosing appropriate encoding mode). However both look fine for encoding 1080p and lower resolution stream. Clearly, Intel’s encoder can be used to encoder multiple low resolution streams in parallel or mix real time encoding with background encoding (provided that background encoding is throttled to let the real time stream run fast enough). If otherwise real-time encoding is not necessary, both encoders can do the job as well, and with Nvidia the application needs to make sure that only two sessions are running simultaneously, Intel’s encoder can be used in a more flexible way.

Also, Nvidia’s encoder is slightly faster, however Intel’s allow 3+ concurrently encoded stream and also allows to supply RGB input directly without converting to YUV.

There is also Intel® Hardware H265 Encoder MFT available for H.265 encoding, but this is going to be another story some time later.


Follow up: mixed parallel H.264 encoding, Intel® Quick Sync Video H.264 Encoder MFT + NVIDIA H.264 Encoder MFT

$
0
0

A scenario which was dropped out from previous post is mixed simultaneous encoding using both hardware encoders. Rationale: Intel QSV encoder might exist as a “free” capability of the motherboard (provided with onboard video adapter), The other one might be available with the video adapter intentionally plugged in (including for other reasons, such as to power dual monitor system etc).

From this standpoint, it might be interesting if one can benefit from using of both encoders.

Intel QSV Filter Graph

Nvidia NVEVC Filter Graph

Two filter graphs are set to produce 60 seconds of 1080p60 video as soon as possible, and are started simultaneously. The chart below show completion time, side by side with those for runs of one and two sessions of each encoder separately.

Completion Times: Intel® Quick Sync Video H.264 Encoder MFT + NVIDIA H.264 Encoder MFT

Informational: in single stream runs CPU load was around 30%, two session runs – around 50%, of which the part that synthesizes and converts the video to compatible MFT input format took 5-6% of CPU time overall. Or, if computed against 60 seconds of CPU time of eight core CPU, the synthesis-and-conversion itself consumed <4% CPU time for one stream, and <7% for dual stream runs.

 

Fragile MFEnumDeviceSources

$
0
0

As I mentioned in earlier post, Media Foundation video capture capability is internally using undocumented categories with pretty much the same transforms and enumeration applicable to categories documented.

Without documenting it as public contract, MFEnumDeviceSources enumerates transforms, builds standard implementation for IMFMediaSource on top of available transform and… voila! Media Foundation offers “lightweight” API for video/audio capture. Lightweight presumably stands for “of substandard quality” here. It would be lightweight, if they documented the transforms, the enumeration API, make it extensible, decoupled their media source implementation from the transform, documented the internal communication between the two. However, it seems that there has been no progress in this direction since Windows 7.

The implementation is good in terms that it is implementing the documented promises, however if earlier APIs were developer friendly and well-extensible, here it is just minimal implementation without offering too much to people. Even though it could be extensible, it looks like Microsoft simply decided to not spend effort on pushing it to feature rich state, clean and open to developers.

A simple example: it is still possible to register your own transform into undocumented category. MFEnumDeviceSources implementation does see it, picks it up. Not a hardware transform? No go – we only offer media source functionality for hardware transform (actually for no apparent reason, other than possibly to put a stop to custom extensions). Hardware transform? No go – we cannot accept it for another reason, we only offer media source implementation for hardware transforms we “like”. The most confusing part is that rejection of unsupported transform might cause fatal failure in the enumeration loop: the rejection will make other, supported transforms and devices unavailable to applications. I suppose that once the loop encounters unsupported device, it simply forwards the failure upwards invalidating devices already found and yet to be enumerated. It is not the way the API should be developed, but it is okay – the category remains internal and undocumented.

DirectShowFileMediaSamples Update: Command Line Mode

$
0
0

It appears that the tool was never mentioned before (just mentioned in general software list). The application takes a media file on the input and applies respective DirectShow demultiplexer to list individual media samples.

DirectShowFileMediaSamples UI

  • for MP4 files the application attempts to use GDCL MPEG-4 Demultiplexer first
  • it is possible to filter a specific track/stream
  • ability to copy data to clipboard or save to file
  • drag and drop a file to get it processed

Now the tool has command line mode too:

DirectShowFileMediaSamples-Win32.exe input-path [/no-video] [/no-audio] [output-path]

  • /no-video – excludes video tracks
  • /no-audio – excludes audio tracks

Default output path is input path with extension renamed to .TSV. If DirectShowSpy is installed, the file also contains filter graph information used (esp. media types).

For example,

D:\>DirectShowFileMediaSamples-Win32.exe “F:\Media\Ленинград — Экспонат.mp4”

Typical command line use: troubleshooting export/transcoding sessions where on completion you need a textual information about the export to make sure time accuracy of individual samples: start, stop times, gaps etc.

Interactively one can also achieve the same goal using GraphStudioNext‘s built-in Analyzer Filter.

Download links

MediaFoundationVideoEncoderTransforms: Detecting support for hardware H.264 video encoders

$
0
0

H.264 (MPEG-4 Part 10 also known as MPEG-4 AVC) video encoding was never packaged into DirectShow filter by Microsoft and instead they offered Media Foundation Transform (MFT) for the job: H.264 Video Encoder. Further development gave us third party video encoders also packaged as MFTs. Hardware backed MFTs became a part of video hardware drivers and nevertheless are part of Media Foundation API, can also be very well used standalone.

Detection of H.264 encoding capabilities? MediaFoundationVideoEncoderTransforms is here to help.

MediaFoundationVideoEncoderTransforms UI

H.264 options include:

  • H264 Encoder MFT
  • Intel® Quick Sync Video H.264 Encoder MFT
  • NVIDIA H.264 Encoder MFT
  • AMDh264Encoder

H.265 encoding will apparently be (already is) using the same encoder packaging.

The tools enumerates the transforms and provides details, similar to Enumerating Media Foundation Transforms (MFTs) application (source code available).

# System

[…]

# Display Devices <<– Same as in Device Manager

* AMD Radeon R7 200 Series
* Instance: PCI\VEN_1002&DEV_6610&SUBSYS_22BF1458&REV_00\4&2DB3ECDA&0&0008
* DEVPKEY_Device_Manufacturer: Advanced Micro Devices, Inc.
* DEVPKEY_Device_DriverVersion: 15.201.1151.1008
* Intel(R) HD Graphics 530 <<– Video adapter Intel QSV is available through (if you don’t see Intel video, then maybe it needs to be turned on in BIOS)
* Instance: PCI\VEN_8086&DEV_1912&SUBSYS_D0001458&REV_06\3&11583659&0&10
* DEVPKEY_Device_Manufacturer: Intel Corporation
* DEVPKEY_Device_DriverVersion: 20.19.15.4331

# Category `MFT_CATEGORY_VIDEO_ENCODER`

NOTE: Detail is limited to H.264 video encoders.

## Intel® Quick Sync Video H.264 Encoder MFT <<– The guy that does Intel QSV encoding

[…]

## H264 Encoder MFT <<– Stock Microsoft software H.264 implementation, available since Windows 7

[…]

(Other encoders like those from AMD, Nvidia will also be listed)

## Intel® Hardware H265 Encoder MFT <<– Intel also provides now H.265 hardware encoding option

[…]

## H265 Encoder MFT

[…]

Download links

ManifestComDependency: Adding/Removing Registration-Free COM dependencies

$
0
0

In one of the earlier posts I mentioned a problem with registration-free COM dependency setup up by Visual Studio as a part of build process. This post is about the tool that offers an alternate solution for the problems, and also gives more:

  • standalone, independent from build, addition/removal registration-free COM links
  • automation of registration-free COM links for native code builds

Unless one deals with ACTCTX activation contexts programmatically, taking advantage of registration-free COM is essentially a setup of respective side-by-side manifests, either standalone or embedded into executable. The manifests override standard global COM object lookup procedure and point to COM servers directly, in some way similar to the way static links to exported DLL functions work.

To enable, registration-free COM reference COM client needs to prepare respective manifest file (declare an assembly) and list its COM dependencies. The COM dependency list is not just COM server files but rather their COM classes and type libraries. That is, when it comes to automation, the tool needs to go over the COM servers and extract respective identifiers, so that it could properly shape this information and include into manifest XML.

To deal with the challenge, I am using ManifestComDependency tool (no better came to mind when it was created). The command line tool syntax is the following:

 ManifestComDependency <path> [options]
 
 Options:
  * /i[:<assembly-name>] - updates <assemblyIdentity> element replacing it with automatically generated
  * /a[:tc] <dependency-path>[|LIBID[;X.Y]] - adds file <dependency-path> dependency, optionally without type library and COM classes reference
  * /r <dependency-path> - removes dependency from file <dependency-path>
  * /e <export-path> - exports manifest to file <export-path>

The tool opens a file <path> for manifest modification. The file can be a binary file, such as .exe or .dll, in which case the tool will be working with embedded manifest resource. Or, if the path extension is .manifest or .xml, then the file is treated as standalone XML manifest file. Both options are good for manifests associated with .NET builds as well, even though this surely does not need to be managed code development – native COM consumers are okay.

/i option updates <assemblyIdentity> element in the manifest data because it is mandatory and in the same time it might so happen that it is missing or incomplete, which ends up in painful troubleshooting. The tool will name file name, architecture and version information from the binary resource information (product version; the VERSIONINFO resource has to be present).

ManifestComDependency Output

/a option adds a dependency, defined by either path or registered type library identifier the tool would use to resolve the path. t and c modifiers exclude type library and COM server information respectively. The tool created a file element for the dependency and populates it with COM servers discovered there. Type library is obtained using LoadTypeLib API and COM servers are picked up by a trick with RegOverridePredefKey and friends (e.g. see example in regsvr42 source or GraphStudioNext source – both are excellent sources of code snippets for the curious).

The task of COM server discovery assumes load of the library into process (LoadLibrary API call), which assumes bitness match between the tool and the loaded module. This is where you need both Win32 and x64 builds of the tool: if wrong bitness is detected, the tool restarts its sister build passing respective command line arguments, just like regsvr32 does with the only difference that regsvr32 uses binaries in system32 and syswow64 directories, and my tool looks for -Win32 and -x64 suffixes and the files in the same directory.

/r option removes dependencies by name. It is safe to remove certain dependency before adding it back because addition does not check if dependency already exists.

/e option writes the current version of the manifest in external file, esp. for review and troubleshooting if the actual manifest is embedded.

The order of options is important because they are executed one by one in the order of appearance. Then the result is saved/re-embedded once all tasks are done.

Command line example of re-adding registration-free COM dependencies:

ManifestComDependency-x64.exe BatchExport-x64.exe /i /r Player.dll /r mp4demux.dll /a Player.dll /a mp4demux.dll

This can be set as post-build event in the project settings, or put into batch file or run on-demand.

Download links

Making development fun

FFmpeg error LNK2019: unresolved external symbol ff_reshuffle_raw_rgb…

$
0
0

Building a slim version of FFmpeg (specifically: MOV muxer without AVI muxer) from latest source, an error around ff_reshuffle_raw_rgb is breaking the build:

movenc.o : error LNK2019: unresolved external symbol ff_reshuffle_raw_rgb referenced in function mov_write_packet
libavformat/avformat-v-57.dll : fatal error LNK1120: 1 unresolved externals
library.mak:111: recipe for target 'libavformat/avformat-v-57.dll' failed
make: *** [libavformat/avformat-v-57.dll] Error 96

Not a big a deal, it is just  a small bug there:

 libavformat/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/Makefile b/libavformat/Makefile
index 3b32907..6ae4327 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -268,7 +268,7 @@ OBJS-$(CONFIG_MMF_DEMUXER)               += mmf.o
 OBJS-$(CONFIG_MMF_MUXER)                 += mmf.o rawenc.o
 OBJS-$(CONFIG_MOV_DEMUXER)               += mov.o mov_chan.o replaygain.o
 OBJS-$(CONFIG_MOV_MUXER)                 += movenc.o avc.o hevc.o \
-                                            movenchint.o mov_chan.o rtp.o movenccenc.o
+                                            movenchint.o mov_chan.o rtp.o movenccenc.o rawutils.o
 OBJS-$(CONFIG_MP2_MUXER)                 += mp3enc.o rawenc.o id3v2enc.o
 OBJS-$(CONFIG_MP3_DEMUXER)               += mp3dec.o replaygain.o
 OBJS-$(CONFIG_MP3_MUXER)                 += mp3enc.o rawenc.o id3v2enc.o

Certificate Enrollment API Adventures

$
0
0

IX509PrivateKey::Export exports key data from COM object, MSDN:

strExportType [in]

A BSTR value that specifies how the private key is exported.

If the key was created by using a CNG KSP (Key Storage Provider), you can specify one of the values allowed by the pszBlobType parameter in the NCryptExportKey function.

If the key was created by using a CryptoAPI CSP (Cryptographic Service Provider), you can specify one of the following values from the Bcrypt.h header file included with Wincrypt.h.
BCRYPT_PUBLIC_KEY_BLOB – Exports only the public portion of the private key.
BCRYPT_
PRIVATE_KEY_BLOB – Exports the entire private key.

Well this is actually accurate, however trying to make it…

CComPtr<IX509PrivateKey> pPrivateKey;
// ...
CComBSTR sPublicKeyBlob, sPrivateKeyBlob;
ATLENSURE_SUCCEEDED(pPrivateKey->Export(BCRYPT_PUBLIC_KEY_BLOB, XCN_CRYPT_STRING_BASE64, &sPublicKeyBlob));
ATLENSURE_SUCCEEDED(pPrivateKey->Export(BCRYPT_PRIVATE_KEY_BLOB, XCN_CRYPT_STRING_BASE64, &sPrivateKeyBlob));

… the both calls result in E_POINTER (0x80004003). The first argument is not just LPCWSTR. It has to be BSTR and the API is checking the length of the value using SysStringLen. One has to wrap the argument to provide it as BSTR:

CComPtr<IX509PrivateKey> pPrivateKey;
// ...
CComBSTR sPublicKeyBlob, sPrivateKeyBlob;
ATLENSURE_SUCCEEDED(pPrivateKey->Export(CComBSTR(BCRYPT_PUBLIC_KEY_BLOB), XCN_CRYPT_STRING_BASE64, &sPublicKeyBlob));
ATLENSURE_SUCCEEDED(pPrivateKey->Export(CComBSTR(BCRYPT_PRIVATE_KEY_BLOB), XCN_CRYPT_STRING_BASE64, &sPrivateKeyBlob));

Another problem is related to IObjectId::InitializeFromAlgorithmName.

strAlgorithmName [in]

A BSTR variable that contains the name. You can specify a name, or an OID in dotted decimal format. The method verifies that the format is consistent with the ASN.1 X.208 standard. For more information about CNG algorithm names, see CNG Algorithm Identifiers.

MSDN offers choices to provide a string or OID. Unfortunately, OID does not work and fails on internal argument validation with E_INVALIDARG (0x80070057).

ATLENSURE_SUCCEEDED(pObjectId->InitializeFromAlgorithmName(XCN_CRYPT_HASH_ALG_OID_GROUP_ID, 
    XCN_CRYPT_OID_INFO_PUBKEY_ANY, AlgorithmFlagsNone, 
        CComBSTR(L"SHA256"))); //CComBSTR(szOID_RSA_SHA256RSA)));

Calling convention violator broke streaming loop pretty far away

$
0
0

A really nasty problem coming from MainConcept AVC/H.264 SDK Encoder was destroying media streaming pipeline. SDK is somewhat old (9.7.9.5738) and the problem might be already fixed, or might be not. The problem is a good example of how a small bug could become a big pain.

The problem was coming up in 64-bit Release builds only. Win32 build? OK. Debug build where you can step things through? No problem.

The bug materialized in GDCL MP4 Demultiplexer filter streaming (Demultiplexer filter in the pipeline below) generating media samples with incorrect time stamps.

Pipeline

Initial start and stop time are okay, and further go as _I64_MIN (incorrect).

Clipbrd3

The problem appears to be SSE optimization and x64 calling convention related. This explains why it’s only 64-bit Release build suffering from the issue. MS compiler decided to use XMM7 register for dRate variable in this code fragment:

REFERENCE_TIME tStart, tStop;
double dRate;
m_pParser->GetSeekingParams(&tStart, &tStop, &dRate);

[...]

for(; ; )
{
    [...]

    tSampleStart = REFERENCE_TIME(tSampleStart / dRate);
    tSampleEnd = REFERENCE_TIME(tSampleEnd / dRate);

dRate is the only floating point thing here and it’s clear why the compiler optimized the variable into register: no other floating point activity around.

However sample delivery goes pretty deep into other functions and modules reaching MainConcept H.264 encoder. One of its functions is violating x64 calling convention and does not preserve XMM6+ register values. OOPS! Everything is about working right, but after media sample delivery dRate value is destroyed and further media samples receive incorrect time stamps.

It is not really a problem of MP4 demultiplexer, of course, however media sample delivery might involve a long delivery chain where any violator would break streaming loop. In the same time, it is not really a big expense to de-optimize the floating point math in the demultiplexer for those a few time stamp adjustment operations. A volatile specifier breaks compiler optimization and makes the loop resistant to SSE2 register violators:

// HOTFIX: Volatile specifier is not really necessary here but it fixes a nasty problem with MainConcept AVC SDK violating x64 calling convention;
//         MS compiler might choose to keep dRate in XMM6 register and the value would be destroyed by the violating call leading to incorrect 
//         further streaming (wrong time stamps)
volatile DOUBLE dRate;
m_pParser->GetSeekingParams(&tStart, &tStop, (DOUBLE*) &dRate);

This makes H.264 this build of encoding SDK unstable and the problem is hopefully already fixed. The SDK indeed gave other troubles on specific architectures leading to undefined behavior.

How to create Virtual Webcam in Windows 10?

$
0
0

(this is a re-post from StackOverflow)

Virtual webcam is typically a software only implementation that application discover as if it is a device with physical representation. The mentioned applications use APIs to work with web cameras and ability to extend the APIs and add your own video source is the way to create a virtual web camera.

In Windows there are a few APIs to consume video sources: Video for Windows, DirectShow, Media Foundation (in chronological order).

Video for Windows is not really extensible and limited in capabilities overall. It will see a virtual device if you provide a kernel mode driver for a virtual camera.

DirectShow is the API used by most video capture enabled Windows applications and it is present in all Windows versions including Windows 10 (except just Windows RT). Then it’s perfectly extensible and in most cases the term “virtual webcam” refers to DirectShow virtual webcam. Methods to create DirectShow virtual webcam discussed in many StackOverflow questions remain perfectly valid for Windows 10, for applications that implement video capture using DirectShow:

DirectShow samples were removed from Windows SDK but you can still find them in older releases:

If you provide a kernel mode driver for video camera device (your virtual webcam through custom kernel driver), DirectShow would also see it just like other video APIs.

Media Foundation is a supposed successor of DirectShow but its video capture capabilities in the part of extensibility simply do not exist. Microsoft decided to not allow custom video sources application would be able to discover the same way as web cameras. Due to Media Foundation complexity, and overhead and overall unfriendliness it is used by modest amount of applications. To implement a virtual webcam for Media Foundation application you again, like in case of Video for Windows, have to implement a kernel mode driver.

Utility Clearance: Matrox DSX SDK Capabilities

$
0
0

The tool gathers and formats capture capabilities of hardware accessible via Matrox DSX SDK:

Matrox DSX SDK is a feature-rich development toolkit that enables Matrox’s industry-leading DSX hardware capabilities. OEMs use this hardware and software to build complete solutions that ensure 24/7 on-air reliability in a broadcast environment. Matrox DSX SDK customers have access to unlimited premium support from experienced applications engineers, personalized training courses, design review programs, and feature-customization to meet their specific needs.

Specifically, I used it a lot (X.AVCio, MXO2 series and other) to identify inputs, their properties, genlock, auto-detection of video signal.

System

[…]

Matrox DSX API

DS.X AVCio

  • sHardwareProfileInfo.eHardwareProfileType: 27 DS.XAVCio
  • sHardwareProfileInfo.ulHardwareProfileIndex: 0
  • sHardwareProfileInfo.wszHardwareProfileName: DS.X AVCio
  • bIsAvailable: 1
  • iXLinkID: -1
  • iXLinkHDID: -1
  • eHardwareSerie: 41 kEMvHardwareSerieDSXAVCio

IMvInputOutputIndependent Interface

  • Video Capture Devices: 1
  • Video Playback Devices: 2
  • Audio Capture Devices: 3
  • Audio Playback Devices: 4
  • I/O Devices: 1
  • Audio VoiceOver Mixer Devices: 0
  • Supported Genlock Sources: keGenlockSourceInternal | keGenlockSourceSDIVideo | keGenlockSourceAnalogVideo | keGenlockSourceDVIVideo

I/O Device: AVCio Card

  • Description: AVCio Card
  • Identifier: keIODeviceIDDSXAVCio
  • Miscellaneous:
    • eIODeviceID: keIODeviceIDDSXAVCio
    • szIODeviceName: AVCio Card
    • szIODeviceOption:
    • eSupportedVideoInputChannels: 1
    • eSupportedVideoOutputChannels: 3
    • eSupportedAudioCaptureChannels: 1
    • eSupportedAudioPlaybackChannels: 1
    • eSupportedEAInputChannels: 0
    • eSupportedEAOutputChannels: 0
    • eSupportedAnalogAudioInputChannels: 3
    • eSupportedAnalogAudioOutputChannels: 3
    • eSupportedAesEbuInputChannels: 0
    • eSupportedAesEbuOutputChannels: 0
    • eSupportedHdmiAudioInputChannels: 0
    • eSupportedHdmiAudioOutputChannels: 0

Genlock

Default Resolution:

  • Width and Height: 720 x 486
  • Bit Depth: 8 bits/component
  • Aspect Ratio: 4:3
  • Frame Rate: 29.97
  • Scan Mode: Second field top line

Current Resolution:

  • Width and Height: 1920 x 1080
  • Bit Depth: 8 bits/component
  • Aspect Ratio: 16:9
  • Frame Rate: 59.94
  • Scan Mode: Progressive

Information:

  • Supported Sources: keGenlockSourceInternal | keGenlockSourceSDIVideo | keGenlockSourceAnalogVideo | keGenlockSourceDVIVideo

Status:

  • Source: keGenlockSourceDVIVideo
  • State: keGenlockStateLocked

Video Capture Channel 0x01

Default Resolution:

  • Width and Height: 720 x 486
  • Bit Depth: 8 bits/component
  • Aspect Ratio: 4:3
  • Frame Rate: 29.97
  • Scan Mode: Second field top line

Current Resolution:

  • Width and Height: 1920 x 1080
  • Bit Depth: 8 bits/component
  • Aspect Ratio: 16:9
  • Frame Rate: 59.94
  • Scan Mode: Progressive

Information:

  • Supported Input Signals: keVideoSignalComposite | keVideoSignalSVideo | keVideoSignalSDI | keVideoSignalDVI
  • Supported Output Signals: keVideoSignalComposite | keVideoSignalSVideo | keVideoSignalSDI | keVideoSignalDVI

Source:

  • Video Signal: Default keVideoSignalComposite, Current keVideoSignalDVI

Status:

  • Selected Signal: keVideoSignalDVI
  • Video Present: 1
  • Input Resolution Mismatch: 0
  • Copy Protected: 0

Input Resolution:

  • Width and Height: 1920 x 1080
  • Bit Depth: 8 bits/component
  • Aspect Ratio: 16:9
  • Frame Rate: 59.94
  • Scan Mode: Progressive

Output Resolution:

  • Width and Height: 1920 x 1080
  • Bit Depth: 8 bits/component
  • Aspect Ratio: 16:9
  • Frame Rate: 59.94
  • Scan Mode: Progressive
  • Auto-Detect Input Valid: 1

Auto-Detect Input Resolution:

  • Width and Height: 1920 x 1080
  • Bit Depth: 10 bits/component
  • Aspect Ratio: 16:9
  • Frame Rate: 59.94
  • Scan Mode: Progressive
Video Input Parameters

[…]

Download links

Signing with CryptoAPI using Certificate and Detached Private Key

$
0
0

Use of separated certificate and private key might be confusing without understanding how parts or CryptoAPI are related one to another. Apparently, CryptSignMessage and friends require private key in order to create a digital signature.

It is not a problem when private key resides right in the signing certificate (such as, for example, imported with PFXImportCertStore):

CRYPT_SIGN_MESSAGE_PARA Parameters;
ZeroMemory(&Parameters, sizeof Parameters);
Parameters.cbSize = sizeof Parameters;
Parameters.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
Parameters.pSigningCert = CertificateContext; // <<--- Certificate with Private Key
// ...

Things get more complicated when the certificate does not contain the private key. API’s error is CRYPT_E_NO_KEY_PROPERTY which is described as follows:

“The pSigningCert in *pSignPara does not have a CERT_KEY_PROV_INFO_PROP_ID or CERT_KEY_CONTEXT_PROP_ID property.”

CERT_KEY_PROV_INFO_PROP_ID is a property to be defined with certificate context and it expects a structure of type CRYPT_KEY_PROV_INFO. The other one, CERT_KEY_CONTEXT_PROP_ID takes a CERT_KEY_CONTEXT structure.

Even though described as “The CRYPT_KEY_PROV_INFO structure contains information about a key container within a cryptographic service provider (CSP).” and “The CERT_KEY_CONTEXT structure contains data associated with a CERT_KEY_CONTEXT_PROP_ID property.” respectively, it is not well clear to see where the key is attached exactly.

The missing part is that the private key is not something to be provided explicitly. Instead, the key is to be pre-loaded into provider and then this provider is associated with CERT_KEY_CONTEXT structure, which goes as a property value, which in turn is added to signing certificate context, whcih finally gets used for creating a digital signature.

__E(CryptStringToBinary(sPrivateKeyBlob, (DWORD) wcslen(sPrivateKeyBlob), CRYPT_STRING_BASE64_ANY, pnData, &nDataSize, NULL, NULL));
// ...
CCryptProvider Provider;
__E(Provider.AcquireContext(NULL, NULL, PROV_RSA_FULL, 0));
CCryptKey Key;
Key.Attach(Provider.ImportKey(pnData, nDataSize));
__E(Key);
// ...
CERT_KEY_CONTEXT KeyContext;
ZeroMemory(&KeyContext, sizeof KeyContext);
KeyContext.cbSize = sizeof KeyContext;
KeyContext.hCryptProv = Provider; // <<--- Here we go, ooh
KeyContext.dwKeySpec = AT_SIGNATURE;
CertificateContext.SetProperty(CERT_KEY_CONTEXT_PROP_ID, &KeyContext);

“… you will never get the same high quality video experience that you find with DirectShow”

$
0
0

Microsoft’s James Daily wrote back in 2011 (and it’s an incredible response in the public forum from MS guy – provided that DirectShow branch of the same forum did not see anything close for 10+ years) about how technologies relate one to another:

Hey, I’m the team’s DShow expert. Trevor asked me to take a look at your post and give my two cents. From looking at the DShow code that you are using in your winforms application I just want you to be aware that by including quartz.dll as a dependency you are using the DirectShow 8 OLE automation objects. These objects have been deprecated for years and are certainly not recommended [this might perhaps be not accurate enough because generally stuff in quartz.dll is not deprecated, it’s rather orphaned and yet waits it deprecation like related stuff from qedit.dll; however the overall attitude is about right – RR]. At this time Microsoft does not have a supported solution for calling DirectShow code from C# (or any managed language). Please see the “note” at the top of the page at the link below for documented confirmation of this. Because the technology is not supported from the winforms environment it is not possible for us to suggest a supported workaround from managed code.

That said it should be possible to facilitate the functionality that you are looking for by creating a custom EVR presenter. By using a custom presenter you can get direct access to the D3D surface. You can then use the standard D3D constructs to draw directly to the same D3D surface that the EVR is using to blit the video. There are two things to keep in mind about this solution. First you must code this solution in unmanaged C++. Again this is due to the fact that DirectShow is not supported from managed code. Second, this solution is extremely complex and difficult to implement even for the most experienced DirectShow / D3D expert. Because of these two factors it is recommended that you take a serious look at the MediaElement in WPF.

As you know the WPF environment is constructed from the ground up to offer developers a very rich “graphics first” environment. The MediaElement in particular was designed to allow you to mix video with various other UI components seamlessly. This solution will give you the flicker free, “draw over video” solution that you are looking for. The best part is you can do all of this in C#. The bad part of this solution is that the MediaElement is not designed for displaying time sensitive media content. In other words, the MediaElement is notorious for dropping and delaying the display of video frames. There are ways to minimize this such as using SD rather than HD content, use a video accelerated codec, etc. However, you will never get the same high quality video experience that you find with DirectShow.

I hope this will help you understand the current shortcomings of the technologies that you have chosen and help you to focus your efforts on a fully supported and viable solution. If you need any additional clarification please let us know.

and then also:

Unfortunately you can’t really tell the WPF MediaElement to never drop frames. The term we use for this class of issues is “disparate clocks”. In this case WPF is updating the screen at a certain rate (clock 1). The MediaElement (based on WMP) is cranking out video frames at a slightly different rate (clock 2). Given the underlying technologies there is currently no way to synchronize the two clocks and force them to “tick” at the same rate. Since the display will only be updated according to the WPF clock, multiple frames of video may be sent from the MediaElement to WPF between clock ticks. Because of this the MediaElement may appear to drop frames. This is a very common problem in multimedia development and there is no simple solution.

So if you absolutely need frame accuracy in your application then using the MediaElement probably won’t work for you. That said, there are some things that you can do to improve the chances of your content dropping as few frames as possible. Modify your content so that it uses either the h.264 or VC1 codec. Require your users to have modern video HW capable of advanced video acceleration. Use the MPEG 4 or ASF file container. When encoding your content set your frame rate at or below 25 frames per second. Set the resolution of your content to something like 720×480. Set the bitrate to VBR constrained and set an upper limit of between 500 Kbps and 2.5 Mbps.

If you use the guidelines above you will minimize the number of frames that get dropped but you will never be able to completely eliminate them. Also keep in mind that the same frames may not be dropped. For example: if you play video1.asf the first time you might drop frames 200 and 375. On the next run of the same file you may drop frames 143, 678 and 901. This is due to the relatively nondeterministic nature of the Windows OS.

I hope this helps.

Another commenter responded rather angrily:

…fail to include any mention of the DirectShow.NET library. Why? And shame on them for failing to do so. This library helps you use DirectShow in a managed context. There are plenty of code samples to be found….

The answer to this, however, was given in the same thread above a couple of times and explains that the responses are limited by existing policy:

I cannot comment on 3rd party libraries.

Because the technology is not supported from the winforms environment it is not possible for us to suggest a supported workaround…

Video for Windows API and Multiple Cameras

$
0
0

A StackOverflow question (already deleted) asked about use of indices when referencing Video for Windows (VFW) capture devices such as in capGetDriverDescription API and other. Video capture with Video for Windows allowed use of up to 10 devices (did anyone have that many at that time?). The numbering was API specific and at the latest stage the documentation described it as:

Plug-and-Play capture drivers are enumerated first, followed by capture drivers listed in the registry, which are then followed by capture drivers listed in SYSTEM.INI.

Even though it is a legacy API, and the API was really really simple and limited in capabilities, it still exists in all Windows versions, there is still some code running, and due to complexity of modern APIs some people still use it in VB.NET and C# projects.

There is, however, a trap involved if someone attempts to use multiple cameras using VFW. VFW drivers are no longer developed since… Let us see what VirtualDub says about dates and how ancient they are:

The newer type of video capture driver in Windows uses the Windows Driver Model (WDM), which was introduced in Windows 98 and 2000. The Microsoft DirectShow API is the primary API to use these drivers. Because the DirectShow API supports a larger variety of commands and settings than VFW, the functionality set of a WDM driver is significantly improved.

DirectShow is a much more complex API than VFW, however, and WDM-model drivers historically have been a lot less stable than their VFW counterparts. It is not unusual to see problems such as capture applications that cannot be closed, because their program execution is stuck in the capture driver. WDM is the proscribed driver model going forward, however, so the situation should improve over time.

All new drivers were WDM drivers for 15+ years. In order to provide backward compatibility later between VFW and WDM, Microsoft came out with Microsoft WDM Image Capture (Win32) driver. Windows versions up to Windows 10 include it, and it is the only VFW driver in the system. In turn, it manages one of existing WDM-driver devices of choice and exposes video capture functionality to VFW applications. If there are two or more WDM drivers, the VFW driver offers to choose between the devices.

VFW Capture Source Dialog

The screenshot displays a long standing bug with this driver: it offers choices of all registered DirectShow video capture devices (it enumerates CLSID_VideoInputDeviceCategory category) and reality is that it can only work with WDM devices and not other (more on this below).

VirtualDub has a mention of this driver as well:

If you have a Windows Driver Model (WDM) driver installed, you may also have an entry in the device list called Microsoft WDM Image Capture (Win32) (VFW). This entry comes from a Microsoft driver called VFWWDM32 and is a wrapper that allows WDM-model drivers to be used through the older Video for Windows (VFW) API. The WDM driver that is adapted can be selected through the Video Source driver dialog.

There are unfortunately some quirks in the way this adapter works, and some video capture devices will work erratically or not at all through this wrapper. Device settings not accessible through VFW will also still not be available when using it. If possible, use the capture device directly in DirectShow mode rather than using the VFWWDM32 driver.

This is works pretty nice with VFW API and applications. Even though the are all ancient and deprecated years ago, the system still has bridge to newer devices and applications can leverage their functionality. The problem is that there is only one VFW driver, and its index is zero. If you need two cameras you’re busted.

VFWWDM32 itself does not use any system exclusive resources and there is no reason why its different instances could not be configured with different WDM devices. However, VFWWDM32 is a simple old wrapper, either thread unsafe or such as implemented as singleton. People complain the operation with two cameras is impossible or unstable. It is still possible to run two different processes (such as, for example, VirtualDub) with two completely different VFWWDM32’s which do not interfere because of process boundary and run fine. WDM device is selected using capDlgVideoSource interactively, developers had hard time to do selection programmatically.

The interesting part is how VFWWDM32 does video capture using WDM. It is a cut corner in development: instead of doing simple DriectShow graph with Source –> Renderer, or Source –> Sample Grabber -> Renderer topology, where the wrapper would easily support all DriectShow video devices, including virtual, they decided to implement it this way:

VFWWDM Filter Graph

One filter graph, where the filter is the WDM Video Capture Filter for device in question.

  • the graph is CLSID_FilterGraphPrivateThread type, FINALLY it is found what this undocumented flavor of DirectShow fitler graph is used for
  • source filter output pins are not terminated, not connected to anything else
  • the graph is never run

Instead, VFWWDM32 uses some private undocumented communication to the WDM filter internals to run the device and receive frames.

Bottom line: VFW is a backward compatibility layer now on top DirectShow. DirectShow and Media Foundation both use WDM drivers to access video capture devices. Artificial constrain caused by simplistic implementation of VFWWDM driver is a limit of one video camera per process at a time.


MSDN Forums – HTTP Error 400

$
0
0

“Bad Request – Request Too Long” with https://social.msdn.microsoft.com/Forums

MSDN HTTP 400 Error

Somehow they piled up cookie data as long as 16 KB and they stopped accepting that as a HTTP header… Cleanup of browser cookies for MS sites resolves the access problem.

Microsoft Developer Web Service Day

DirectShowSpy: Automated Media Sample Traces, Load Trace from File

$
0
0

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

DirectShowSpy: REGDB_E_CLASSNOTREG with IMMDevice::Activate

$
0
0

A DirectShow developer complained on sudden failure of Core Audio IMMDevice::Activate call supposed to instantiate a DirectShow filter for a given device.

The problem appeared to be related to installed DirectShowSpy and its interference with the API calls. The symptom was of the following kind: when Activate was called for different types of objects, the calls all succeeded except interoperation with DirectShow (activation for IBaseFilter), e.g. EnumerateAudioDevices output:

    IAudioClient            0x00000000
    IAudioEndpointVolume    0x00000000
    IAudioMeterInformation  0x00000000
    IAudioSessionManager    0x00000000
    IAudioSessionManager2   0x00000000
    IBaseFilter             REGDB_E_CLASSNOTREG
    IDeviceTopology         0x00000000
    IMFTrustedOutput        0x00000000

When Core Audio is requested to do DirectShow activation, the API creates and instance of System Device Enumerator, which is forwarded the activation call to. DirectShowSpy intercepts these calls, however what it did not do was support for unknown COM interfaces, and support for undocumented IMMDeviceActivator interface which is used internally by the APIs to forward the activation call.

So, System Device Enumerator implements documented ICreateDevEnum and then it also implements undocumented internal IMMDeviceActivator. The entire sequence call is as follows:

// Top level code:

CComPtr<IMMDevice> pDevice = ...; // Audio endpoint interface
pDevice->Activate(..., __uuidof(IBaseFilter), ...)

// API:

STDMETHOD(Activate)(...)
{
    // ...
    if(requested is IBaseFilter)
    {
        CComPtr<IMMDeviceActivator> pDeviceActivator;
        pDeviceActivator.CoCreateInstace(CLSID_SystemDeviceEnum);
        return pDeviceActivator->Activate(pDevice, ...)
    }

DirectShowSpy’s failure to provide IMMDeviceActivator resulted in symptom in question and is fixed with version 1.0.0.2106 and on. The failure code is not so much descriptive, but of course the APIs did not expect external hook and failure is not actually a supposed possible behavior there.

System Device Enumerator matches the known devices to the provided Core Audio device and creates an instance of respective filter – this is how APIs work together. DirectShowSpy prints these calls out to its log.

roatlbase.h(1582): TraceModuleVersion: "D:\...\DirectShowSpy-Win32.dll" version is 1.0.0.2107, running in "D:\...\EnumerateAudioDevices-Win32.exe" at 0x63210000
dllmain.h(36): CDirectShowSpyModule::CDirectShowSpyModule: this 0x633963A4
SystemDeviceEnumeratorSpy.h(669): CSystemDeviceEnumeratorSpyT<...>::CSystemDeviceEnumeratorSpyT: this 0x02F1DA68
SystemDeviceEnumeratorSpy.h(681): CSystemDeviceEnumeratorSpyT<...>::FinalConstruct: pszPath "D:\...\EnumerateAudioDevices-Win32.exe", this 0x02F1DA68, m_dwRef 1
SystemDeviceEnumeratorSpy.h(49): CSystemDeviceEnumeratorSpyT<...>::InternalQueryInterface: 0x02F1DA68, Interface {3B0D0EA4-D0A9-4B0E-935B-09516746FAC0}, Result 0x00000000
SystemDeviceEnumeratorSpy.h(49): CSystemDeviceEnumeratorSpyT<...>::InternalQueryInterface: 0x02F1DA68, Interface {3B0D0EA4-D0A9-4B0E-935B-09516746FAC0}, Result 0x00000000
SystemDeviceEnumeratorSpy.h(808): CSystemDeviceEnumeratorSpyT<...>::Activate: this 0x02F1DA68, InterfaceIdentifier {56A86895-0AD4-11CE-B03A-0020AF0BA770}, pMmDevice 0x0054E7F8
SystemDeviceEnumeratorSpy.h(815): CSystemDeviceEnumeratorSpyT<...>::Activate: nActivateResult 0x00000000 
SystemDeviceEnumeratorSpy.h(673): CSystemDeviceEnumeratorSpyT<...>::~CSystemDeviceEnumeratorSpyT: this 0x02F1DA68

Download links

DirectShowSpy: Restore default system behavior

$
0
0

There was a problem reported for registered and relocated DirectShowSpy, which might be causing issues: Deleting faulty DirectShowSpy registry key.

Some users that use a 3rd party tool called DirectShowSpy may encounter errors when logging in to XSplit.

This can be caused by a fault registry key that is introduced when DirectShowSpy is registered to intercept Filter Graph initialization — Filter Graph is used by XSplit. The faulty DirectShowSpy registry key is usually caused by DirectShowSpy program begin relocated after registration.

To workaround this situation, XSplit1 detects the presence of HKEYCLASSESROOT\CLSID{E436EBB3-524F-11CE-9F53-0020AF0BA770}\TreatAs registry key2 when it fails to initialize Filter Graph and exits when it is found. In this case, user must manually correct the DirectShowSpy registration or delete3 the registry key. Only after either is done can XSplit be restarted.

The description of the problem is good, solution is good but incomplete.

DirectShowSpy intercepts a few COM classes, not just one, and removing single registry value is only a partial fix.

DirectShowSpy.dll exports UnregisterTreatAsClasses function to accurately restore operation of system classes. It does registry permission magic and updates all COM classes involved. Default unregistration (DllUnregisterServer, regsvr32 /u) behavior is to restore original classes only in case they are currently overridden by DirectShowSpy. That is, if the DLL is moved (deleted) the broken registrations are retained in the registry during unregistration process.

UnregisterTreatAsClasses resolved this problem by forcing recovery of original classes no matter who is overriding them at the moment.

C:\>rundll32 DirectShowSpy-Win32.dll,UnregisterTreatAsClasses
C:\>rundll32 DirectShowSpy-x64.dll,UnregisterTreatAsClasses
Viewing all 249 articles
Browse latest View live