mirror of
https://github.com/godotengine/godot.git
synced 2024-11-10 22:23:07 +00:00
optional streaming from thread for Theora
This commit is contained in:
parent
3ecc9e07b7
commit
fe2a9bc746
@ -155,6 +155,12 @@ public:
|
||||
inline int size() {
|
||||
return data.size();
|
||||
};
|
||||
|
||||
inline void clear() {
|
||||
read_pos = 0;
|
||||
write_pos = 0;
|
||||
|
||||
}
|
||||
|
||||
void resize(int p_power) {
|
||||
int old_size = size();
|
||||
|
@ -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,8 +786,34 @@ 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() {
|
||||
|
||||
file = NULL;
|
||||
@ -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);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -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:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user