The MASM Forum

General => The Workshop => Topic started by: jj2007 on June 21, 2017, 05:01:24 AM

Title: DirectShow transform
Post by: jj2007 on June 21, 2017, 05:01:24 AM
Anybody around for whom the text below is not Chinese?

What I really need is a pointer to the bitmap before the frame is rendered to the DC. Ideally I'd like to use Gdi+ to rotate the image. My code runs fine with most video formats, the only problem is that some need to be rotated...

How to add a filter in a graph (https://social.msdn.microsoft.com/Forums/vstudio/en-US/200f7048-38f6-4cf6-98c2-8a54905f912d/how-to-add-a-filter-in-a-graph?forum=windowsdirectshowdevelopment)
Actually you have several options. Yes you anyway need to add your filter to the graph manually as suggested by Michel.

Then you can:

    Instead of IGraphBuilder:: RenderFile call IGraphBuilder:: AddSourceFilter to only auto-add first filter for the sourec file. After that use IGraphBuilder::Connect (or ICaptureGraphBuilder:: RenderStream) where you can provide your filter (filter's pin) interface to engage it into rendering explicitly
    You can still IGraphBuilder:: RenderFile but before Run'ning break the connection using IFilterGraph:: Disconnect and re-connect pins through your filter at the point of interest

Before running the graph it is available to you for any reconstruction. Once you are finished with inserting your filter, Run the graph.
Title: Re: DirectShow transform
Post by: HSE on June 21, 2017, 05:18:28 AM
It's not Chinese JJ!!!

(Perhaps some extraterrestrial translation of chinese)
Title: Re: DirectShow transform
Post by: qWord on June 21, 2017, 08:47:09 AM
Quote from: jj2007 on June 21, 2017, 05:01:24 AM
Anybody around for whom the text below is not Chinese?
Translation: ,,If you already have a filter that transform the frames, it must be inserted before the Video Renderer Filter in the graph of filters."

You might take a look at the tool "GraphEdit" that comes with the Windows SDKs.
Title: Re: DirectShow transform
Post by: jj2007 on June 21, 2017, 09:00:25 AM
Quote from: qWord on June 21, 2017, 08:47:09 AMTranslation: ,,If you already have a filter that transform the frames, it must be inserted before the Video Renderer Filter in the graph of filters."

Good, now I have it also in Japanese. Any volunteers for English?

Quote from: jj2007 on June 21, 2017, 05:01:24 AMWhat I really need is a pointer to the bitmap before the frame is rendered to the DC. Ideally I'd like to use Gdi+ to rotate the image.
Title: Re: DirectShow transform
Post by: Siekmanski on June 21, 2017, 09:16:00 AM
Did you try "GetCurrentBuffer" from the ISampleGrabber interface? Then you can get a pointer to the pixel data.
No promises I will succeed, but I'll give it a try this week and maybe come up with something in English :biggrin:
Title: Re: DirectShow transform
Post by: jj2007 on June 21, 2017, 05:48:25 PM
Thanks a lot, Marinus. I had stumbled over the word ISampleGrabber in one of the many posts I read, but I am still far from understanding the logic. So with ISampleGrabber::GetCurrentBuffer, I hope there is no need to register a DLL with GUID and all that crap....? Looking forward to your example. Take it easy, the next days I am busy anyway with family ;-)

P.S.: Pixel data sounds good in principle. What I wonder, though, if the graphics card can do the rotation faster, e.g. with Gdi+ Image.RotateFlip; that's why I mentioned the DC.
Title: Re: DirectShow transform
Post by: Siekmanski on June 21, 2017, 07:43:37 PM
No dll's needed, we can get direct access via COM interfaces. It was a pain in the ass to find and collect them all.
I found the interfaces in these C++ include files: strmif.h control.h and uuids.h
Don't know how the DirectShow filters work internally, but if we can get the pointer to the pixel buffer we can handle the rotations and flipping ourselves, by copying the pixels with SSE AVX to a DirectX texture or to a GDIplus bitmap buffer.
I managed to get the pixel buffer pointer from capture devices, so I think and hope it can be done. we will see....

It will be a nice routine for my multimedia library.
Title: Re: DirectShow transform
Post by: Siekmanski on June 30, 2017, 09:36:33 AM
After reading hours on MSDN to get a grasp how things work under the hood of DirectShow filters and pin connections etc.
I put something together that works in a very direct way to get the encoded raw bitmap data from video movies.
Made an example using Direct3D9 in 2D mode which is IMHO by far the best and fastest way of manipulating bitmaps.
It offers much more possibilities than GDI or GDI+ and is mega fast in rendering, alpha blending etc.

I'm not very well known with the DirectShow api so, if any of you guys have better ideas let us know.

But of course you can use this routine in any api you like.

Example how to use it without Direct3D9,

.const

VIDEO_INFO struct
    AvgTimePerFrame     dq ?
    biBitCount          dd ?
    biWidth             dd ?
    biHeight            dd ?
    pBitMapBuffer       dd ?
    BitMapBufferSize    dd ?
VIDEO_INFO ends

include dx9macros.inc ; here are the macros used in the "sampleGrabber" code, look in the Includes folder.

.data?

VideoInfo_1         VIDEO_INFO <?>

.data
Video_file db "Test.avi"

    include DSVideoGrabber.asm

.code
    invoke  CoInitialize, NULL ; put this line somewhere at the start of your code.
                               ; this is needed for the COM interfaces to work correctly.


    invoke  RtlZeroMemory,offset VideoInfo_1,sizeof VideoInfo_1
    invoke  VideoGrabber,offset Video_file,offset VideoInfo_1 ; start the VideoGrabber.
    cmp     eax,S_OK
    jne     no_video_found

    coinvoke g_pMediaControl,IMediaControl,Run ; start the movie.

; Now poll +/- 60 times a second the VideoGrabber buffer.

PollVideoData proc
    mov     ecx,pVideoInfo
    coinvoke g_pSampleGrabber,ISampleGrabber,GetCurrentBuffer,addr VideoInfo_1.BitMapBufferSize,VideoInfo_1.pBitMapBuffer
    cmp     eax,S_OK    ; is there a new VideoFrame available?
    je      GetVideoFrame
    ret
GetVideoFrame:
; copy the data to your own destination buffer
    mov     esi,VideoInfo_1.pBitMapBuffer   ; pointer to the raw BitMapBuffer from the SampleGrabber
    mov     edi,MyBitMapBuffer   ; pointer to your destination BitMapBuffer
    mov     ecx,VideoInfo_1.BitMapBufferSize

; place your copy routine here.
    ret
PollVideoData endp

    invoke  ReleaseVideoObjects,offset VideoInfo_1 ; when done...

    invoke  CoUninitialize         



The main routine,

align 4
VideoGrabber proc uses esi edi pVideoName:DWORD,pVideoInfo:DWORD

    invoke  ReleaseVideoObjects,pVideoInfo
    call    ReleaseVideoImageObjects        ; remove this line if you're not using D3D9

    ; create the Filter Graph Manager   
    invoke  CoCreateInstance,GUID_ADDR(CLSID_FilterGraph),NULL,CLSCTX_INPROC_SERVER,GUID_ADDR(IID_IGraphBuilder),addr g_pGraphBuilder
    cmp     eax,S_OK
    jne     VideoGrabber_Error

    ; create the IMediaControl interface
    coinvoke g_pGraphBuilder,IGraphBuilder,QueryInterface,GUID_ADDR(IID_IMediaControl),addr g_pMediaControl
    cmp     eax,S_OK
    jne     VideoGrabber_Error

    ; Create an instance of the Sample Grabber filter
    invoke  CoCreateInstance,GUID_ADDR(CLSID_SampleGrabber),NULL,CLSCTX_INPROC_SERVER,GUID_ADDR(IID_IBaseFilter),addr g_pGrabberFilter
    cmp     eax,S_OK
    jne     VideoGrabber_Error

    ; Add it to the filter graph
    coinvoke g_pGraphBuilder,IGraphBuilder,AddFilter,g_pGrabberFilter,NULL
    cmp     eax,S_OK
    jne     VideoGrabber_Error

    ; Query the Sample Grabber filter for the ISampleGrabber interface
    coinvoke g_pGrabberFilter,ISampleGrabber,QueryInterface,GUID_ADDR(IID_ISampleGrabber),addr g_pSampleGrabber
    cmp     eax,S_OK
    jne     VideoGrabber_Error

    ; When you first create the Sample Grabber, it has no preferred media type.
    ; This means you can connect to almost any filter in the graph, but you would have no control over the type of data that it received.
    ; Before building the rest of the graph, therefore, you must set a media type for the Sample Grabber, by calling the ISampleGrabber.SetMediaType method.

    ; When the Sample Grabber connects, it will compare this media type against the media type offered by the other filter.
    ; The only fields that it checks are the major type, subtype, and format type. For any of these, the value GUID_NULL means "accept any value."
    ; Most of the time, you will want to set the major type and subtype. For example, the following code specifies uncompressed 32-bit RGB video:

    invoke  CoTaskMemAlloc,sizeof AM_MEDIA_TYPE ; allocate memory for the AM_MEDIA_TYPE structure
    mov     pVideoMediaType,eax
   
    invoke  RtlZeroMemory,pVideoMediaType,sizeof AM_MEDIA_TYPE
    mov     edi,pVideoMediaType
    invoke  RtlMoveMemory,addr [edi].AM_MEDIA_TYPE.majortype,GUID_ADDR(MEDIATYPE_Video),16
    invoke  RtlMoveMemory,addr [edi].AM_MEDIA_TYPE.subtype,GUID_ADDR(MEDIASUBTYPE_RGB32),16
    invoke  RtlMoveMemory,addr [edi].AM_MEDIA_TYPE.formattype,GUID_ADDR(FORMAT_VideoInfo),16
    ;  Regardless of what type you set, the Sample Grabber Filter rejects any video types with top-down orientation (negative biHeight).
    coinvoke g_pSampleGrabber,ISampleGrabber,SetMediaType,pVideoMediaType
    cmp     eax,S_OK
    jne     VideoGrabber_Error

    ; Now you can build the rest of the filter graph. Because the Sample Grabber will only connect using the media type you have specified,
    ; this lets you take advantage of the Filter Graph Manager's Intelligent Connect mechanisms when you build the graph.

    ; For example, if you specified uncompressed video, you can connect a source filter to the Sample Grabber,
    ; and the Filter Graph Manager will automatically add the file parser and the decoder.

    invoke  MultiByteToWideChar,CP_ACP,0,pVideoName,-1,offset szLstring,MAX_PATH
    coinvoke g_pGraphBuilder,IGraphBuilder,AddSourceFilter,offset szLstring,offset szLSource,addr g_pSourceFilter
    cmp     eax,S_OK
    je      asf_ok
    cmp     eax,VFW_E_CANNOT_LOAD_SOURCE_FILTER
    jne     enf
    invoke  MessageBox,0,TEXT_("The source filter for this file could not be loaded."),TEXT_("AddSourceFilter Error."),MB_ICONERROR
    jmp     VideoGrabber_Error
enf:
    cmp     eax,VFW_E_NOT_FOUND
    jne     euft
    invoke  MessageBox,0,TEXT_("File or object not found."),TEXT_("AddSourceFilter Error."),MB_ICONERROR
    jmp     VideoGrabber_Error
euft:
    cmp     eax,VFW_E_UNKNOWN_FILE_TYPE
    jne     asfe
    invoke  MessageBox,0,TEXT_("The media type of this file was not recognized."),TEXT_("AddSourceFilter Error."),MB_ICONERROR
    jmp     VideoGrabber_Error
asfe:
    invoke  wsprintf,addr szString_buffer,TEXT_("AddSourceFilter Error: %0x"),eax
    invoke  MessageBox,0,addr szString_buffer,TEXT_("AddSourceFilter Error."),MB_ICONERROR
    jmp     VideoGrabber_Error
asf_ok:

    ; The following example uses a ConnectFilters helper function.
    ; It tries to find an output pin of the SourceFilter and an input pin of the GrabberFilter, if succeeded the 2 filters are connected.
    ; It can happen that there are more streams in a filter such as the audio stream. In this example only the raw Video is encoded.
    ; IGraphBuilder.Connect will return VFW_S_PARTIAL_RENDER (040242h), which is not an error because there is no audio filter added.

    invoke  ConnectTwoFilters,g_pSourceFilter,g_pGrabberFilter
    cmp     eax,S_OK
    jne     VideoGrabber_Error

    ; The Sample Grabber is a transform filter, so the output pin must be connected to another filter.
    ; Often, you may simply want to discard the samples after you are done with them.
    ; In that case, connect the Sample Grabber to the Null Renderer Filter, which discards the data that it receives.

    ; This is exactly what jj2007 and I (Siekmanski) want, direct access to the raw encoded bitmap data and nothing more.
   
    ; Query the NullRendererFilter
    invoke  CoCreateInstance,GUID_ADDR(CLSID_NullRenderer),NULL,CLSCTX_INPROC_SERVER,GUID_ADDR(IID_IBaseFilter),addr g_pNullRendererFilter
    cmp     eax,S_OK
    jne     VideoGrabber_Error

    ; Add it to the filter graph
    coinvoke g_pGraphBuilder,IGraphBuilder,AddFilter,g_pNullRendererFilter,NULL
    cmp     eax,S_OK
    jne     VideoGrabber_Error

    ; Connect the SampleGrabber to the NullRendererFilter
    invoke  ConnectTwoFilters,g_pGrabberFilter,g_pNullRendererFilter
    cmp     eax,S_OK
    jne     VideoGrabber_Error

    coinvoke g_pSampleGrabber,ISampleGrabber,SetOneShot,FALSE       ; After the first sample, the Sample Grabber continues to process samples.
    cmp     eax,S_OK
    jne     VideoGrabber_Error

    coinvoke g_pSampleGrabber,ISampleGrabber,SetBufferSamples,TRUE  ; This method does not return a value.

    invoke  CoTaskMemAlloc,sizeof VIDEOINFOHEADER
    mov     esi,pVideoMediaType
    mov     dword ptr [esi].AM_MEDIA_TYPE.pbFormat,eax              ; insert allocated VIDEOINFOHEADER structure memory, to receive the BITMAPINFOHEADER info

    coinvoke g_pSampleGrabber,ISampleGrabber,GetConnectedMediaType,pVideoMediaType ; get the bitmap info from the SampleGrabber
    cmp     eax,S_OK
    je      gcmt_ok
    cmp     eax,VFW_E_NOT_CONNECTED
    je      not_connected
    invoke  wsprintf,addr szString_buffer,TEXT_("GetConnectedMediaType Error: %0x"),eax
    invoke  MessageBox,0,addr szString_buffer,TEXT_("GetConnectedMediaType Error."),MB_ICONERROR
    jmp     VideoGrabber_Error
not_connected:
    invoke  MessageBox,0,TEXT_("The filter is not connected."),TEXT_("GetConnectedMediaType Error."),MB_ICONERROR
    jmp     VideoGrabber_Error
gcmt_ok:

    mov     edi,pVideoInfo                                          ; copy the bitmap info to the VIDEO_INFO structure
    mov     esi,pVideoMediaType
    movsd   xmm0,qword ptr [esi].VIDEOINFOHEADER.AvgTimePerFrame
    movsd   qword ptr [edi].VIDEO_INFO.AvgTimePerFrame,xmm0
    mov     esi,dword ptr [esi].AM_MEDIA_TYPE.pbFormat
    lea     esi,[esi].VIDEOINFOHEADER.bmiHeader
    movzx   eax,word ptr [esi].BITMAPINFOHEADER.biBitCount
    mov     dword ptr [edi].VIDEO_INFO.biBitCount,eax
    mov     eax,dword ptr [esi].BITMAPINFOHEADER.biWidth
    mov     dword ptr [edi].VIDEO_INFO.biWidth,eax
    mov     eax,dword ptr [esi].BITMAPINFOHEADER.biHeight
    mov     dword ptr [edi].VIDEO_INFO.biHeight,eax

    invoke  CoTaskMemFree,dword ptr [esi].AM_MEDIA_TYPE.pbFormat    ; free the VIDEOINFOHEADER memory from the AM_MEDIA_TYPE structure memory
    mov     dword ptr [esi].AM_MEDIA_TYPE.pbFormat,NULL
    invoke  CoTaskMemFree,pVideoMediaType                           ; free the AM_MEDIA_TYPE structure memory
    mov     pVideoMediaType,NULL
       
    ; Pausing the filter graph cues the graph for immediate rendering when the graph is next run.
    ; While the graph is paused, filters process data but do not render it.
    ; Data is pushed through the graph and processed by transform filters as far as buffering permits, but renderer filters do not render the data.
    ; However, video renderers display a static poster frame of the first sample.

    coinvoke g_pMediaControl,IMediaControl,Pause

    ; "IMediaControl.Pause" returns:
    ; S_FALSE if the graph paused successfully, but some filters have not completed the state transition.
    ; S_OK if all filters in the graph completed the transition to a paused state.

    ; So, we have to wait for the filters have completed the state transition.
    ; Because "IMediaEventEx.WaitForCompletion" can stall forever, we wait for "ISampleGrabber.GetCurrentBuffer" is ready, and gives back the BitMapBufferSize.

    mov     edi,pVideoInfo
WaitForCompletion: 
    invoke Sleep,10
    coinvoke g_pSampleGrabber,ISampleGrabber,GetCurrentBuffer,addr [edi].VIDEO_INFO.BitMapBufferSize,NULL
    cmp     dword ptr [edi].VIDEO_INFO.BitMapBufferSize,0
    jz      WaitForCompletion
    cmp     eax,S_OK
    jne     WaitForCompletion

    invoke  CoTaskMemAlloc,dword ptr [edi].VIDEO_INFO.BitMapBufferSize ; Now we know the size of the BitMapBufferSize, allocate the memory for the SampleGrabber.
    mov     dword ptr [edi].VIDEO_INFO.pBitMapBuffer,eax

    ; coinvoke g_pMediaControl,IMediaControl,Run
    ; "IMediaControl.Run" returns:
    ; S_FALSE if the graph is preparing to run, but some filters have not completed the transition to a running state.
    ; S_OK if all filters in the graph completed the transition to a running state.

    ; So, we don't check the return message, it will run when the graph completed the transition to a running state.
    mov     eax,S_OK
    ret

VideoGrabber_Error:
    call    ReleaseVideoObjects
    mov     eax,S_FALSE
    ret
VideoGrabber endp


EDIT: new source code, (see Reply #24)

Placed the AM_MEDIA_TYPE structure and the VIDEOINFOHEADER structure in memory allocated by CoTaskMemAlloc as suggested by Microsoft.
Replaced the sse2 SIMD vertex fill routine by a simpler routine. ( my wife's laptop choked in the previous one )
Removed the SetSamplerState,0,D3DRS_DITHERENABLE,TRUE. ( Not all video-cards have it implemented and black out the texture )
Added some error handling.

You have to install additional DirectShow Video Codecs if certain video formats refuse to work on your PC.

http://www.codecguide.com/download_kl.htm ( See jj2007's Reply #25 for handling this. )

Marinus

Title: Re: DirectShow transform
Post by: jj2007 on June 30, 2017, 04:56:34 PM
Great work, Marinus :t

The exe works fine, it opens with a delay of about 4 seconds.
Building succeeds if I use crt_sprintf, but the new exe choked once shortly before CoTaskMemFree. Since then, it builds fine and behaves well ::)

As soon as I have some spare time, I will have a closer look. Thanks a lot for investigating this :icon14:
Title: Re: DirectShow transform
Post by: Siekmanski on June 30, 2017, 09:22:48 PM
Thanks, the delay is because it streams a movie from the internet.  :biggrin:
If you load it as a file it runs immediately.
The sprintf behaviour, I may be using an older msvcrt.lib ?

It was fun and time spent well.  :t

Quotebut the new exe choked once shortly before CoTaskMemFree

VIDEO_INFO.pBitMapBuffer was uninitialized.

Zeroing the VIDEO_INFO structure was needed before calling VideoGrabber.

    invoke  RtlZeroMemory,offset VideoInfo_1,sizeof VideoInfo_1
    invoke  VideoGrabber,TEXT_("https://archive.org/download/Apollo_9__Three_To_Make_Ready/Apollo_9_Three_To_Make_Ready_512kb.mp4"),offset VideoInfo_1

Uploaded the new sources (Reply #7), also includes the older msvcrt.lib I used.
Title: Re: DirectShow transform
Post by: jj2007 on June 30, 2017, 11:26:28 PM
Quote from: Siekmanski on June 30, 2017, 09:22:48 PMThanks, the delay is because it streams a movie from the internet.  :biggrin:

I've downloaded the movie (30 seconds - Internet is slow here), it plays fine with my player, but DShowGrabber.exe stops at the image below :(
Title: Re: DirectShow transform
Post by: Siekmanski on June 30, 2017, 11:40:34 PM
 :(
I've also downloaded the movie and loaded it as a file, it runs immediately.
I don't have a clue, it runs fine here.

Try changing the window dimensions in DShowGrabber.Asm to:

Screen_Width        dd  320
Screen_Height       dd  240
Title: Re: DirectShow transform
Post by: jj2007 on June 30, 2017, 11:46:56 PM
My best guess so far is that the download is too slow, and that DShow cancels at a certain point.
When modifying the path, the exe starts immediately but no video; changing w+h has no effect except that the window is smaller.
Title: Re: DirectShow transform
Post by: Siekmanski on June 30, 2017, 11:57:46 PM
Does this one work?
It loads a small avi from file.
Title: Re: DirectShow transform
Post by: aw27 on July 01, 2017, 12:17:18 AM
Quote from: Siekmanski on June 30, 2017, 09:22:48 PM
Thanks, the delay is because it streams a movie from the internet.  :biggrin:
If you load it as a file it runs immediately.
The sprintf behaviour, I may be using an older msvcrt.lib ?

It was fun and time spent well.  :t

Quotebut the new exe choked once shortly before CoTaskMemFree

VIDEO_INFO.pBitMapBuffer was uninitialized.

Zeroing the VIDEO_INFO structure was needed before calling VideoGrabber.

    invoke  RtlZeroMemory,offset VideoInfo_1,sizeof VideoInfo_1
    invoke  VideoGrabber,TEXT_("https://archive.org/download/Apollo_9__Three_To_Make_Ready/Apollo_9_Three_To_Make_Ready_512kb.mp4"),offset VideoInfo_1

Uploaded the new sources (Reply #7), also includes the older msvcrt.lib I used.

I am having a problem also (trying your DShowGrabber2.zip).
I changed the mp4 to a smaller one downloaded from my site but did not help.

I could track the error to here:


coinvoke g_pSampleGrabber,ISampleGrabber,GetConnectedMediaType,offset VideoMediaType ; get the bitmap info from the SampleGrabber
    cmp     eax,S_OK
    jne     VideoGrabber_Error

where eax is 80040209


Title: Re: DirectShow transform
Post by: Siekmanski on July 01, 2017, 12:56:37 AM
Thanks aw27,

It didn't work on my wife's laptop either, have some debugging to do this weekend.
Title: Re: DirectShow transform
Post by: jj2007 on July 01, 2017, 01:13:56 AM
In case it helps... stuck at this call:CPU Disasm
Address           Hex dump                     Command                            Comments
004014DD          ³.  E8 2AFBFFFF              call <jmp.&kernel32.MultiByteToWid ; ÀKERNEL32.MultiByteToWideChar
004014E2          ³.  8B15 50404000            mov edx, [404050]
004014E8          ³.  8B12                     mov edx, [edx]
004014EA          ³.  68 54404000              push offset 00404054
004014EF          ³.  68 78404000              push offset 00404078               ; UNICODE "Source"
004014F4          ³.  68 60494000              push offset 00404960               ; UNICODE "sample.avi"
004014F9          ³.  FF35 50404000            push dword ptr [404050]
004014FF          ³.  FF52 38                  call near [edx+38] <<<<<<<<<<<<<<<<<<<<<<<
00401502          ³.  83F8 00                  cmp eax, 0
Title: Re: DirectShow transform
Post by: Siekmanski on July 01, 2017, 05:08:25 PM
Did some debugging and hope it works now.
The return messages for connecting the filters are shown first for debugging purposes.

In case it doesn't show the video on screen, could you post the error codes please?

The error code for "Connect SourceFilter: 40242" is normal because the audio stream is not decoded.
Title: Re: DirectShow transform
Post by: jj2007 on July 01, 2017, 05:49:30 PM
Now the video shows, with error 40242 for the audio part :t
Title: Re: DirectShow transform
Post by: Siekmanski on July 01, 2017, 08:48:28 PM
Some internet streams of different formats.
I'll update the sources when it works all fine on your computers, some feedback from you guys would be nice.  :biggrin:
Title: Re: DirectShow transform
Post by: jj2007 on July 01, 2017, 08:56:24 PM
12:11:06  works fine
12:23:48  works fine
12:27:14  works fine, takes a bit longer
12:38:20  crashes in RtlFreeHeap called by the first CoTaskMemFree
Title: Re: DirectShow transform
Post by: TWell on July 01, 2017, 09:58:54 PM
DShowGrabber.exe
DShowGrabber2.exe
QuoteConnecting Error.
No combination of intermediate filters could be found to make the connection.

DShowGrabber3.exe
QuoteAddSourceFilter Error.
AddSourceFilter Error; 800c0008

DShowGrabber4.exe
Shows a video.
Title: Re: DirectShow transform
Post by: aw27 on July 02, 2017, 12:07:00 AM
DShowGrabber.exe - no combination of intermediate filters can be found to make the connection
DShowGrabber2.exe - Video OK
DShowGrabber3.exe - no combination of intermediate filters can be found to make the connection
DShowGrabber4.exe - Video OK
Title: Re: DirectShow transform
Post by: HSE on July 02, 2017, 12:15:15 AM
0,3 and 4    -->   Ok

2                 --> no combination etc. On close Olly say: Entry Point Alert :Module 'Netvideo' has entry point outside the code (as specified in the PE header)
Title: Re: DirectShow transform
Post by: Siekmanski on July 02, 2017, 02:08:00 PM
Thanks guys for testing.  :t

Updated the sources in Reply #7

Placed the AM_MEDIA_TYPE structure and the VIDEOINFOHEADER structure in memory allocated by CoTaskMemAlloc as suggested by Microsoft.
Replaced the sse2 SIMD vertex fill routine by a simpler routine. ( my wife's laptop choked in the previous one )
Removed the SetSamplerState,0,D3DRS_DITHERENABLE,TRUE. ( Not all video-cards have it implemented and black out the texture )
Added some error handling.

You have to install additional DirectShow Video Codecs if certain video formats refuse to work on your PC.

http://www.codecguide.com/download_kl.htm

Marinus
Title: Re: DirectShow transform
Post by: jj2007 on July 02, 2017, 05:46:22 PM
Quote from: Siekmanski on July 02, 2017, 02:08:00 PM
Thanks guys for testing.  :t

With pleasure. There is great interest, it seems :biggrin:

QuoteYou have to install additional DirectShow Video Codecs if certain video formats refuse to work on your PC.

http://www.codecguide.com/download_kl.htm

The best I had so far was http://www.windows7codecs.com/

I've now installed K-Lite. Codecs are incredibly messy, and all these packages are competing and blaming other packages for problems. K-Lite asked to uninstall all other packages present on my machine... which I did. Now 3gp videos have started working  :biggrin: but swf stopped working :(

P.S.: WARNING: Google for k-lite codec pack web companion - definitely not Marinus' fault, but I was a bit shocked to see Micros**t Bang appear as my "homepage". Reminds me of the windows 10 marketing disaster :eusa_boohoo:

See e.g. K-Lite now bundled with web companion that changes your home page and search provider (http://codecs.forumotion.net/t2118-k-lite-now-bundled-with-web-companion-that-changes-your-home-page-and-search-provider):
QuoteI uninstalled it in Programs and Features in Windows 10 but it leaves .dlls in System 32 and Syswow64 that if removed will terminate one's internet connection . their forum says to all it's users to run a command prompt of "netsh winsock reset"

Apparently, you need "netsh winsock reset" (https://forum.adaware.com/index.php?/topic/34397-lavasoft-web-comapanion-surreptiously-installed-itself-bundled-with-k-lite-codec-pack/) to make de-installation of this crap possible.

Here (http://codecs.forumotion.net/t2508-adware-installed-even-though-i-clicked-decline), the Admin (apparently working for K-Lite) is blaming the stupid users:
QuoteThe official installer can show an offer during installation. It is clearly labelled as such, as the page is named "Additional Software Offer", plus the page explains that it is optional and can either be declined or accepted. The actual software isn't included. It is only downloaded once the offer has been accepted. The installer never installs anything that is potentially unwanted without permission from the user. So anyone that claims something got installed while they clicked decline is just lying to cover up their own mistake of blindly clicking through the installer without reading anything.

So I must be one of those stupid dumb users who blindly click on everything, thank you so much, K-Lite :icon14:

Another little GREAT nuisance: Either K-Lite or the "Web Companion" grab the video file extensions, and set them to Media Player Classic :icon_redface:

In short: 3gp videos have started working, which is a great plus (it seems a standard on Android phones), but be extremely cautious when installing K-Lite.
Title: Re: DirectShow transform
Post by: jj2007 on July 02, 2017, 07:13:52 PM
Back on topic: There is a little problem with the notification icons of codecs, see screenshot of the "personalise" option below. This happens both with Marinus' and my own player. Sometimes the area is flooded with this crap, they disappear when you hover over them with the mouse. Probably some COM interface needs to be released properly to prevent this.
Title: Re: DirectShow transform
Post by: Siekmanski on July 02, 2017, 07:31:07 PM
jj2007, thanks for the warning.

Microsoft has more surprises for us:

CoTaskMemFree,

void CoTaskMemFree(
  void pv
);

Passing into this function any invalid and, under some circumstances, NULL pointers result in unexpected termination of the application.

And it does, if I free the VIDEO_INFO.pBitMapBuffer and pass NULL to it, it result in unexpected termination of the application.
So, I removed this.

The result is when no codec is found ( "No combination of intermediate filters could be found to make the connection." ) to play the movie, the application now terminates in a normal way.

Also corrected a sloppy mistake at the end of the VideoGrabber routine, mov eax,S_FALSE ( was cmp eax,S_FALSE )   

Updated the sources in Reply #7 again...
Title: Re: DirectShow transform
Post by: sinsi on July 02, 2017, 07:35:33 PM
Off topic, the best codec pack I have found is the shark007 pack, both 32 and 64 bit.
Title: Re: DirectShow transform
Post by: Siekmanski on July 03, 2017, 11:24:23 PM
Found an interesting DirectShow codecs download site.  8)

http://www.free-codecs.com/video_codecs.htm

Here you can find codecs and download/install them separately.

This one is awesome: http://www.free-codecs.com/3dyd-youtube-source_download.htm  :t

Direct download link: http://www.free-codecs.com/download_soft.php?d=198626d75c1ab40d05ba49ded72db0e7&s=954&r=&f=3dyd-youtube-source.htm

I have installed it and now I can watch YouTube movies in my own application.
It works perfectly.  :biggrin:

Thinking of writing an audio grabber to save the music as a wav or mp3 file ripped from a YouTube movie.
Title: Re: DirectShow transform
Post by: adeyblue on July 05, 2017, 08:27:18 AM
You can setup a callback so you don't have to poll for when the data is available (ISampleGrabberCB). You can also (if supported) step the graph one video frame at a time which can help if you just want to process without necessarily displaying the video (IVideoFrameStep).

There's an example here that uses both (http://blog.airesoft.co.uk/code/dshowrotate.zip) with code (C++), video & exe that rotates each frame of the video 90 degrees with both GDI & GDI+ and writes them out (it'll create 92 bmp files), or just the code here (http://blog.airesoft.co.uk/code/dshowrotate.cpp).

It works here but as this thread's proved, with this stuff YMMV.
Title: Re: DirectShow transform
Post by: Siekmanski on July 05, 2017, 09:06:27 AM
Nice example. I'll have a closer look at the source code.

There are many ways in directshow to accomplish the same goal.
I'm trying to get a direct pointer to the bitmap data, the SampleGrabber needs an extra copy of the frame data and is just a waste of time.

The TextureRenderer filter seems to be what I'm looking for....
Title: Re: DirectShow transform
Post by: jj2007 on July 05, 2017, 09:18:11 AM
Quote from: adeyblue on July 05, 2017, 08:27:18 AM
You can setup a callback

That was our intention in the end - in windowless mode, get a pointer to the pixels, rotate as necessary, pass the pointer back to COM.

Do you have an idea if that is possible speed-wise? At 20 fps for example, only 50ms are available for the whole display, of which x may be needed for doing rotation, flipping etc.

Another option to investigate: grab the sample (which seems to be kind of a DIB ?), then BitBlt or stretchblt or whatever to the DC, and instead of letting the COM interface continue, discard the sample by passing it to the null renderer. Afterwards, Gdi+ can also do the rotation and other transformations. We could even add subtitles etc :P