void AVDemuxThread::nextFrame() { // clock type will be wrong if no lock because slot frameDeliveredNextFrame() is in video thread QMutexLocker locker(&next_frame_mutex); Q_UNUSED(locker); pause(true); // must pause AVDemuxThread (set user_paused true) AVThread* av[] = {video_thread, audio_thread}; bool connected = false; for (size_t i = 0; i < sizeof(av)/sizeof(av[0]); ++i) { AVThread *t = av[i]; if (!t) continue; // set clock first if (clock_type < 0) clock_type = (int)t->clock()->isClockAuto() + 2*(int)t->clock()->clockType(); t->clock()->setClockType(AVClock::VideoClock); t->scheduleFrameDrop(false); t->pause(false); t->packetQueue()->blockFull(false); if (!connected) { connect(t, SIGNAL(frameDelivered()), this, SLOT(frameDeliveredNextFrame()), Qt::DirectConnection); connected = true; } } emit requestClockPause(false); nb_next_frame.ref(); pauseInternal(false); }
void AVDemuxThread::seekInternal(qint64 pos, SeekType type) { AVThread* av[] = { audio_thread, video_thread}; qDebug("seek to %s %lld ms (%f%%)", QTime(0, 0, 0).addMSecs(pos).toString().toUtf8().constData(), pos, double(pos - demuxer->startTime())/double(demuxer->duration())*100.0); demuxer->setSeekType(type); demuxer->seek(pos); if (ademuxer) { ademuxer->setSeekType(type); ademuxer->seek(pos); } AVThread *watch_thread = 0; // TODO: why queue may not empty? int sync_id = 0; for (size_t i = 0; i < sizeof(av)/sizeof(av[0]); ++i) { AVThread *t = av[i]; if (!t) continue; if (!sync_id) sync_id = t->clock()->syncStart(!!audio_thread + !!video_thread); Q_ASSERT(sync_id != 0); qDebug("demuxer sync id: %d/%d", sync_id, t->clock()->syncId()); t->packetQueue()->clear(); t->requestSeek(); // TODO: the first frame (key frame) will not be decoded correctly if flush() is called. //PacketBuffer *pb = t->packetQueue(); //qDebug("%s put seek packet. %d/%d-%.3f, progress: %.3f", t->metaObject()->className(), pb->buffered(), pb->bufferValue(), pb->bufferMax(), pb->bufferProgress()); t->packetQueue()->setBlocking(false); // aqueue bufferValue can be small (1), we can not put and take Packet pkt; pkt.pts = qreal(pos)/1000.0; pkt.position = sync_id; t->packetQueue()->put(pkt); t->packetQueue()->setBlocking(true); // blockEmpty was false when eof is read. if (isPaused()) { //TODO: deal with pause in AVThread? t->pause(false); watch_thread = t; } } if (watch_thread) { pauseInternal(false); Q_EMIT requestClockPause(false); // need direct connection // direct connection is fine here connect(watch_thread, SIGNAL(seekFinished(qint64)), this, SLOT(seekOnPauseFinished()), Qt::DirectConnection); } }