From 6dd8768811cfca5bb831619d93cf870e5d20667f Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 12 Nov 2014 11:23:23 -0300 Subject: 3D Import Import & UDP -=-=-=-=-=-=-=-=-=-=- -Animation Import filter support -Animation Clip import support -Animation Optimizer Fixes, Improvements and Visibile Options -Extremely Experimental UDP support. --- drivers/gles2/rasterizer_gles2.cpp | 5 + .../include/theoraplayer/TheoraVideoClip.h | 2 + .../include/theoraplayer/TheoraVideoManager.h | 4 +- .../AVFoundation/TheoraVideoClip_AVFoundation.mm | 3 +- drivers/theoraplayer/src/TheoraVideoClip.cpp | 2 + drivers/theoraplayer/src/TheoraVideoManager.cpp | 14 +- drivers/theoraplayer/video_stream_theoraplayer.cpp | 51 ++++-- drivers/theoraplayer/video_stream_theoraplayer.h | 3 + drivers/unix/os_unix.cpp | 2 + drivers/unix/packet_peer_udp_posix.cpp | 188 +++++++++++++++++++++ drivers/unix/packet_peer_udp_posix.h | 56 ++++++ 11 files changed, 309 insertions(+), 21 deletions(-) create mode 100644 drivers/unix/packet_peer_udp_posix.cpp create mode 100644 drivers/unix/packet_peer_udp_posix.h (limited to 'drivers') diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 4044496953..bc1b17eade 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::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,11 +4185,13 @@ 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()); } + printf("readpixels time %i\n", (int)(OS::get_singleton()->get_ticks_usec() - time)); w=DVector::Write(); r_capture->create(viewport.width,viewport.height,0,Image::FORMAT_RGBA,pixels); r_capture->flip_y(); + printf("total time %i\n", (int)(OS::get_singleton()->get_ticks_usec() - time)); #endif 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..72e3dfc9fa 100644 --- a/drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm +++ b/drivers/theoraplayer/src/AVFoundation/TheoraVideoClip_AVFoundation.mm @@ -271,7 +271,8 @@ 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; + 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..643899aaed 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 { @@ -141,6 +143,7 @@ public: playing=false; _clear(); }; + virtual bool is_playing() const { return true; }; virtual void set_paused(bool p_paused) {}; @@ -164,12 +167,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 +184,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(memnew(AudioStreamInput(nChannels, p_freq))); @@ -247,12 +255,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); } }; @@ -358,13 +367,15 @@ void VideoStreamTheoraplayer::pop_frame(Ref 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::Write wr = data.write(); - uint8_t* ptr = wr.ptr(); - copymem(ptr, f->getBuffer(), imgsize); + { + DVector::Write wr = data.write(); + uint8_t* ptr = wr.ptr(); + memcpy(ptr, f->getBuffer(), imgsize); + } /* for (int i=0; imBpp; @@ -421,6 +432,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 +454,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 +469,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; @@ -478,6 +500,7 @@ VideoStreamTheoraplayer::VideoStreamTheoraplayer() { started = false; playing = false; loop = false; + audio_track=0; }; diff --git a/drivers/theoraplayer/video_stream_theoraplayer.h b/drivers/theoraplayer/video_stream_theoraplayer.h index d88f495032..f926dfdaf5 100644 --- a/drivers/theoraplayer/video_stream_theoraplayer.h +++ b/drivers/theoraplayer/video_stream_theoraplayer.h @@ -18,6 +18,8 @@ class VideoStreamTheoraplayer : public VideoStream { bool playing; bool loop; + int audio_track; + public: virtual void stop(); @@ -43,6 +45,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 @@ -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..d951524d3a --- /dev/null +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -0,0 +1,188 @@ +#include "packet_peer_udp_posix.h" + +#ifdef UNIX_ENABLED + + +#include +#include +#include +#include +#include + +#include +#include + +#ifndef NO_FCNTL +#include +#else +#include +#endif + +#ifdef JAVASCRIPT_ENABLED +#include +#endif + + +int PacketPeerUDPPosix::get_available_packet_count() const { + + Error err = const_cast(this)->poll(); + 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(this)->poll(); + if (err!=OK) + return err; + if (queue_count==0) + return ERR_UNAVAILABLE; + + uint32_t size; + rb.read((uint8_t*)&size,4,true); + rb.read((uint8_t*)&packet_ip.host,4,true); + rb.read((uint8_t*)&packet_port,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\n", p_port); + rb.resize(nearest_power_of_2(p_recv_buffer_size)); + return OK; +} + +void PacketPeerUDPPosix::close(){ + + if (sockfd != -1) + ::close(sockfd); + sockfd=-1; + rb.resize(8); + queue_count=0; +} + +Error PacketPeerUDPPosix::poll() { + + 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), 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..428c3ac37e --- /dev/null +++ b/drivers/unix/packet_peer_udp_posix.h @@ -0,0 +1,56 @@ +#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 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(); + +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 poll(); + 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 -- cgit v1.2.3