summaryrefslogtreecommitdiff
path: root/drivers/theora
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2015-12-05 23:16:41 -0300
committerJuan Linietsky <reduzio@gmail.com>2015-12-05 23:16:41 -0300
commitfe2a9bc746df86510391435f89eb10f6e0eddec4 (patch)
tree75818ca9c2e54b88c0641515bfa57626a023fa2c /drivers/theora
parent3ecc9e07b7650725c8786d6af7c5f77ab6d94cc2 (diff)
optional streaming from thread for Theora
Diffstat (limited to 'drivers/theora')
-rw-r--r--drivers/theora/video_stream_theora.cpp117
-rw-r--r--drivers/theora/video_stream_theora.h26
2 files changed, 132 insertions, 11 deletions
diff --git a/drivers/theora/video_stream_theora.cpp b/drivers/theora/video_stream_theora.cpp
index f301bd7515..01b6f4d35e 100644
--- a/drivers/theora/video_stream_theora.cpp
+++ b/drivers/theora/video_stream_theora.cpp
@@ -7,11 +7,34 @@
int VideoStreamPlaybackTheora:: buffer_data() {
- char *buffer=ogg_sync_buffer(&oy,4096);
- int bytes=file->get_buffer((uint8_t*)buffer, 4096);
- ogg_sync_wrote(&oy,bytes);
- return(bytes);
+ char *buffer=ogg_sync_buffer(&oy,4096);
+
+#ifdef THEORA_USE_THREAD_STREAMING
+
+ int read;
+
+ do {
+ thread_sem->post();
+ read = MIN(ring_buffer.data_left(),4096);
+ if (read) {
+ ring_buffer.read((uint8_t*)buffer,read);
+ ogg_sync_wrote(&oy,read);
+ } else {
+ OS::get_singleton()->delay_usec(100);
+ }
+
+ } while(read==0);
+
+ return read;
+
+#else
+
+ int bytes=file->get_buffer((uint8_t*)buffer, 4096);
+ ogg_sync_wrote(&oy,bytes);
+ return(bytes);
+
+#endif
}
int VideoStreamPlaybackTheora::queue_page(ogg_page *page){
@@ -200,6 +223,14 @@ void VideoStreamPlaybackTheora::clear() {
}
ogg_sync_clear(&oy);
+#ifdef THEORA_USE_THREAD_STREAMING
+ thread_exit=true;
+ thread_sem->post(); //just in case
+ Thread::wait_to_finish(thread);
+ memdelete(thread);
+ thread=NULL;
+ ring_buffer.clear();
+#endif
//file_name = "";
theora_p = 0;
@@ -217,6 +248,7 @@ void VideoStreamPlaybackTheora::clear() {
void VideoStreamPlaybackTheora::set_file(const String& p_file) {
+ ERR_FAIL_COND(playing);
ogg_packet op;
th_setup_info *ts = NULL;
@@ -227,7 +259,17 @@ void VideoStreamPlaybackTheora::set_file(const String& p_file) {
file = FileAccess::open(p_file, FileAccess::READ);
ERR_FAIL_COND(!file);
+#ifdef THEORA_USE_THREAD_STREAMING
+ thread_exit=false;
+ thread_eof=false;
+ //pre-fill buffer
+ int to_read = ring_buffer.space_left();
+ int read = file->get_buffer(read_buffer.ptr(),to_read);
+ ring_buffer.write(read_buffer.ptr(),read);
+ thread=Thread::create(_streaming_thread,this);
+
+#endif
ogg_sync_init(&oy);
@@ -415,6 +457,8 @@ void VideoStreamPlaybackTheora::set_file(const String& p_file) {
buffering=true;
time=0;
audio_frames_wrote=0;
+
+
};
float VideoStreamPlaybackTheora::get_time() const {
@@ -436,13 +480,16 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
return;
};
+#ifdef THEORA_USE_THREAD_STREAMING
+ thread_sem->post();
+#endif
+
//double ctime =AudioServer::get_singleton()->get_mix_time();
//print_line("play "+rtos(p_delta));
time+=p_delta;
if (videobuf_time>get_time()) {
-
return; //no new frames need to be produced
}
@@ -573,21 +620,23 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
if(videobuf_time>=get_time()) {
frame_done=true;
- print_line("frame!");
+
} else{
/*If we are too slow, reduce the pp level.*/
pp_inc=pp_level>0?-1:0;
- print_line("skip!");
}
}
} else {
- print_line("no packet..");
+
break;
}
}
-
+#ifdef THEORA_USE_THREAD_STREAMING
+ if (file && thread_eof && ring_buffer.data_left()==0) {
+#else
if (file && /*!videobuf_ready && */ file->eof_reached()) {
+#endif
printf("video done, stopping\n");
stop();
return;
@@ -633,6 +682,7 @@ void VideoStreamPlaybackTheora::update(float p_delta) {
else if(tdiff<ti.fps_denominator*0.05/ti.fps_numerator){
pp_inc=pp_level>0?-1:0;
}
+
}
video_write();
@@ -644,15 +694,21 @@ void VideoStreamPlaybackTheora::play() {
if (!playing)
time=0;
+ else {
+ stop();
+ }
+
playing = true;
delay_compensation=Globals::get_singleton()->get("audio/video_delay_compensation_ms");
delay_compensation/=1000.0;
+
};
void VideoStreamPlaybackTheora::stop() {
if (playing) {
+
clear();
set_file(file_name); //reset
}
@@ -730,7 +786,33 @@ int VideoStreamPlaybackTheora::get_mix_rate() const{
return vi.rate;
}
+#ifdef THEORA_USE_THREAD_STREAMING
+
+
+void VideoStreamPlaybackTheora::_streaming_thread(void *ud) {
+
+ VideoStreamPlaybackTheora *vs=(VideoStreamPlaybackTheora*)ud;
+
+ while(!vs->thread_exit) {
+
+ //just fill back the buffer
+ if (!vs->thread_eof) {
+
+ int to_read = vs->ring_buffer.space_left();
+ if (to_read) {
+ int read = vs->file->get_buffer(vs->read_buffer.ptr(),to_read);
+ vs->ring_buffer.write(vs->read_buffer.ptr(),read);
+ vs->thread_eof=vs->file->eof_reached();
+ }
+
+
+ }
+
+ vs->thread_sem->wait();
+ }
+}
+#endif
VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() {
@@ -749,14 +831,31 @@ VideoStreamPlaybackTheora::VideoStreamPlaybackTheora() {
audio_track=0;
delay_compensation=0;
audio_frames_wrote=0;
+
+#ifdef THEORA_USE_THREAD_STREAMING
+ int rb_power = nearest_shift(RB_SIZE_KB*1024);
+ ring_buffer.resize(rb_power);
+ read_buffer.resize(RB_SIZE_KB*1024);
+ thread_sem=Semaphore::create();
+ thread=NULL;
+ thread_exit=false;
+ thread_eof=false;
+
+#endif
};
VideoStreamPlaybackTheora::~VideoStreamPlaybackTheora() {
+#ifdef THEORA_USE_THREAD_STREAMING
+
+ memdelete(thread_sem);
+#endif
clear();
if (file)
memdelete(file);
+
+
};
diff --git a/drivers/theora/video_stream_theora.h b/drivers/theora/video_stream_theora.h
index 5540f050f9..3d88ba4e4b 100644
--- a/drivers/theora/video_stream_theora.h
+++ b/drivers/theora/video_stream_theora.h
@@ -6,9 +6,13 @@
#include "theora/theoradec.h"
#include "vorbis/codec.h"
#include "os/file_access.h"
-
+#include "ring_buffer.h"
#include "io/resource_loader.h"
#include "scene/resources/video_stream.h"
+#include "os/thread.h"
+#include "os/semaphore.h"
+
+//#define THEORA_USE_THREAD_STREAMING
class VideoStreamPlaybackTheora : public VideoStreamPlayback {
@@ -66,7 +70,25 @@ class VideoStreamPlaybackTheora : public VideoStreamPlayback {
AudioMixCallback mix_callback;
void* mix_udata;
- int audio_track;
+#ifdef THEORA_USE_THREAD_STREAMING
+
+ enum {
+ RB_SIZE_KB=1024
+ };
+
+ RingBuffer<uint8_t> ring_buffer;
+ Vector<uint8_t> read_buffer;
+ bool thread_eof;
+ Semaphore *thread_sem;
+ Thread *thread;
+ volatile bool thread_exit;
+
+ static void _streaming_thread(void *ud);
+
+#endif
+
+
+ int audio_track;
protected: