1/**
2 * Copyright (c) 2006-2023 LOVE Development Team
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty. In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 *
8 * Permission is granted to anyone to use this software for any purpose,
9 * including commercial applications, and to alter it and redistribute it
10 * freely, subject to the following restrictions:
11 *
12 * 1. The origin of this software must not be misrepresented; you must not
13 * claim that you wrote the original software. If you use this software
14 * in a product, an acknowledgment in the product documentation would be
15 * appreciated but is not required.
16 * 2. Altered source versions must be plainly marked as such, and must not be
17 * misrepresented as being the original software.
18 * 3. This notice may not be removed or altered from any source distribution.
19 **/
20
21// STL
22#include <vector>
23
24// LOVE
25#include "Video.h"
26#include "common/delay.h"
27#include "timer/Timer.h"
28
29namespace love
30{
31namespace video
32{
33namespace theora
34{
35
36Video::Video()
37{
38 workerThread = new Worker();
39 workerThread->start();
40}
41
42Video::~Video()
43{
44 delete workerThread;
45}
46
47VideoStream *Video::newVideoStream(love::filesystem::File *file)
48{
49 TheoraVideoStream *stream = new TheoraVideoStream(file);
50 workerThread->addStream(stream);
51 return stream;
52}
53
54const char *Video::getName() const
55{
56 return "love.video.theora";
57}
58
59Worker::Worker()
60 : stopping(false)
61{
62 threadName = "VideoWorker";
63}
64
65Worker::~Worker()
66{
67 stop();
68}
69
70void Worker::addStream(TheoraVideoStream *stream)
71{
72 love::thread::Lock l(mutex);
73 streams.push_back(stream);
74 cond->broadcast();
75}
76
77void Worker::stop()
78{
79 {
80 love::thread::Lock l(mutex);
81 stopping = true;
82 cond->broadcast();
83 }
84
85 owner->wait();
86}
87
88void Worker::threadFunction()
89{
90 double lastFrame = love::timer::Timer::getTime();
91
92 while (true)
93 {
94 love::sleep(2);
95
96 love::thread::Lock l(mutex);
97
98 while (!stopping && streams.empty())
99 {
100 cond->wait(mutex);
101 lastFrame = love::timer::Timer::getTime();
102 }
103
104 if (stopping)
105 return;
106
107 double curFrame = love::timer::Timer::getTime();
108 double dt = curFrame-lastFrame;
109 lastFrame = curFrame;
110
111 for (auto it = streams.begin(); it != streams.end(); ++it)
112 {
113 TheoraVideoStream *stream = *it;
114 if (stream->getReferenceCount() == 1)
115 {
116 // We're the only ones left
117 streams.erase(it);
118 break;
119 }
120
121 stream->threadedFillBackBuffer(dt);
122 }
123 }
124}
125
126} // theora
127} // video
128} // love
129