diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gles2/rasterizer_gles2.cpp | 20 | ||||
-rw-r--r-- | drivers/png/resource_saver_png.cpp | 107 | ||||
-rw-r--r-- | drivers/png/resource_saver_png.h | 4 | ||||
-rw-r--r-- | drivers/theoraplayer/SCsub | 5 | ||||
-rw-r--r-- | drivers/theoraplayer/include/theoraplayer/TheoraVideoClip.h | 2 | ||||
-rw-r--r-- | drivers/theoraplayer/include/theoraplayer/TheoraVideoManager.h | 4 | ||||
-rw-r--r-- | drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm | 5 | ||||
-rw-r--r-- | drivers/theoraplayer/src/TheoraVideoClip.cpp | 2 | ||||
-rw-r--r-- | drivers/theoraplayer/src/TheoraVideoManager.cpp | 14 | ||||
-rw-r--r-- | drivers/theoraplayer/video_stream_theoraplayer.cpp | 82 | ||||
-rw-r--r-- | drivers/theoraplayer/video_stream_theoraplayer.h | 4 | ||||
-rw-r--r-- | drivers/unix/os_unix.cpp | 2 | ||||
-rw-r--r-- | drivers/unix/packet_peer_udp_posix.cpp | 194 | ||||
-rw-r--r-- | drivers/unix/packet_peer_udp_posix.h | 57 |
14 files changed, 426 insertions, 76 deletions
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 4044496953..057de329df 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -4173,6 +4173,9 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) { pixels.resize(viewport.width*viewport.height*4); DVector<uint8_t>::Write w = pixels.write(); glPixelStorei(GL_PACK_ALIGNMENT, 4); + +// uint64_t time = OS::get_singleton()->get_ticks_usec(); + if (current_rt) { #ifdef GLEW_ENABLED glReadBuffer(GL_COLOR_ATTACHMENT0); @@ -4182,10 +4185,25 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) { // back? glReadPixels( viewport.x, window_size.height-(viewport.height+viewport.y), viewport.width,viewport.height,GL_RGBA,GL_UNSIGNED_BYTE,w.ptr()); } + + uint32_t *imgptr = (uint32_t*)w.ptr(); + for(int y=0;y<(viewport.height/2);y++) { + + uint32_t *ptr1 = &imgptr[y*viewport.width]; + uint32_t *ptr2 = &imgptr[(viewport.height-y-1)*viewport.width]; + + for(int x=0;x<viewport.width;x++) { + + uint32_t tmp = ptr1[x]; + ptr1[x]=ptr2[x]; + ptr2[x]=tmp; + } + } + w=DVector<uint8_t>::Write(); r_capture->create(viewport.width,viewport.height,0,Image::FORMAT_RGBA,pixels); - r_capture->flip_y(); + //r_capture->flip_y(); #endif diff --git a/drivers/png/resource_saver_png.cpp b/drivers/png/resource_saver_png.cpp index 9b394e8a8c..1fee50c8b5 100644 --- a/drivers/png/resource_saver_png.cpp +++ b/drivers/png/resource_saver_png.cpp @@ -31,6 +31,7 @@ #include "drivers/png/png.h" #include "os/file_access.h" #include "globals.h" +#include "core/image.h" static void _write_png_data(png_structp png_ptr,png_bytep data, png_size_t p_length) { @@ -46,12 +47,56 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t ERR_EXPLAIN("Can't save empty texture as PNG"); ERR_FAIL_COND_V(!texture->get_width() || !texture->get_height(),ERR_INVALID_PARAMETER); + Image img = texture->get_data(); - if (img.get_format() > Image::FORMAT_INDEXED_ALPHA) - img.decompress(); + Error err = save_image(p_path, img); + + if (err == OK) { + + bool global_filter = Globals::get_singleton()->get("image_loader/filter"); + bool global_mipmaps = Globals::get_singleton()->get("image_loader/gen_mipmaps"); + bool global_repeat = Globals::get_singleton()->get("image_loader/repeat"); + + String text; + + if (global_filter!=bool(texture->get_flags()&Texture::FLAG_FILTER)) { + text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"filter=true\n":"filter=false\n"; + } + if (global_mipmaps!=bool(texture->get_flags()&Texture::FLAG_MIPMAPS)) { + text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"gen_mipmaps=true\n":"gen_mipmaps=false\n"; + } + if (global_repeat!=bool(texture->get_flags()&Texture::FLAG_REPEAT)) { + text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"repeat=true\n":"repeat=false\n"; + } + if (bool(texture->get_flags()&Texture::FLAG_ANISOTROPIC_FILTER)) { + text+="anisotropic=true\n"; + } + if (bool(texture->get_flags()&Texture::FLAG_CONVERT_TO_LINEAR)) { + text+="tolinear=true\n"; + } + + if (text!="" || FileAccess::exists(p_path+".flags")) { + + FileAccess* f = FileAccess::open(p_path+".flags",FileAccess::WRITE); + if (f) { + + f->store_string(text); + memdelete(f); + } + } + } + + + return err; +}; + +Error ResourceSaverPNG::save_image(const String &p_path, Image &p_img) { + + if (p_img.get_format() > Image::FORMAT_INDEXED_ALPHA) + p_img.decompress(); - ERR_FAIL_COND_V(img.get_format() > Image::FORMAT_INDEXED_ALPHA, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(p_img.get_format() > Image::FORMAT_INDEXED_ALPHA, ERR_INVALID_PARAMETER); png_structp png_ptr; png_infop info_ptr; @@ -89,7 +134,7 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t int cs=0; - switch(img.get_format()) { + switch(p_img.get_format()) { case Image::FORMAT_GRAYSCALE: { @@ -113,14 +158,14 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t } break; default: { - if (img.detect_alpha()) { + if (p_img.detect_alpha()) { - img.convert(Image::FORMAT_RGBA); + p_img.convert(Image::FORMAT_RGBA); pngf=PNG_COLOR_TYPE_RGB_ALPHA; cs=4; } else { - img.convert(Image::FORMAT_RGB); + p_img.convert(Image::FORMAT_RGB); pngf=PNG_COLOR_TYPE_RGB; cs=3; } @@ -128,8 +173,8 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t } } - int w = img.get_width(); - int h = img.get_height(); + int w = p_img.get_width(); + int h = p_img.get_height(); png_set_IHDR(png_ptr, info_ptr, w,h, 8, pngf, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); @@ -144,7 +189,7 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t } - DVector<uint8_t>::Read r = img.get_data().read(); + DVector<uint8_t>::Read r = p_img.get_data().read(); row_pointers = (png_bytep*)memalloc(sizeof(png_bytep)*h); for(int i=0;i<h;i++) { @@ -165,43 +210,6 @@ Error ResourceSaverPNG::save(const String &p_path,const RES& p_resource,uint32_t png_write_end(png_ptr, NULL); memdelete(f); - - if (true) { - - bool global_filter = Globals::get_singleton()->get("image_loader/filter"); - bool global_mipmaps = Globals::get_singleton()->get("image_loader/gen_mipmaps"); - bool global_repeat = Globals::get_singleton()->get("image_loader/repeat"); - - String text; - - if (global_filter!=bool(texture->get_flags()&Texture::FLAG_FILTER)) { - text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"filter=true\n":"filter=false\n"; - } - if (global_mipmaps!=bool(texture->get_flags()&Texture::FLAG_MIPMAPS)) { - text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"gen_mipmaps=true\n":"gen_mipmaps=false\n"; - } - if (global_repeat!=bool(texture->get_flags()&Texture::FLAG_REPEAT)) { - text+=bool(texture->get_flags()&Texture::FLAG_FILTER)?"repeat=true\n":"repeat=false\n"; - } - if (bool(texture->get_flags()&Texture::FLAG_ANISOTROPIC_FILTER)) { - text+="anisotropic=true\n"; - } - if (bool(texture->get_flags()&Texture::FLAG_CONVERT_TO_LINEAR)) { - text+="tolinear=true\n"; - } - - if (text!="" || FileAccess::exists(p_path+".flags")) { - - f = FileAccess::open(p_path+".flags",FileAccess::WRITE); - if (f) { - - f->store_string(text); - memdelete(f); - } - } - } - - /* cleanup heap allocation */ return OK; @@ -218,3 +226,8 @@ void ResourceSaverPNG::get_recognized_extensions(const RES& p_resource,List<Stri } } + +ResourceSaverPNG::ResourceSaverPNG() { + + Image::save_png_func = &save_image; +}; diff --git a/drivers/png/resource_saver_png.h b/drivers/png/resource_saver_png.h index 7da50150e2..116d425d24 100644 --- a/drivers/png/resource_saver_png.h +++ b/drivers/png/resource_saver_png.h @@ -6,9 +6,13 @@ class ResourceSaverPNG : public ResourceFormatSaver { public: + static Error save_image(const String &p_path, Image& p_img); + virtual Error save(const String &p_path,const RES& p_resource,uint32_t p_flags=0); virtual bool recognize(const RES& p_resource) const; virtual void get_recognized_extensions(const RES& p_resource,List<String> *p_extensions) const; + + ResourceSaverPNG(); }; diff --git a/drivers/theoraplayer/SCsub b/drivers/theoraplayer/SCsub index 979ff2ed1b..d4218debb6 100644 --- a/drivers/theoraplayer/SCsub +++ b/drivers/theoraplayer/SCsub @@ -67,10 +67,13 @@ if env["platform"] == "iphone": env_theora = env.Clone() -env_theora.Append(CPPFLAGS=["-D_YUV_C", "-D__THEORA", "-D_LIB"]) +env_theora.Append(CPPFLAGS=["-D_YUV_C", "-D_LIB", "-D__THEORA"]) if env["platform"] == "iphone": env_theora.Append(CPPFLAGS=["-D__AVFOUNDATION"]) +else: + pass + #env_theora.Append(CPPFLAGS=["-D__FFMPEG"]) if env["platform"] == "android": env_theora.Append(CPPFLAGS=["-D_ANDROID"]) diff --git a/drivers/theoraplayer/include/theoraplayer/TheoraVideoClip.h b/drivers/theoraplayer/include/theoraplayer/TheoraVideoClip.h index b2987c01c4..fe71cf8566 100644 --- a/drivers/theoraplayer/include/theoraplayer/TheoraVideoClip.h +++ b/drivers/theoraplayer/include/theoraplayer/TheoraVideoClip.h @@ -87,6 +87,7 @@ protected: std::string mName; int mWidth, mHeight, mStride; int mNumFrames; + int audio_track; int mSubFrameWidth, mSubFrameHeight, mSubFrameOffsetX, mSubFrameOffsetY; float mAudioGain; //! multiplier for audio samples. between 0 and 1 @@ -233,6 +234,7 @@ public: bool getAutoRestart() { return mAutoRestart; } + void set_audio_track(int p_track) { audio_track=p_track; } /** TODO: user priority. Useful only when more than one video is being decoded diff --git a/drivers/theoraplayer/include/theoraplayer/TheoraVideoManager.h b/drivers/theoraplayer/include/theoraplayer/TheoraVideoManager.h index 3ff9b217cd..d94c51b4d4 100644 --- a/drivers/theoraplayer/include/theoraplayer/TheoraVideoManager.h +++ b/drivers/theoraplayer/include/theoraplayer/TheoraVideoManager.h @@ -67,8 +67,8 @@ public: //! search registered clips by name TheoraVideoClip* getVideoClipByName(std::string name); - TheoraVideoClip* createVideoClip(std::string filename,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0); - TheoraVideoClip* createVideoClip(TheoraDataSource* data_source,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0); + TheoraVideoClip* createVideoClip(std::string filename,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0, int p_track=0); + TheoraVideoClip* createVideoClip(TheoraDataSource* data_source,TheoraOutputMode output_mode=TH_RGB,int numPrecachedOverride=0,bool usePower2Stride=0, int p_audio_track=0); void update(float timeDelta); diff --git a/drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm b/drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm index 8c3d2cc3b9..1b5cf0ab13 100644 --- a/drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm +++ b/drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm @@ -271,7 +271,10 @@ void TheoraVideoClip_AVFoundation::load(TheoraDataSource* source) AVAssetTrack *videoTrack = [tracks objectAtIndex:0]; NSArray* audioTracks = [asset tracksWithMediaType:AVMediaTypeAudio]; - AVAssetTrack *audioTrack = audioTracks.count > 0 ? [audioTracks objectAtIndex:0] : NULL; + if (audio_track >= audioTracks.count) + audio_track = 0; + AVAssetTrack *audioTrack = audioTracks.count > 0 ? [audioTracks objectAtIndex:audio_track] : NULL; + printf("*********** using audio track %i\n", audio_track); #ifdef _AVFOUNDATION_BGRX bool yuv_output = (mOutputMode != TH_BGRX && mOutputMode != TH_RGBA); diff --git a/drivers/theoraplayer/src/TheoraVideoClip.cpp b/drivers/theoraplayer/src/TheoraVideoClip.cpp index b71319e6a1..ed9f2c22da 100644 --- a/drivers/theoraplayer/src/TheoraVideoClip.cpp +++ b/drivers/theoraplayer/src/TheoraVideoClip.cpp @@ -51,6 +51,8 @@ TheoraVideoClip::TheoraVideoClip(TheoraDataSource* data_source, mWaitingForCache(false), mOutputMode(TH_UNDEFINED) { + + audio_track=0; mAudioMutex = NULL; mThreadAccessMutex = new TheoraMutex(); mTimer = mDefaultTimer = new TheoraTimer(); diff --git a/drivers/theoraplayer/src/TheoraVideoManager.cpp b/drivers/theoraplayer/src/TheoraVideoManager.cpp index 87696d12a9..53b211374a 100644 --- a/drivers/theoraplayer/src/TheoraVideoManager.cpp +++ b/drivers/theoraplayer/src/TheoraVideoManager.cpp @@ -35,6 +35,8 @@ extern "C" void initYUVConversionModule(); } +#include "core/os/memory.h" + //#define _DECODING_BENCHMARK //uncomment to test average decoding time on a given device @@ -184,16 +186,18 @@ TheoraAudioInterfaceFactory* TheoraVideoManager::getAudioInterfaceFactory() TheoraVideoClip* TheoraVideoManager::createVideoClip(std::string filename, TheoraOutputMode output_mode, int numPrecachedOverride, - bool usePower2Stride) + bool usePower2Stride, + int p_track) { - TheoraDataSource* src=new TheoraFileDataSource(filename); - return createVideoClip(src,output_mode,numPrecachedOverride,usePower2Stride); + TheoraDataSource* src=memnew(TheoraFileDataSource(filename)); + return createVideoClip(src,output_mode,numPrecachedOverride,usePower2Stride, p_track); } TheoraVideoClip* TheoraVideoManager::createVideoClip(TheoraDataSource* data_source, TheoraOutputMode output_mode, int numPrecachedOverride, - bool usePower2Stride) + bool usePower2Stride, + int p_audio_track) { mWorkMutex->lock(); @@ -226,6 +230,8 @@ TheoraVideoClip* TheoraVideoManager::createVideoClip(TheoraDataSource* data_sour #ifdef __FFMPEG clip = new TheoraVideoClip_FFmpeg(data_source, output_mode, nPrecached, usePower2Stride); #endif + + clip->set_audio_track(p_audio_track); clip->load(data_source); clip->decodeNextFrame(); // ensure the first frame is always preloaded and have the main thread do it to prevent potential thread starvatio diff --git a/drivers/theoraplayer/video_stream_theoraplayer.cpp b/drivers/theoraplayer/video_stream_theoraplayer.cpp index fdf612ff0f..62dee1336a 100644 --- a/drivers/theoraplayer/video_stream_theoraplayer.cpp +++ b/drivers/theoraplayer/video_stream_theoraplayer.cpp @@ -39,6 +39,8 @@ #include "core/ring_buffer.h" #include "core/os/thread_safe.h" +#include "core/globals.h" + static TheoraVideoManager* mgr = NULL; class TPDataFA : public TheoraDataSource { @@ -120,6 +122,7 @@ class AudioStreamInput : public AudioStreamResampled { int rb_power; int total_wrote; bool playing; + bool paused; public: @@ -131,6 +134,7 @@ public: AudioServer::get_singleton()->stream_set_active(stream_rid,true); AudioServer::get_singleton()->stream_set_volume_scale(stream_rid,1); playing = true; + paused = false; }; virtual void stop() { @@ -141,10 +145,11 @@ public: playing=false; _clear(); }; + virtual bool is_playing() const { return true; }; - virtual void set_paused(bool p_paused) {}; - virtual bool is_paused(bool p_paused) const { return false; }; + virtual void set_paused(bool p_paused) { paused = p_paused; }; + virtual bool is_paused(bool p_paused) const { return paused; }; virtual void set_loop(bool p_enable) {}; virtual bool has_loop() const { return false; }; @@ -164,12 +169,16 @@ public: void input(float* p_data, int p_samples) { + _THREAD_SAFE_METHOD_; + //printf("input %i samples from %p\n", p_samples, p_data); if (rb.space_left() < p_samples) { rb_power += 1; rb.resize(rb_power); } rb.write(p_data, p_samples); + + update(); //update too here for less latency }; void update() { @@ -177,15 +186,16 @@ public: _THREAD_SAFE_METHOD_; int todo = get_todo(); int16_t* buffer = get_write_buffer(); - int samples = rb.data_left(); - const int to_write = MIN(todo, samples); + int frames = rb.data_left()/channels; + const int to_write = MIN(todo, frames); - for (int i=0; i<to_write; i++) { + for (int i=0; i<to_write*channels; i++) { - uint16_t sample = uint16_t(rb.read() * 32767); + int v = rb.read() * 32767; + int16_t sample = CLAMP(v,-32768,32767); buffer[i] = sample; }; - write(to_write/channels); + write(to_write); total_wrote += to_write; }; @@ -201,6 +211,7 @@ public: AudioStreamInput(int p_channels, int p_freq) { playing = false; + paused = true; channels = p_channels; freq = p_freq; total_wrote = 0; @@ -231,7 +242,7 @@ public: TPAudioGodot(TheoraVideoClip* owner, int nChannels, int p_freq) : TheoraAudioInterface(owner, nChannels, p_freq), TheoraTimer() { - printf("***************** audio interface constructor\n"); + printf("***************** audio interface constructor freq %i\n", p_freq); channels = nChannels; freq = p_freq; stream = Ref<AudioStreamInput>(memnew(AudioStreamInput(nChannels, p_freq))); @@ -247,12 +258,13 @@ public: void update(float time_increase) { - mTime = (float)(stream->get_total_wrote() / channels) / freq; + //mTime = (float)(stream->get_total_wrote()) / freq; + //mTime = MAX(0,mTime-AudioServer::get_singleton()->get_output_delay()); //mTime = (float)sample_count / channels / freq; - //mTime += time_increase; + mTime += time_increase; //float duration=mClip->getDuration(); //if (mTime > duration) mTime=duration; - //printf("time at timer is %f, samples %i\n", mTime, sample_count); + //printf("time at timer is %f, %f, samples %i\n", mTime, time_increase, sample_count); } }; @@ -276,12 +288,12 @@ void VideoStreamTheoraplayer::stop() { clip->stop(); clip->seek(0); }; + started = true; }; void VideoStreamTheoraplayer::play() { - - playing = true; - started = true; + if (clip) + playing = true; }; bool VideoStreamTheoraplayer::is_playing() const { @@ -291,7 +303,13 @@ bool VideoStreamTheoraplayer::is_playing() const { void VideoStreamTheoraplayer::set_paused(bool p_paused) { - playing = false; + paused = p_paused; + if (paused) { + clip->pause(); + } else { + if (clip && playing && !started) + clip->play(); + } }; bool VideoStreamTheoraplayer::is_paused(bool p_paused) const { @@ -346,6 +364,9 @@ int VideoStreamTheoraplayer::get_pending_frame_count() const { void VideoStreamTheoraplayer::pop_frame(Ref<ImageTexture> p_tex) { + if (!clip) + return; + TheoraVideoFrame* f = clip->getNextFrame(); if (!f) { return; @@ -358,13 +379,15 @@ void VideoStreamTheoraplayer::pop_frame(Ref<ImageTexture> p_tex) { #endif float w=clip->getWidth(),h=clip->getHeight(); - int imgsize = w * h * f->mBpp; + int imgsize = w * h * f->mBpp; int size = f->getStride() * f->getHeight() * f->mBpp; data.resize(imgsize); - DVector<uint8_t>::Write wr = data.write(); - uint8_t* ptr = wr.ptr(); - copymem(ptr, f->getBuffer(), imgsize); + { + DVector<uint8_t>::Write wr = data.write(); + uint8_t* ptr = wr.ptr(); + copymem(ptr, f->getBuffer(), imgsize); + } /* for (int i=0; i<h; i++) { int dstofs = i * w * f->mBpp; @@ -405,6 +428,12 @@ void VideoStreamTheoraplayer::update(float p_time) { if (!mgr) return; + if (!clip) + return; + + if (!playing || paused) + return; + //printf("video update!\n"); if (started) { if (clip->getNumReadyFrames() < 2) { @@ -421,6 +450,13 @@ void VideoStreamTheoraplayer::update(float p_time) { mgr->update(p_time); }; + +void VideoStreamTheoraplayer::set_audio_track(int p_idx) { + audio_track=p_idx; + if (clip) + clip->set_audio_track(audio_track); +} + void VideoStreamTheoraplayer::set_file(const String& p_file) { FileAccess* f = FileAccess::open(p_file, FileAccess::READ); @@ -436,10 +472,13 @@ void VideoStreamTheoraplayer::set_file(const String& p_file) { mgr->setAudioInterfaceFactory(audio_factory); }; + int track = GLOBAL_DEF("theora/audio_track", 0); // hack + if (p_file.find(".mp4") != -1) { std::string file = p_file.replace("res://", "").utf8().get_data(); - clip = mgr->createVideoClip(file, TH_BGRX, 16); + clip = mgr->createVideoClip(file, TH_RGBX, 2, false, track); + //clip->set_audio_track(audio_track); memdelete(f); } else { @@ -448,6 +487,7 @@ void VideoStreamTheoraplayer::set_file(const String& p_file) { try { clip = mgr->createVideoClip(ds); + clip->set_audio_track(audio_track); } catch (_TheoraGenericException e) { printf("exception ocurred! %s\n", e.repr().c_str()); clip = NULL; @@ -477,7 +517,9 @@ VideoStreamTheoraplayer::VideoStreamTheoraplayer() { clip = NULL; started = false; playing = false; + paused = false; loop = false; + audio_track=0; }; diff --git a/drivers/theoraplayer/video_stream_theoraplayer.h b/drivers/theoraplayer/video_stream_theoraplayer.h index d88f495032..d43c12609f 100644 --- a/drivers/theoraplayer/video_stream_theoraplayer.h +++ b/drivers/theoraplayer/video_stream_theoraplayer.h @@ -17,6 +17,9 @@ class VideoStreamTheoraplayer : public VideoStream { bool started; bool playing; bool loop; + bool paused; + + int audio_track; public: @@ -43,6 +46,7 @@ public: void update(float p_time); void set_file(const String& p_file); + void set_audio_track(int p_idx); ~VideoStreamTheoraplayer(); VideoStreamTheoraplayer(); diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index ef4cf644fd..e6458068ea 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -42,6 +42,7 @@ #include "dir_access_unix.h" #include "tcp_server_posix.h" #include "stream_peer_tcp_posix.h" +#include "packet_peer_udp_posix.h" #include <stdarg.h> @@ -115,6 +116,7 @@ void OS_Unix::initialize_core() { #ifndef NO_NETWORK TCPServerPosix::make_default(); StreamPeerTCPPosix::make_default(); + PacketPeerUDPPosix::make_default(); IP_Unix::make_default(); #endif mempool_static = new MemoryPoolStaticMalloc; diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp new file mode 100644 index 0000000000..26a0b29228 --- /dev/null +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -0,0 +1,194 @@ +#include "packet_peer_udp_posix.h" + +#ifdef UNIX_ENABLED + + +#include <errno.h> +#include <unistd.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <stdio.h> + +#ifndef NO_FCNTL +#include <sys/fcntl.h> +#else +#include <sys/ioctl.h> +#endif + +#ifdef JAVASCRIPT_ENABLED +#include <arpa/inet.h> +#endif + + +int PacketPeerUDPPosix::get_available_packet_count() const { + + Error err = const_cast<PacketPeerUDPPosix*>(this)->_poll(false); + if (err!=OK) + return 0; + + return queue_count; +} + +Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size) const{ + + Error err = const_cast<PacketPeerUDPPosix*>(this)->_poll(false); + if (err!=OK) + return err; + if (queue_count==0) + return ERR_UNAVAILABLE; + + uint32_t size; + rb.read((uint8_t*)&packet_ip.host,4,true); + rb.read((uint8_t*)&packet_port,4,true); + rb.read((uint8_t*)&size,4,true); + rb.read(packet_buffer,size,true); + --queue_count; + *r_buffer=packet_buffer; + r_buffer_size=size; + return OK; + +} +Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){ + + int sock = _get_socket(); + ERR_FAIL_COND_V( sock == -1, FAILED ); + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(peer_port); + addr.sin_addr = *((struct in_addr*)&peer_addr.host); + + errno = 0; + int err; + + while ( (err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, sizeof(addr))) != p_buffer_size) { + + if (errno != EAGAIN) { + return FAILED; + } + } + + return OK; +} + +int PacketPeerUDPPosix::get_max_packet_size() const{ + + return 512; // uhm maybe not +} + +Error PacketPeerUDPPosix::listen(int p_port, int p_recv_buffer_size){ + + close(); + int sock = _get_socket(); + if (sock == -1 ) + return ERR_CANT_CREATE; + sockaddr_in addr = {0}; + addr.sin_family = AF_INET; + addr.sin_port = htons(p_port); + addr.sin_addr.s_addr = INADDR_ANY; + if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_in)) == -1 ) { + close(); + return ERR_UNAVAILABLE; + } + printf("UDP Connection listening on port %i bufsize %i \n", p_port,p_recv_buffer_size); + rb.resize(nearest_shift(p_recv_buffer_size)); + return OK; +} + +void PacketPeerUDPPosix::close(){ + + if (sockfd != -1) + ::close(sockfd); + sockfd=-1; + rb.resize(8); + queue_count=0; +} + + +Error PacketPeerUDPPosix::wait() { + + return _poll(true); +} + +Error PacketPeerUDPPosix::_poll(bool p_wait) { + + struct sockaddr_in from = {0}; + socklen_t len = sizeof(struct sockaddr_in); + int ret; + while ( (ret = recvfrom(sockfd, recv_buffer, MIN(sizeof(recv_buffer),rb.data_left()-12), p_wait?0:MSG_DONTWAIT, (struct sockaddr*)&from, &len)) > 0) { + rb.write((uint8_t*)&from.sin_addr, 4); + uint32_t port = ntohs(from.sin_port); + rb.write((uint8_t*)&port, 4); + rb.write((uint8_t*)&ret, 4); + rb.write(recv_buffer, ret); + len = sizeof(struct sockaddr_in); + ++queue_count; + }; + + if (ret == 0 || (ret == -1 && errno != EAGAIN) ) { + close(); + return FAILED; + }; + + return OK; +} +bool PacketPeerUDPPosix::is_listening() const{ + + return sockfd!=-1; +} + +IP_Address PacketPeerUDPPosix::get_packet_address() const { + + return packet_ip; +} + +int PacketPeerUDPPosix::get_packet_port() const{ + + return packet_port; +} + +int PacketPeerUDPPosix::_get_socket() { + + if (sockfd != -1) + return sockfd; + + sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + ERR_FAIL_COND_V( sockfd == -1, -1 ); + //fcntl(sockfd, F_SETFL, O_NONBLOCK); + + return sockfd; +} + + +void PacketPeerUDPPosix::set_send_address(const IP_Address& p_address,int p_port) { + + peer_addr=p_address; + peer_port=p_port; +} + +PacketPeerUDP* PacketPeerUDPPosix::_create() { + + return memnew(PacketPeerUDPPosix); +}; + +void PacketPeerUDPPosix::make_default() { + + PacketPeerUDP::_create = PacketPeerUDPPosix::_create; +}; + + +PacketPeerUDPPosix::PacketPeerUDPPosix() { + + sockfd=-1; + packet_port=0; + queue_count=0; + peer_port=0; +} + +PacketPeerUDPPosix::~PacketPeerUDPPosix() { + + close(); +} +#endif diff --git a/drivers/unix/packet_peer_udp_posix.h b/drivers/unix/packet_peer_udp_posix.h new file mode 100644 index 0000000000..b14568eb5f --- /dev/null +++ b/drivers/unix/packet_peer_udp_posix.h @@ -0,0 +1,57 @@ +#ifndef PACKET_PEER_UDP_POSIX_H +#define PACKET_PEER_UDP_POSIX_H + +#ifdef UNIX_ENABLED + +#include "io/packet_peer_udp.h" +#include "ring_buffer.h" + +class PacketPeerUDPPosix : public PacketPeerUDP { + + + enum { + PACKET_BUFFER_SIZE=65536 + }; + + mutable RingBuffer<uint8_t> rb; + uint8_t recv_buffer[PACKET_BUFFER_SIZE]; + mutable uint8_t packet_buffer[PACKET_BUFFER_SIZE]; + IP_Address packet_ip; + int packet_port; + mutable int queue_count; + int sockfd; + + IP_Address peer_addr; + int peer_port; + + _FORCE_INLINE_ int _get_socket(); + + static PacketPeerUDP* _create(); + virtual Error _poll(bool p_block); + +public: + + virtual int get_available_packet_count() const; + virtual Error get_packet(const uint8_t **r_buffer,int &r_buffer_size) const; + virtual Error put_packet(const uint8_t *p_buffer,int p_buffer_size); + + virtual int get_max_packet_size() const; + + virtual Error listen(int p_port,int p_recv_buffer_size=65536); + virtual void close(); + virtual Error wait(); + virtual bool is_listening() const; + + virtual IP_Address get_packet_address() const; + virtual int get_packet_port() const; + + virtual void set_send_address(const IP_Address& p_address,int p_port); + + static void make_default(); + + PacketPeerUDPPosix(); + ~PacketPeerUDPPosix(); +}; + +#endif // PACKET_PEER_UDP_POSIX_H +#endif |