Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pause player at first frame immediately after video load with optional seek #637

Closed
junaid-ebrahim opened this issue Jun 1, 2016 · 11 comments

Comments

@junaid-ebrahim
Copy link

junaid-ebrahim commented Jun 1, 2016

Hi
I would like to use two or more players to load different video files , seek to a different position within each player and pause it there. The problem I am having is that the renderer is blank on initial load even after the "started" signal is fired so pausing in the started slot still shows a blank renderer, the only way for me to workaround this is to wait for around half a second and then call pause again. It would be great if there was a way to load, seek and then pause at that position using the AVPlayer object without waiting for playback to happen. Below is a snippet of what I am trying to do. I think the problem is that the pause is ignored because the player is still setting up the threads even though asyncLoad is false, maybe queue the pause request while the initial load is happening and then action it once the first frame has been decoded and sent to renderer. Not sure if this is an issue or an enhancement.

            player1->setFile("file1.flv")
            player1->play();
            QThread::msleep(500);  // This is my workaround , without this renderer is blank
            player1->setPosition(0*1000LL); // seek to start
            player1->pause(true);

            player2->setFile("file2.flv")
            player2->play();
            QThread::msleep(500); // This is my workaround , without this renderer is blank
            player2->setPosition(5*1000LL); // seek to 5 seconds into video
            player2->pause(true);
    // and now I want to resume playback to see the videos playing  side by side
    player1->pause(false);
    player2->pause(false);
@junaid-ebrahim
Copy link
Author

Just an update , it seems to work even if I reduce the QThread::msleep(500) to QThread::usleep(1) . That's 500 MILLIseconds to 1 MICROsecond, this makes it a better workaround since the time delay is much smaller.

@wang-bin
Copy link
Owner

wang-bin commented Jun 1, 2016

setPosition/seek is async too. You have to pause when seekFinished is emitted. A possible solution is

    player.setRenderer(this);
    connect(&player, &AVPlayer::started, [this](){
        connect(&player, &AVPlayer::seekFinished, this, &PlayerWindow::pauseOnSeek);
        player.setPosition(5*1000LL);
    });
....
void pauseOnSeek() {
    player.pause(true);
    disconnect(&player, &AVPlayer::seekFinished, this, &PlayerWindow::pauseOnSeek);
}

@junaid-ebrahim
Copy link
Author

Ok, that seems to work but I noticed a small issue , I have to sleep for a time immediately after the play() call otherwise the "seekFinished" never gets called, I think that the whole signal and slots are still being setup in the player and the setPosition call immediately after play is ignored. I assume it is only safe to make seek calls to the player only after the started signal is emitted ?

@wang-bin
Copy link
Owner

wang-bin commented Jun 2, 2016

Are you using the latest code? This issue should be fixed, see #616

@junaid-ebrahim
Copy link
Author

Have not tried the latest code , will do and confirm soon

@junaid-ebrahim
Copy link
Author

Tested and confirmed that seekFinished gets called if a seek immediately follows a play() call , this is only if async load is set to false, i.e. player->setAsyncLoad(false)

@wang-bin
Copy link
Owner

wang-bin commented Jun 3, 2016

You have to call seek in your slot connected to AVPlayer::started()

@wang-bin
Copy link
Owner

wang-bin commented Jun 3, 2016

I can add AVPlayer::waitForStarted() if necessary

@junaid-ebrahim
Copy link
Author

I suppose this would help with load speed in the case of loading multiple videos asynchronously then waiting for them to finish before calling seek on them (all within one function). I don't think this is needed though as the started signal is fine for my purposes.

I think the 3 main reasons for my confusion was

  1. I did not know when the earliest time to call seek was, and the answer would be the "started" signal.
  2. When was the earliest time to call pause, and the answer would be the "seekFinished" signal.
  3. The "started" signal does not mean that the video has reached the renderer yet so pause should not be called in here.

Maybe a helpful comment and possible future documentation note would be to indicate the above. Thanks a lot for your assistance.

@wang-bin
Copy link
Owner

wang-bin commented Jun 6, 2016

I think about waitForStarted(). It's not necessary.

wang-bin added a commit that referenced this issue Jun 25, 2016
Then #637 can be simplified as
player.setStartPosition(5000); ;
connect(&player, &AVPlayer::seekFinished, this,
&PlayerWindow::pauseOnSeek);
@umod47
Copy link

umod47 commented Apr 20, 2018

I have tried this solution and it works...
unless I try to play MJPEG-compressed video in mp4 container.
The signal "seekFinished" is not emitted when I call seek after "started" is emitted. What's more strange, audio is played, the time is displayed, but the frames are not switched (the first frame keeps being displayed).
Here is the log:

QtAV 1.12.0(Mar 28 2018, 01:50:42)
...
eglGetCurrentDisplay=>eglGetCurrentDisplay@0
resolving WGL_NV_DX_interop...
Playback started (this is where "play" is called)
AudioDecoder::id("FFmpeg")
onPlaybackStarted (this is where "started" is caught)
"[ShaderManager] cache a new shader material type(10): gl material 16to8bit: 0, planar: 1, has alpha: 0, 2d texture: 1, 2nd plane rg: 0, xyz: 0"
creating VBO...
creating VAO...
vao updated
geometry attributes changed, rebind vao...
geometry updated

However, "seekFinished" works later. When some time passes and the videowidget appears on the screen, I can pause and play (leaving first frame displayed), but the video restores to normal behaviour only when I seek to some time by hand.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants