void VideoStream::sendPacket(VideoStream *stream) { while (stream->m_run) { // dequeue the picture if (!stream->m_frame) stream->m_frame = stream->m_frameBuffer.dequeue(); if (!stream->m_frame) continue; qreal pts = av_frame_get_best_effort_timestamp(stream->m_frame.data()) * stream->timeBase().value(); qreal diff = pts - stream->globalClock()->clock(); qreal delay = pts - stream->m_lastPts; // skip or repeat frame. We take into account the // delay to compute the threshold. I still don't know // if it is the best guess double syncThreshold = qBound(AV_SYNC_THRESHOLD_MIN, delay, AV_SYNC_THRESHOLD_MAX); if (!qIsNaN(diff) && qAbs(diff) < AV_NOSYNC_THRESHOLD && delay < AV_SYNC_FRAMEDUP_THRESHOLD) { // video is backward the external clock. if (diff <= -syncThreshold) { stream->m_frame = AVFramePtr(); stream->m_lastPts = pts; continue; } else if (diff > syncThreshold) { // video is ahead the external clock. QThread::usleep(1e6 * (diff - syncThreshold)); continue; } } else stream->globalClock()->setClock(pts); stream->m_clockDiff = diff; QbPacket oPacket = stream->convert(stream->m_frame.data()); emit stream->oStream(oPacket); emit stream->frameSent(); stream->m_frame = AVFramePtr(); stream->m_lastPts = pts; } }
AVFramePtr FrameBuffer::dequeue() { this->m_mutex.lock(); if (this->m_buffer.isEmpty()) if (!this->m_bufferNotEmpty.wait(&this->m_mutex, THREAD_WAIT_LIMIT)) { this->m_mutex.unlock(); return AVFramePtr(); } AVFramePtr frame; if (!this->m_buffer.isEmpty()) { frame = this->m_buffer.dequeue(); emit this->sizeChanged(this->m_buffer.size()); if (this->m_buffer.size() < this->m_maxSize) this->m_bufferNotFull.wakeAll(); } this->m_mutex.unlock(); return frame; }
AVFramePtr dt_create_decoded_frame() { AVFramePtr frame(avcodec_alloc_frame(), details::_AVFrameDestroy()); if (NULL == frame.get()) { BOOST_THROW_EXCEPTION(errors::bad_alloc()); DT_IF_DISABLE_EXCEPTIONS(return AVFramePtr()); }
void FrameBuffer::enqueue(AVFrame *frame) { this->m_mutex.lock(); if (this->m_buffer.size() >= this->m_maxSize) this->m_bufferNotFull.wait(&this->m_mutex); this->m_buffer.enqueue(AVFramePtr(frame, this->deleteFrame)); this->m_bufferNotEmpty.wakeAll(); emit this->sizeChanged(this->m_buffer.size()); this->m_mutex.unlock(); }