Details
-
Bug
-
Resolution: Unresolved
-
Not Evaluated
-
None
-
1.2.0
-
None
-
Windows XP SP3 32-bit ; Qt libraries 4.7.3 for Windows (VS 2008) ; QtMobility opensource src 1.2 (only the module Multimedia was compiled) ; MSVC 2008.
Description
Reading videos under Windows using a QMediaPlayer object connected to a QVideoWidget object and using the method QMediaPlayer::play() works very well.
But, if I try to read the same video, frame by frame (or position by position) using the QMediaPlayer::setPositions methods and a QTimer (timeout set every 40 ms: playback at 25Hz), then the content of the QVideoWidget object can freeze for a part of the video and play well for another part. In some case, the content is freezed every time.
As using the same code under MacOS 10.5 with the Quicktime backend didn't have this problem, I looked in the code of the Directshow backend and especialy in the file plugins/multimedia/directshow/player/directshowplayerservice.cpp and the method DirectShowPlayerService::doSeek.
Looking on the web, it seems that the method IMediaSeeking::seekPosition set the new position, but the media can be in an intermediate state (seeking to the given time?) and then has no the time to extract the frame before the next call of seekPosition().
This problem doesn't occur every time. For example a video at 100 FPS has not this problem while a video at 25 FPS has it. In this case, the codec is the same (MS-MPEG4 v1).
I proposed here a small fix which check the state of the media and wait until the media is not in an intermediate state.
/* File plugins/multimedia/directshow/player/directshowplayerservice.cpp, line 914 */ LONGLONG maximum = 0; m_playbackRange = SUCCEEDED(seeking->GetAvailable(&minimum, &maximum)) ? QMediaTimeRange( minimum / qt_directShowTimeScale, maximum / qt_directShowTimeScale) : QMediaTimeRange(); locker->unlock(); seeking->SetPositions( &seekPosition, AM_SEEKING_AbsolutePositioning, 0, AM_SEEKING_NoPositioning); locker->relock(); /* Suggested patch */ if (IMediaControl *control = com_cast<IMediaControl>(m_graph, IID_IMediaControl)) { FILTER_STATE fs; control->GetState(INFINITE, (OAFilterState*)&fs); control->Release(); } /* End patch*/ seeking->GetCurrentPosition(¤tPosition); m_position = currentPosition / qt_directShowTimeScale; seeking->Release(); } else { m_position = 0; }