42 : renderer(rb), Thread(
"player"), video_position(1), audio_position(0)
43 , audioPlayback(new
openshot::AudioPlaybackThread())
44 , videoPlayback(new
openshot::VideoPlaybackThread(rb))
45 , videoCache(new
openshot::VideoCacheThread())
46 , speed(1), reader(NULL), last_video_position(1)
50 PlayerPrivate::~PlayerPrivate()
59 void PlayerPrivate::run()
66 if (reader->info.has_audio)
67 audioPlayback->startThread(8);
68 if (reader->info.has_video) {
69 videoCache->startThread(2);
70 videoPlayback->startThread(4);
73 using std::chrono::duration_cast;
76 using ms = std::chrono::milliseconds;
77 using double_ms = std::chrono::duration<double, ms::period>;
80 const auto frame_duration = double_ms(1000.0 / reader->info.fps.ToDouble());
82 while (!threadShouldExit()) {
84 const auto time1 = std::chrono::high_resolution_clock::now();
90 if ((speed == 0 && video_position == last_video_position)
91 || (video_position > reader->info.video_length)
94 std::this_thread::sleep_for(frame_duration);
99 videoPlayback->frame = frame;
100 videoPlayback->render.signal();
103 last_video_position = video_position;
106 int64_t video_frame_diff = 0;
107 if (reader->info.has_audio && reader->info.has_video) {
110 audioPlayback->Seek(video_position);
113 audio_position = audioPlayback->getCurrentFramePosition();
114 video_frame_diff = video_position - audio_position;
118 const auto time2 = std::chrono::high_resolution_clock::now();
121 const auto render_time = double_ms(time2 - time1);
124 auto sleep_time = duration_cast<ms>(frame_duration - render_time);
127 ZmqLogger::Instance()->AppendDebugMethod(
"PlayerPrivate::run (determine sleep)",
"video_frame_diff", video_frame_diff,
"video_position", video_position,
"audio_position", audio_position,
"speed", speed,
"render_time(ms)", render_time.count(),
"sleep_time(ms)", sleep_time.count());
130 if (video_frame_diff > 0 && reader->info.has_audio && reader->info.has_video) {
138 sleep_time += duration_cast<ms>(video_frame_diff * frame_duration);
141 else if (video_frame_diff < -10 && reader->info.has_audio && reader->info.has_video) {
143 video_position += std::fabs(video_frame_diff) / 2;
144 sleep_time = sleep_time.zero();
148 if (sleep_time > sleep_time.zero()) {
149 std::this_thread::sleep_for(sleep_time);
156 std::shared_ptr<openshot::Frame> PlayerPrivate::getFrame()
160 if (video_position + speed >= 1 && video_position + speed <= reader->info.video_length)
161 video_position = video_position + speed;
163 if (frame && frame->number == video_position && video_position == last_video_position) {
170 videoCache->setCurrentFramePosition(video_position);
173 return reader->GetFrame(video_position);
176 }
catch (
const ReaderClosed & e) {
178 }
catch (
const OutOfBoundsFrame & e) {
181 return std::shared_ptr<openshot::Frame>();
185 bool PlayerPrivate::startPlayback()
187 if (video_position < 0)
return false;
195 void PlayerPrivate::stopPlayback(
int timeOutMilliseconds)
197 if (audioPlayback->isThreadRunning() && reader->info.has_audio) audioPlayback->stopThread(timeOutMilliseconds);
198 if (videoCache->isThreadRunning() && reader->info.has_video) videoCache->stopThread(timeOutMilliseconds);
199 if (videoPlayback->isThreadRunning() && reader->info.has_video) videoPlayback->stopThread(timeOutMilliseconds);
200 if (isThreadRunning()) stopThread(timeOutMilliseconds);
Header file for all Exception classes.
Source file for PlayerPrivate class.
This is the base class of all Renderers in libopenshot.
This namespace is the default namespace for all code in the openshot library.