I decided to gather DirectShow code and filters related to processing video from network/IP cameras and video servers into a library (in fact, a few libraries) so that it could be easily used for testing, research and other purposes. As time is going to permit, documentation and sample code will be provided, further development will be carried out.
This initial post publishes two libraries (DLLs) which host DirectShow filters to receive JPEG or M-JPEG video from network using HTTP based protocol, decode video with the help of Intel IPP 6.0 library (UMC version of the JPEG implementation), as well as perform additional helpful features, including writing series of frames into .JPG files and emulating video feed from saved .JPG files, conversion filters to obtain video in 24-bit and 32-bit RGB formats, YUY2 and YV12 formats.
File and Class Summary
Acqusition.dll
Acqusition.dll (download) hosts the following classes:
- DirectShow Filters
- HTTP Stream Source Filter, to receive HTTP content and deliver into DirectShow environment through output pin
- JPEG HTTP Stream Parser Filter, to parse HTTP content (typically received from HTTP Stream Source Filter) of image/jpeg and multipart/x-mixed-replace types and output JPEG frames
- JPEG Multi File Renderer Filter, to write parsed JPEG frames (typically received from JPEG HTTP Stream Parser Filter) into files
- JPEG Multi File Source Filter, to read JPEG files (typically written by JPEG Multi File Renderer Filter) and stream video into DirectShow environmentto emulate video feed
Acqusition.dll is dependent only on well known DLLs and does not require presence/redistribution of specific dependency files.
CodingI.dll
CodingI.dll (download) hosts the following classes:
- DirectShow Filters
- JPEG Frame Decoder Filter, to parse JPEG data and pass frames downstream with a corresponding mediatype provided with VIDEOINFOHEADER format and correct resolution; in case of resolution changes the filter is capable of dynamically re-agreeing media type with downstream peer
- JPEG Decoder Filter, to decode JPEG data into 24-bit/32-bit RGB (unfortunately Intel IPP codec has limited capabilities of decoding video into YUV pixel formats)
- YUY2 Encoder Filter, to convert RGB data into YUY2 pixel format
- YV12 Encoder Filter, to convert RGB data into YV12 pixel format
- Shell Extensions
- JPEG File Resolution Shell Property Page, to provide additional information (such as sampling, color format, resolution) about .JPG and .JPEG files through a shell property page
CodingI.dll is dependent on Intel IPP 6.0 library DLLs and relies on availability of these dependencies in the system. For the CodingI.dll to be operationable, it is required to have a free, trial or registered version of Intel IPP library installed. In particular, the files that are sufficient to be present/redistributed are:
- libguide40.dll, libiomp5md.dll
- ippcore-6.0.dll
- ippi-6.0.dll, ippj-6.0.dll, ipps-6.0.dll, ippcc-6.0.dll, ippvc-6.0.dll
- ippipx-6.0.dll, ippjpx-6.0.dll, ippspx-6.0.dll, ippccpx-6.0.dll, ippvcpx-6.0.dll
Quick Usage Example
Given a M-JPEG compatible network camera on IP address 98.76.54.32, the graph constructed as shown below is capable to deliver video data and render it through standard Video Mixing Renderer Filter.
Assume the camera is StarDot NetCam SC series, with /jpeg.cgi HTTP request to query for JPEG image and /nph-mjpeg.cgi HTTP request to query for M-JPEG video feed.
To construct the graph in GraphEdit (GraphStudio), first it is required to manually add Alax.Info HTTP Stream Source Filter and provide HTTP URL for the request in the property page:
Then an Alax.Info JPEG HTTP Stream Parser Filter is added and connected downstream to the previously added source filter:
A this point it is possible to automatically render output pin and DirectShow intelligent connect will add the rest of required filters, Alax.Info JPEG Frame Decoder (I), Alax.Info JPEG Decoder (I) and Video Renderer.
However, in order for the graph to run in GraphEdit it is required to manually provide correct video resolution in the properties of JPEG Frame Decoder Filter and once applied reconnect all downstream connections up to video renderer in order to enforce new media type.
Running the graph will start streaming video.
Class Overview
HTTP Stream Source Filter
The filter sends one or series of HTTP requests to receive data from network location and stream received data into DirectShow environment.
- Filter Executable: Acquisition.dll
- Filter CLSID: __uuidof(HttpStreamSourceFilter) {943AC94A-3188-4ABC-9BD0-6CFF37CEBBCE}
- Filter Property Page CLSID: __uuidof(HttpStreamSourceFilterLocationPropertyPage), {91EF5CEC-30D1-4e2a-871D-F50A8CB4A7B1}
- Filter Merit: MERIT_UNLIKELY
- Filter Category: CLSID_LegacyAmFilterCategory
- Filter Interfaces: IPersistStreamInit, IPersistStream, ISpecifyPropertyPages, IBaseFilter, IMediaFilter, IPersist, IConnectionPointContainer, IAMovieSetup, IAMFilterMiscFlags, IHttpStreamSourceFilter, IDispatch, IFileSourceFilter (not available in graphedt.exe process)
- Filter Pins: single output pin (Output)
- Output Pin Media Types: MEDIATYPE_Stream/MEDIASUBTYPE_NULL
- Output Pin Interfaces: IPin, IAMPushSource, IAMLatency
Remarks
Filter is a live source and delivers raw data received from network HTTP request(s) in an endless manner. In case the HTTP response is of a finite Content-Length, filter will continuously repeat request. Each first media sample of a response is marked with AM_SAMPLE_DATADISCONTINUITY flag.
Filter exposes connection point and events for the top level application to be able to receive error events as well as callbacks to modify HTTP request verb and object name immediately before the request is sent to network.
Filter is using custom memory allocator through which is exposes IServiceProvider interface on the media samples through which downstream filters could gain access to IHttpStreamSourceHeaders interface and obtain HTTP response headers.
JPEG HTTP Stream Parser Filter
The filter takes data stream on the input and parses streams of image/jpeg and multipart/x-mixed-replace MIME content types into JPEG frames, so that each output media sample contains one JPEG frame.
- Filter Executable: Acquisition.dll
- Filter CLSID: __uuidof(JpegHttpStreamParserFilter) {805469B4-6F03-4532-88C1-7A07A7C8961C}
- Filter Property Page CLSID: N/A
- Filter Merit: MERIT_UNLIKELY
- Filter Category: CLSID_LegacyAmFilterCategory
- Filter Interfaces: IPersistStreamInit, IPersistStream, ISpecifyPropertyPages, IBaseFilter, IMediaFilter, IPersist, IAMovieSetup, IAMFilterMiscFlags, IJpegHttpStreamParserFilter, IDispatch
- Filter Pins: single input and single output pin (Input, Output)
- Input Pin Media Types: MEDIATYPE_Stream/MEDIASUBTYPE_NULL
- Input Pin Interfaces: IPin, IMemInputPin
- Output Pin Media Types: MEDIATYPE_Video/MEDIASUBTYPE_JPEG (FOURCC ‘AIJ0’), MEDIATYPE_Stream/MEDIASUBTYPE_JPEG (FOURCC ‘AIJ0’)
- Output Pin Interfaces: IPin, IMediaSeeking, IMediaPosition, IDispatch
Remarks
Filter is using custom memory allocator through which is exposes IServiceProvider interface on the media samples through which downstream filters could gain access to IHttpStreamSourceHeaders interface and obtain HTTP response headers, both original response and subheaders of multipart Content-Type parts.
JPEG MultiFile Renderer Filter
The filter received JPEG frames and writes data into separate .JPG files, one per frame, into provided directory.
- Filter Executable: Acquisition.dll
- Filter CLSID: __uuidof(JpegMultiFileRendererFilter) {4194A70D-7FB0-4362-973E-B58EA5690FE6}
- Filter Property Page CLSID: __uuidof(JpegMultiFileRendererFilterDirectoryPropertyPage), {300AAAC6-9D89-4633-A7A8-CF7F22D5492F}
- Filter Merit: MERIT_DO_NOT_USE
- Filter Category: CLSID_LegacyAmFilterCategory
- Filter Interfaces: IPersistStreamInit, IPersistStream, ISpecifyPropertyPages, IBaseFilter, IMediaFilter, IPersist, IConnectionPointContainer, IAMovieSetup, IAMFilterMiscFlags, IJpegMultiFileRendererFilter, IDispatch, IFileSinkFilter2 (not available in graphedt.exe process), IFileSinkFilter (not available in graphedt.exe process)
- Filter Pins: single input pin (Input)
- Input Pin Media Types: MEDIATYPE_Video/MEDIASUBTYPE_JPEG (FOURCC ‘AIJ0’)
- Input Pin Interfaces:�IPin, IMemInputPin
Remarks
None.
JPEG MultiFile Source Filter
The filter reads contents of provided directory and stream contained .JPG files emulating a video feed.
- Filter Executable: Acquisition.dll
- Filter CLSID: __uuidof(JpegMultiFileSourceFilter) {B749D696-E479-44dc-AF17-220EBEDFAAE8}
- Filter Property Page CLSID: __uuidof(JpegMultiFileSourceFilterDirectoryPropertyPage), {DE611B46-F6BA-4de5-A714-BEDE243A0BAC}
- Filter Merit: MERIT_DO_NOT_USE
- Filter Category: CLSID_LegacyAmFilterCategory
- Filter Interfaces: IPersistStreamInit, IPersistStream, ISpecifyPropertyPages, IBaseFilter, IMediaFilter, IPersist, IAMovieSetup, IAMFilterMiscFlags, IJpegMultiFileSourceFilter, IDispatch, IFileSourceFilter (not available in graphedt.exe process)
- Filter Pins: single output pin (Output)
- Output Pin Media Types: MEDIATYPE_Video/MEDIASUBTYPE_JPEG (FOURCC ‘AIJ0’), MEDIATYPE_Stream/MEDIASUBTYPE_JPEG (FOURCC ‘AIJ0’)
- Output Pin Interfaces: IPin, IAMPushSource, IAMLatency
Remarks
The filter converts file time stamps into media sample time stamps to convert file write rate into DirectShow rendering/playback rate.
JPEG Frame Decoder Filter
The filter takes raw JPEG input media samples in the input, parses JPEG headers and outputs media samples supplied with valid VIDEOINFOHEADER format with correct resolution.
- Filter Executable: CodingI.dll
- Filter CLSID: __uuidof(JpegFrameDecoderFilter) {EA070483-8D39-4782-8C7B-489AD8B6177F}
- Filter Property Page CLSID: __uuidof(JpegFrameDecoderFilterResolutionPropertyPage), {E14A1F56-A683-4ec2-86B0-F7B6EABF7DC6}
- Filter Merit: MERIT_UNLIKELY – 1
- Filter Category: CLSID_LegacyAmFilterCategory
- Filter Interfaces: IPersistStreamInit, IPersistStream, ISpecifyPropertyPages, IBaseFilter, IMediaFilter, IPersist, IConnectionPointContainer, IAMovieSetup, IAMFilterMiscFlags, IJpegFrameDecoderFilter, IDispatch
- Filter Pins: single input and single output pin (Input, Output)
- Input Pin Media Types: MEDIATYPE_Video/MEDIASUBTYPE_JPEG (FOURCC ‘AIJ0’)
- Input Pin Interfaces: IPin, IMemInputPin
- Output Pin Media Types: MEDIATYPE_Video/MEDIASUBTYPE_JPEG (FOURCC ‘AIJ0’)/FORMAT_VideoInfo
- Output Pin Interfaces: IPin, IMediaSeeking, IMediaPosition, IDispatch
Remarks
Filter is attempting to dynamically re-agree media type with downstream filter in case media type changes. Initialially in absence of data about effective video resolution, the filter uses default resolution (320×240 or overridden through private interface IJpegFrameDecoderFilter.
Filter is attempting to share memory allocators on input and output pins to be able to pass media samples transparently without copying data.
Filter exposes connection point and events for the top level application to be able to receive resolution change events.
JPEG Decoder Filter
The filter decodes input media samples of JPEG� format and outputs 24-bit/32-bit RGB media samples.
- Filter Executable: CodingI.dll
- Filter CLSID: __uuidof(JpegFrameFilter) {28A8C753-363C-460a-9D99-74E534A5114F}
- Filter Property Page CLSID: N/A
- Filter Merit: MERIT_NORMAL + 0x10
- Filter Category: CLSID_LegacyAmFilterCategory
- Filter Interfaces: IPersistStreamInit, IPersistStream, ISpecifyPropertyPages, IBaseFilter, IMediaFilter, IPersist, IConnectionPointContainer, IAMovieSetup, IAMFilterMiscFlags, IJpegDecoderFilter, IDispatch
- Filter Pins: single input and single output pin (Input, Output)
- Input Pin Media Types: MEDIATYPE_Video/MEDIASUBTYPE_JPEG (FOURCC ‘AIJ0’)/FORMAT_VideoInfo
- Input Pin Interfaces: IPin, IMemInputPin
- Output Pin Media Types: MEDIATYPE_Video/MEDIASUBTYPE_RGB24/FORMAT_VideoInfo, MEDIATYPE_Video/MEDIASUBTYPE_RGB32/FORMAT_VideoInfo
- Output Pin Interfaces: IPin, IMediaSeeking, IMediaPosition, IDispatch
Remarks
Filter is attempting to re-agree media type on the output pin in case it receives a request to change media type on the input pin, in order to transparently support dynamic resolution change.
YUY2 Encoder Filter
The filter converts 24-bit and 32-bit RGB media samples into YUY2 pixel format.
- Filter Executable: CodingI.dll
- Filter CLSID: __uuidof(Yuy2EncoderFilter) {5302581E-A3B2-408b-BC23-71ECA8BC8885}
- Filter Property Page CLSID: N/A
- Filter Merit: MERIT_DO_NOT_USE + 0x10
- Filter Category: CLSID_LegacyAmFilterCategory
- Filter Interfaces: IBaseFilter, IMediaFilter, IPersist, IAMovieSetup, IAMFilterMiscFlags
- Filter Pins: single input and single output pin (Input, Output)
- Input Pin Media Types: MEDIATYPE_Video/MEDIASUBTYPE_RGB24/FORMAT_VideoInfo, MEDIATYPE_Video/MEDIASUBTYPE_RGB32/FORMAT_VideoInfo
- Input Pin Interfaces: IPin, IMemInputPin
- Output Pin Media Types: MEDIATYPE_Video/MEDIASUBTYPE_YUY2/FORMAT_VideoInfo,
- Output Pin Interfaces: IPin, IMediaSeeking, IMediaPosition, IDispatch
Remarks
Filter is attempting to re-agree media type on the output pin in case it receives a request to change media type on the input pin, in order to transparently support dynamic resolution change.
YV12 Encoder Filter
The filter converts 24-bit and 32-bit RGB media samples into YV12 pixel format.
- Filter Executable: CodingI.dll
- Filter CLSID: __uuidof(Yv12EncoderFilter) {CDC777A0-0DB0-4a01-9C42-F23F053F9F36}
- Filter Property Page CLSID: N/A
- Filter Merit: MERIT_DO_NOT_USE + 0x10
- Filter Category: CLSID_LegacyAmFilterCategory
- Filter Interfaces: IBaseFilter, IMediaFilter, IPersist, IAMovieSetup, IAMFilterMiscFlags
- Filter Pins: single input and single output pin (Input, Output)
- Input Pin Media Types: MEDIATYPE_Video/MEDIASUBTYPE_RGB24/FORMAT_VideoInfo, MEDIATYPE_Video/MEDIASUBTYPE_RGB32/FORMAT_VideoInfo
- Input Pin Interfaces: IPin, IMemInputPin
- Output Pin Media Types: MEDIATYPE_Video/MEDIASUBTYPE_YV12/FORMAT_VideoInfo,
- Output Pin Interfaces: IPin, IMediaSeeking, IMediaPosition, IDispatch
Remarks
Filter is attempting to re-agree media type on the output pin in case it receives a request to change media type on the input pin, in order to transparently support dynamic resolution change.
One of the visitors complained that sequence of filters could not stream M-JPEG video from Panasonic BL-C140 (also in Russian) camera (with latest firmware 3.51R00). The problem may apply to different models too. It appeared that the camera generated incorrect multipart MIME stream and provided incorrect boundary. Today’s SVN update works the problem around.
For reference: Information request: /Get?Func=Model&Kind=1, JPEG request: /SnapshotJPEG?Resolution=320×240&Kind=1, M-JPEG request: /nphMotionJpeg?Resolution=320×240&Kind=1
More on Panasonic BL-C140:
I noticed that and frankly I am not sure what exactly is causing it. It may be an incomplete frame sent by camera (JPEG with a few trailing bytes cut out) OR incorrect Content-Length reported by camera OR incorrect JPEG decoding by Intel IPP code. Or definitely by bug possible too. I will look into that later.
The problem with different resolutions is that filters don’t handle dynamic resolution change. They connect at 320×240 and later cannot switch to different resolution. I have dynamic resolution change attempt in my filters but Video Mixing Renderer does not seem to support that to full required extent.
I known it would support as a part of dynamic reconnection, but I did not implement that in my filters (and it is a hosting application who rather has to do that).
So in my sample Samples/RenderHttpMjpegVideo01 note that application connects to event of JPEG Frame Decoder using DispEventAdvise and catches resolution changes. Later is this seems to be a cause of filter graph error (_tprintf(_T(“Detected resolution change…) it recreates the entire graph with new resolution.
In GraphEdit, you need to change URL in source filter, change default resolution as you did in frame decoder, then:
640×480 resolution
Press Play and your’re fine again!
A sample application RenderHttpMjpegVideo01 that takes a HTTP URL as a command line argument and renders M-JPEG video was updated to be compiled in more or less standard environment: Visual Studio with ATL, Windows/Platform SDK, WTL.
Yes, these host filters. “regsvr32 Acquisition.dll” from command prompt and the filters are already there in available graphedit. Also check https://alax.info/blog/category/utilities/media-tools from bottom to top and this gives a brief explanation of the contained filters.
Also RenderHttpMjpegVideo01 and RenderHttpMjpegVideo02 is a C++ code which uses these filters.
I have not put any MPEG-4 code available yet, and it is unlikely happen in the nearest future. However as long as Axis cameras are in question, you can use any RTSP client to access media feed from them.
Is there a licensing requirement for using this software in a commercial application, not for redistribution?
At the very moment I grant permission to use the binaries in commercial application provided that:
As the comment will be kept published, these conditions are subject to additional confirmation and can be changed at any time, please email me to licensing at alax info for further questions.
Also commercial licenses for binaries packaged to be used “out of the box” with included redistributables, support, OEM/branded versions might be considered individually.
I have followed all the steps to render my camera but it is not working.
I have registered Acquisition.dll and CodingI.dll (this one after installing IPP 6.0.0.062). I have created the graph, and even changed JPEG Frame Decoder Filter resolution, but when I press Play I see nothing in the render window and the graph stops.
I am trying to connect to an AXIS 213 PTZ camera and the connection string I am using is “http://root:@172.27.4.171:80/axis-cgi/mjpg/video.cgi?resolution=768×576” (I have tried this connection string in VLC and it works fine).
Do you have any idea what could be the problem?
Thanks
In the connection string after the username “root” I also have the password. The post doesn’t show it beacause I wrote it between “” characters.
Thank you for pointing this out, I fixed that. It should be working fine with Axis cameras, just for example I tried one at Texel Airport (The NetherLands):
You need to update DLLs from SVN repository.
Hi alax and thanks for answering,
As you said I got the new DLLs (I previously unregistered the old ones). I am sorry but I am getting the “the graph could not change state” error with both, my camera and the Texel Airport Camera (I do change the JPEG Frame Decoder Filter resolution though). Is it working for you?
I don’t know what is wrong. Any idea?
This is typically because effective resolution is different from what is set up on a decoding filter. Check screenshot 2 there. You need to set up 352×288.
What is causing this error is that filter attempt to dynamically change resolution, but Video Mixing Renderer is unable to do that, it cannot “change state” while running, so you need to provide correct resolution before running the graph.
If you change resolution on already connected graph, delete JPEG Decoder and reconnect JPEG Frame Decoder’s output to Video Mixing Renderer again to have decoder added for changed resolution.
I already did that but I still get the error. I don’t know what’s wrong but it doesn’t work for me.
I would appreciate any other suggestion.
OK, I tried to build the graph on a clean XP system – it worked for me. Step by step things I did:
Build graph as described in post https://alax.info/blog/1006
Axis camera started streaming.
Useful attachments:
What is also important is what error code is given with the message. For example, code 0x80190191 corresponds to HTTP 401 error “Unauthorized”. 0x80072efd “A connection with the server could not be established” is typically given if the camera is offline (you can enter the same URL into browser to see if the camera responds anything for given URL).