none
repeated SetPositions not updating EVR display

    Question

  • I'm having an issue with the EVR not updating it's display when I call SetPositions repeatedly when paused. The same operation works fine when using VMR9. There was a previous thread describing how I have come suspect that there may be a problem with the EVR. I'm just trying to show ten frames of video which are one second apart. What I see is the 1st frame and the 10th frame with no intermediate frames being shown in the EVR. I have tried calling RepaintVideo between each call to SetPositions but that doesn't do anything. Putting a Sleep(1000) between each call to SetPositions does allow me to view each of the ten video frames. I'm decoding H.264 video.

    The pseudo code to replicate the issue goes something like this...

    int count = 0;
    while(count++ < 10) {
    	
    	// get the current position...
    	LONGLONG t = 0;
    	hr = GetPosition(t);
    	CHECK_HRESULT(hr);
    
    	// add some time (1 second)...
    	t += 10000000;
    
    	// move to the new position...
    	hr = SetPosition(t);
    	CHECK_HRESULT(hr);
    }
    
    

    After the SetPosition I have also tried checking the state to see if it was VFW_S_STATE_INTERMEDIATE, which it never is. When using the VMR9 then the state is often VFW_S_STATE_INTERMEDIATE so a few repeated checks on the state after SetPositions gets around that.

    Any idea how to update the display after calling SetPositions repeatedly when using the EVR?

     

     

     

    Monday, October 24, 2011 2:16 PM

Answers

  • I've tried adding a wait for the graph to queue up data in my own application Easy HDTV DVR, and I'm getting the same result as you, it doesn't work with the EVR.

    With the graph I'm using IMediaControl::GetState does return  VFW_S_CANT_CUE, but this can be worked arround by checking the render filter's state directly with IMediaFilter::GetState.

    The VRM7 and VMR9 both return VFW_S_STATE_INTERMEDIATE after a SetPositions call, but the EVR does not.  There's nothing I can find in the documentation that says wether or not a render should return VFW_S_STATE_INTERMEDIATE after a call to SetPositions.

    I've also tried my suggestion of calling Stop, SetPositions, Pause, then waiting for VFW_S_STATE_INTERMEDIATE to clear, this works on the VRM7 and VMR9, but does not work on the EVR.  The EVR clears the image after a call to Stop, which is contrary to the what the documentation says a renderer should do.  See http://msdn.microsoft.com/en-us/library/windows/desktop/dd373423(v=vs.85).aspx under the section "Handling State Changes and Pause Completion"

    Unless Microsoft changes one these behaviors, I think you're pretty much out of luck in doing what you want.


    Greg Christensen
    Enigma Industries

    • Marked as answer by flobad0b Tuesday, November 22, 2011 4:59 PM
    Tuesday, November 22, 2011 4:13 PM

All replies

  • Just a 'bump' really. I haven't made any progress with this issue, so this is a blatant cry for help.
    Thursday, November 17, 2011 1:55 PM
  • It takes some time for the graph to queue up the data after a call to SetPositions, so you definately need to wait somehow. I don't believe calling SetPositions will change the graph's state, so calling GetState won't tell you anything. I'm just thinking out loud here, as I haven't done exactly what you're trying to do, but you might try doing something to change the graph's state, try calling Stop then SetPositions then Pause and wait for the transisition to paused to complete.


    Greg Christensen
    Enigma Industries


    • Edited by gc04 Thursday, November 17, 2011 10:16 PM
    Thursday, November 17, 2011 9:02 PM
  • Hi Greg. I have code to wait after the call to set positions which ensures the state is not indeterminate before the method exits. I have also tried adding in calls to RepaintVideo to see if that makes any difference. The graph is paused when I call SetPositions repeatedly and, according to the docs, a setpositions while paused should update the display. If I put in a ::Sleep(1000) after each setpositions then it's ok. So, there must be something else I need to wait for which I have not taken into account. Possibly EVR related since the code works ok on VMR9. I also tried flushing the graph (setpositions(NULL,nopos,NULL,nopos)). Hmmmm. 

    HRESULT CGraph::SetPosition(LONGLONG pos)
    {
    	HRESULT hr;
    
    	if(!m_pMediaSeeking) {
    		ASSERT(FALSE);
    		return E_FAIL;
    	}
    
    	// ensure pos is sensible...
    	if(pos < 0)
    		pos = 0;
    
    	if(IsRunning())
    		ASSERT(FALSE);
    
    	CString s;
    	s.Format("CGraph::SetPosition %I64d nsu or %.3lf sec\n", pos, ::RefTimeToSeconds(pos));
    	TRACE(s);
    
    	LONGLONG currentPos = 0;
    	hr = m_pMediaSeeking->GetCurrentPosition(&currentPos);
    	ASSERT(SUCCEEDED(hr));
    
    	if(SUCCEEDED(hr) && pos == currentPos) {
    		TRACE("SetPosition aborted (pos == currentPos) %.3lf sec\n", ::RefTimeToSeconds(pos));
    		return S_OK;
    	}
    
    	hr = m_pMediaSeeking->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
    	switch(hr) {
    	case E_INVALIDARG:
    		ASSERT(FALSE);
    		break;
    	case E_NOTIMPL:
    		ASSERT(FALSE);
    		break;
    	case E_POINTER:
    		ASSERT(FALSE);
    		break;
    	case E_FAIL:
    		// probably seeked off end of video.
    		return hr;
    	}
    	CHECK_HRESULT(hr);
    
    	// check the state to see if the operation is complete...
    	FILTER_STATE fs;
    	while(m_pMediaControl->GetState(10, (OAFilterState*)&fs) == VFW_S_STATE_INTERMEDIATE) {
    		Sleep(1);
    	}
    
    	if(hr != S_OK) {
    		if(hr == VFW_S_STATE_INTERMEDIATE) TRACE("CGraph::SetPosition: VFW_S_STATE_INTERMEDIATE\n");
    		if(hr == VFW_S_CANT_CUE) TRACE("CGraph::SetPosition: VFW_S_CANT_CUE\n");
    		if(hr == E_FAIL) TRACE("CGraph::SetPosition: E_FAIL\n");
    		ASSERT(FALSE);
    	}
    
    	return hr;
    }

     

    • Edited by flobad0b Friday, November 18, 2011 8:48 AM added some code
    Friday, November 18, 2011 8:47 AM
  •  

    	FILTER_STATE fs;
    	while(m_pMediaControl->GetState(10, (OAFilterState*)&fs) == VFW_S_STATE_INTERMEDIATE) {
    		Sleep(1);
    	}
    
    	if(hr != S_OK) {
    		if(hr == VFW_S_STATE_INTERMEDIATE) TRACE("CGraph::SetPosition: VFW_S_STATE_INTERMEDIATE\n");
    		if(hr == VFW_S_CANT_CUE) TRACE("CGraph::SetPosition: VFW_S_CANT_CUE\n");
    		if(hr == E_FAIL) TRACE("CGraph::SetPosition: E_FAIL\n");
    		ASSERT(FALSE);
    	}
    
    
    

    I see you testing for VFW_S_CANT_CUE, but you're not setting hr with the return value of GetState.  Try checking the return value of GetState for VFW_S_CANT_CUE.

     


    Greg Christensen
    Enigma Industries




    • Edited by gc04 Friday, November 18, 2011 5:46 PM
    Friday, November 18, 2011 4:34 PM
  • I revised this problema using the Microsoft DTV-DVD Video Decoder and AVI codec 'CRAM' on Windows 7 (instead of using entirely hand written filter chain on Windows XP) (both end up in VMR9 and no sound path). So this time each MPEG-2 ends up with VFW_S_CANT_CUE but AVI works fine.


    So my guessing is that, for whatever a reason, your source filter - since neither H.264 nor MPEG-2 are indexed - just plays it safe reporting VFW_S_CANT_CUE. That is to say, they are not designed for that type of use. There is simply no wait function and thats a feature. So I suggest you use creativity, e.g. by altering the playback rate you can almost achieve what you were seeking for.

    If, however, seeking works in the delivering thread, then GetState(INFINITE,..) would work absolutely fine.

    I don't know how EVR and VMR9 behave differently...


    • Edited by Thomas.W32 Monday, November 21, 2011 8:11 PM type'o
    Monday, November 21, 2011 8:08 PM
  • Hi Greg. Thanks for spotting that one, I'm now checking the result of GetStatus correctly. Although it doesn't help me in this situation, I'm sure that will prevent future issues.

    	// check the state to see if the operation is complete...
    	FILTER_STATE fs;
    	hr = m_pMediaControl->GetState(5, (OAFilterState*)&fs);
    	while(hr == VFW_S_STATE_INTERMEDIATE) {
    		Sleep(5);
    		hr = m_pMediaControl->GetState(5, (OAFilterState*)&fs);
    	}
    

     

    Tuesday, November 22, 2011 10:34 AM
  • Hi Thomas. I don't get any VFW_S_CANT_CUE return values back from GetState (even after the fix from Greg).
    Tuesday, November 22, 2011 10:44 AM
  • I've tried adding a wait for the graph to queue up data in my own application Easy HDTV DVR, and I'm getting the same result as you, it doesn't work with the EVR.

    With the graph I'm using IMediaControl::GetState does return  VFW_S_CANT_CUE, but this can be worked arround by checking the render filter's state directly with IMediaFilter::GetState.

    The VRM7 and VMR9 both return VFW_S_STATE_INTERMEDIATE after a SetPositions call, but the EVR does not.  There's nothing I can find in the documentation that says wether or not a render should return VFW_S_STATE_INTERMEDIATE after a call to SetPositions.

    I've also tried my suggestion of calling Stop, SetPositions, Pause, then waiting for VFW_S_STATE_INTERMEDIATE to clear, this works on the VRM7 and VMR9, but does not work on the EVR.  The EVR clears the image after a call to Stop, which is contrary to the what the documentation says a renderer should do.  See http://msdn.microsoft.com/en-us/library/windows/desktop/dd373423(v=vs.85).aspx under the section "Handling State Changes and Pause Completion"

    Unless Microsoft changes one these behaviors, I think you're pretty much out of luck in doing what you want.


    Greg Christensen
    Enigma Industries

    • Marked as answer by flobad0b Tuesday, November 22, 2011 4:59 PM
    Tuesday, November 22, 2011 4:13 PM
  • OK, thanks for all your efforts Greg!
    Tuesday, November 22, 2011 4:59 PM
  • I have code working with EVR and scroll bars

    With SB_THUMBTRACK
    pMediaControl->Pause();
    pMediaPosition->put_CurrentPostion(reftime);

    With SB_THUMBPOSITION
    pMediaPosition->put_currentPosition(reftime);
    pMediaControl->Run();

    No state checks, works with any renderer.

    Sunday, December 04, 2011 6:05 AM
  • I have code working with EVR and scroll bars

    With SB_THUMBTRACK
    pMediaControl->Pause();
    pMediaPosition->put_CurrentPostion(reftime);

    With SB_THUMBPOSITION
    pMediaPosition->put_currentPosition(reftime);
    pMediaControl->Run();

    No state checks, works with any renderer.

    That's interesting Douglas, I didn't try the IMediaPosition interface, just IMediaSeeking since the IMediaPosition one is supposed to be depreciated. I'll give it a go.
    Sunday, December 04, 2011 1:46 PM
  • Docs state its depreciated for CE but for Desktops it just states applications should use IMediaSeeking, but if it does not work correctly, you have to do what you have to do.
    Monday, December 05, 2011 1:00 AM
  • I tried the IMediaPosition interface but, for my choice of filters, it does not perform any better for me with the EVR. I guess it's decoder filter dependent.

    However, I have got the IMediaSeeking interface to work, finally, with the EVR. All I had to do was supply the AM_SEEKING_SeekToKeyFrame option to SetPositions. Now I can call SetPositions repeatedly and the display updates. Thankyou to everyone who contributed in this thread :)

    Monday, December 05, 2011 11:27 AM
  • Hi,

    i know that this is an old post, but as i encountered this kind of problems now, i push a comment on this thread.

    On my side, i had a black background drawn on each call to Setpositions(). To resolve this issue, i added the following line in initialisation code:

    pMFVideoDisplayControl->SetRenderingPrefs( MFVideoRenderPrefs::MFVideoRenderPrefs_DoNotRepaintOnStop );
    regards,

    Pascal

    Thursday, April 13, 2017 3:42 PM