From ff59340614ec150e4bd84d3554081e666970aef2 Mon Sep 17 00:00:00 2001 From: Tim Redfern Date: Fri, 3 May 2013 18:25:26 +0100 Subject: elusive hang while rendering --- rotord/01.xml | 15 ++++---- rotord/04.xml | 17 +++++++++ rotord/graph.cpp | 4 +-- rotord/libavaudioloader.cpp | 52 +++++++++++++++------------ rotord/libavaudioloader.h | 1 + rotord/rendercontext.cpp | 25 +++++++------ rotord/rotor.cpp | 14 ++++++-- rotord/rotor.h | 85 +++++++++++++++++++++++++++++++++------------ rotord/utils.cpp | 19 ++++++++++ rotord/utils.h | 6 ++++ 10 files changed, 173 insertions(+), 65 deletions(-) create mode 100644 rotord/04.xml create mode 100644 rotord/utils.cpp create mode 100644 rotord/utils.h diff --git a/rotord/01.xml b/rotord/01.xml index 7a7315d..29d709e 100755 --- a/rotord/01.xml +++ b/rotord/01.xml @@ -2,15 +2,16 @@ Sample template ©Rotor 2013 beats - signal divide - signal 1 to divide + on off + signal 1 to make on off - outputs a single 1 every time signal enters a new number - signal to analyse + performance video - performance video + invert video + invert signal + image to invert - video output - image to output + video output + image to output diff --git a/rotord/04.xml b/rotord/04.xml new file mode 100644 index 0000000..fe5c3e1 --- /dev/null +++ b/rotord/04.xml @@ -0,0 +1,17 @@ + +Sample template ©Rotor 2013 + beats + + performance video + + performance video + + video cycler + switching signal + image to switch + image to switch + + video output + image to output + + diff --git a/rotord/graph.cpp b/rotord/graph.cpp index fc9a129..2139f6c 100644 --- a/rotord/graph.cpp +++ b/rotord/graph.cpp @@ -29,10 +29,10 @@ bool Graph::signal_render(string &signal_xml,const float framerate) { } else return false; } -bool Graph::video_render(const string &output_filename,const string &audio_filename,const float framerate) { +bool Graph::video_render(const string &output_filename,const string &audio_filename,const float framerate,float& progress) { if (find_node("video_output")) { Video_output *video_output=dynamic_cast(find_node("video_output")); - return video_output->render(duration,framerate,output_filename,audio_filename); + return video_output->render(duration,framerate,output_filename,audio_filename,progress); } else return false; } diff --git a/rotord/libavaudioloader.cpp b/rotord/libavaudioloader.cpp index 03919f0..ef84560 100644 --- a/rotord/libavaudioloader.cpp +++ b/rotord/libavaudioloader.cpp @@ -152,42 +152,50 @@ uint16_t* libav::Audioloader::get_samples(int num){ //presumes 16bpc here //std::cerr << "request "<0){ for (int i=0;inb_samples))*av_frame_get_channels(frame))>buffer.size()){ - int m=buffer.size(); - int s=((sample_end+std::max(num,frame->nb_samples))*av_frame_get_channels(frame)); - buffer.reserve(s); - std::cerr << "audioloader reserved buffer to " << s << std::endl; - for (int i=m;inb_samples))*channels)>buffer.size()){ + int m=buffer.size(); + int s=((sample_end+std::max(num,frame->nb_samples))*channels); + buffer.reserve(s); + std::cerr << "audioloader reserved buffer to " << s << std::endl; + for (int i=m;inb_samples;i++) { + for (int j=0;jchannels)+j]= ((uint16_t*) frame->buf[j]->data)[i]; + //temporarily disabled audio as its is SIGSEV with audio from delorentos + + + //buffer[(j*frame->channels)+(sample_end+i)]= ((uint16_t*) frame->buf[j]->data)[i]; ??planar?? nope + } + } + sample_end+=frame->nb_samples; } - if (!frame) { - for (int i=0;inb_samples)*frame->channels)<nb_samples;i++) { - for (int j=0;jchannels)+j]= ((uint16_t*) frame->buf[j]->data)[i]; - //temporarily disabled audio as its is SIGSEV with audio from delorentos - - - //buffer[(j*frame->channels)+(sample_end+i)]= ((uint16_t*) frame->buf[j]->data)[i]; ??planar?? nope - } - } - sample_end+=frame->nb_samples; + //avcodec_free_frame(&frame); } if (sample_end>num) { diff --git a/rotord/libavaudioloader.h b/rotord/libavaudioloader.h index aca6bd0..1197fbb 100644 --- a/rotord/libavaudioloader.h +++ b/rotord/libavaudioloader.h @@ -31,6 +31,7 @@ namespace libav { AVPacket packet; int sample_end; int sample_start; + int channels; //necessary to handle final packet }; diff --git a/rotord/rendercontext.cpp b/rotord/rendercontext.cpp index d6469bd..d0fa5bd 100644 --- a/rotord/rendercontext.cpp +++ b/rotord/rendercontext.cpp @@ -19,17 +19,19 @@ void Render_context::runTask() { processors.push_back(dynamic_cast(a)); } if (load_audio(audio_filename,processors)) { - state=AUDIO_READY; + audio_loaded=true; + state=IDLE; } else { //an error occurred: TODO have to clean up allocated data. autoptr? + audio_loaded=false; state=IDLE; } } if(cmd==RENDER) { state=RENDERING; - if(graph.video_render(output_filename,audio_filename,output_framerate)){ - state=RENDER_READY; + if(graph.video_render(output_filename,audio_filename,output_framerate,progress)){ + state=IDLE; } else { //an error occurred: TODO have to clean up allocated data. autoptr? @@ -88,7 +90,7 @@ Command_response Render_context::session_command(const std::vector& sprintf(c,"%02f",progress); response.description+=""+string(c)+"\n"; } - if (state==AUDIO_READY) { + else if (audio_loaded) { //not sure about this-- should this state be retained? //can the data only be read once? //for now @@ -97,7 +99,10 @@ Command_response Render_context::session_command(const std::vector& response.description+=""; - state=IDLE; + } + else { + response.status=HTTPResponse::HTTP_BAD_REQUEST; + response.description="Rotor: no audio loaded\n"; } } if (command[0]=="DELETE") { @@ -230,8 +235,8 @@ Command_response Render_context::session_command(const std::vector& if (command[0]=="GET") { //DUMMY RESPONSE response.status=HTTPResponse::HTTP_OK; - response.description="DUMMY RESPONSE Rotor: rendering video\n"; - response.description+="25.2\n"; + response.description="Rotor: rendering video\n"; + response.description+=""+ofToString(progress)+"\n"; } if (command[0]=="PUT") { if (command.size()>2) { @@ -383,9 +388,9 @@ bool Render_context::load_audio(const string &filename,vectorprocess_frame(frame->data[0],frame->nb_samples); } sample_processed+=frame->nb_samples; - mutex.lock(); - progress=((double)sample_processed)/samples; - mutex.unlock(); + //mutex.lock(); + progress=((float)sample_processed)/samples; + //mutex.unlock(); } } // You *must* call av_free_packet() after each call to av_read_frame() or else you'll leak memory diff --git a/rotord/rotor.cpp b/rotord/rotor.cpp index b0bf8ab..4c79fc1 100755 --- a/rotord/rotor.cpp +++ b/rotord/rotor.cpp @@ -13,6 +13,9 @@ Node_factory::Node_factory(){ add_type("testcard",new Testcard()); add_type("video_output",new Video_output()); add_type("video_input",new Video_input()); + add_type("on_off",new On_off()); + add_type("invert",new Invert()); + add_type("video_cycler",new Video_cycler()); } bool Signal_input::connect(Signal_node* source) { @@ -151,7 +154,7 @@ void Audio_analysis::print_features(){ } } -bool Video_output::render(const float duration, const float framerate,const string &output_filename,const string &audio_filename){ +bool Video_output::render(const float duration, const float framerate,const string &output_filename,const string &audio_filename,float& progress){ // //setup defaults @@ -188,8 +191,15 @@ bool Video_output::render(const float duration, const float framerate,const stri af+=exporter->get_audio_step(); } Image* i=get_output(Frame_spec(vf,framerate,outW,outH)); - exporter->encodeFrame(i->RGBdata); + if (i) { + exporter->encodeFrame(i->RGBdata); + } vf+=vstep; + progress=vf/duration; + if (progress>0.99) { + //stop here + //seems that the last frame of samples causes std::max to have + } /* if (!exporter->encodeFrame(i->RGBdata)){ //if (!exporter->encodeFrame(get_output(Frame_spec(f,framerate,outW,outH))->RGBdata,audioloader.get_packet())){ diff --git a/rotord/rotor.h b/rotord/rotor.h index 441be2f..ea4d758 100755 --- a/rotord/rotor.h +++ b/rotord/rotor.h @@ -62,6 +62,7 @@ extern "C" { #include "libavaudioloader.h" #include "libavexporter.h" #include "gstvideoloader.h" +#include "utils.h" //fequal namespace Rotor { #define IDLE 0 @@ -76,19 +77,7 @@ namespace Rotor { #define PREVIEW 2 #define RENDER 3 -#ifndef FEQUAL -//float equality -bool fequal(const float u,const float v){ - if (abs(u-v)<.001) return true; - else return false; -}; -bool flessorequal(const float u,const float v){ - //v is less or equal to u - if (u-v>-.001) return true; - else return false; -}; -#define FEQUAL -#endif + //forward declaration class Node; @@ -344,6 +333,21 @@ bool flessorequal(const float u,const float v){ return 0.0f; } }; + class On_off: public Signal_node { + public: + On_off(){}; + On_off(map &settings) { + base_settings(settings); + }; + On_off* clone(map &_settings) { return new On_off(_settings);}; + const float get_output(const Time_spec &time) { + if (inputs[0]->connection) { + float s1=(((Signal_node*)(inputs[0]->connection))->get_output(time)); + if ((int)s1%2) return 1.0f; + } + return 0.0f; + } + }; class Signal_output: public Signal_node { public: Signal_output(){}; @@ -400,12 +404,22 @@ bool flessorequal(const float u,const float v){ Invert* clone(map &_settings) { return new Invert(_settings);}; Image *get_output(const Frame_spec &frame){ if (inputs.size()) { - if (inputs[0]->connection) { - Time_spec requested=Time_spec(frame.time,frame.framerate); - if (fequal((((Signal_node*)inputs[0]->connection)->get_output(requested)),1.0f)) { - //invert=!invert; - } - } + if (image_inputs[0]->connection){ + if (inputs[0]->connection) { + Time_spec requested=Time_spec(frame.time,frame.framerate); + if (fmoreorequal(1.0f,(((Signal_node*)inputs[0]->connection)->get_output(requested)))) { + Image *in=(((Image_node*)image_inputs[0]->connection)->get_output(frame)); + image->setup(frame.w,frame.h); + for (int i=0;iw*in->h*3;i++) { + image->RGBdata[i]=255-in->RGBdata[i]; + } + return image; + + } + } + return (((Image_node*)image_inputs[0]->connection)->get_output(frame)); + } + return nullptr; } if (image_inputs[0]->connection) { @@ -431,7 +445,7 @@ bool flessorequal(const float u,const float v){ else return nullptr; }; Video_output* clone(map &_settings) { return new Video_output(_settings);}; - bool render(const float duration, const float framerate,const string &output_filename,const string &audio_filename); + bool render(const float duration, const float framerate,const string &output_filename,const string &audio_filename,float& progress); private: //ofxMovieExporter *exporter; @@ -454,6 +468,31 @@ bool flessorequal(const float u,const float v){ ofGstVideoPlayer *player; Image *image; }; + class Video_cycler: public Image_node { + //cycles through video inputs in order + public: + Video_cycler(){}; + Video_cycler(map &settings) { + base_settings(settings); + }; + ~Video_cycler(){}; + bool load(const string &filename); + Image *get_output(const Frame_spec &frame){ + int which_input=0; + Time_spec requested=Time_spec(frame.time,frame.framerate); + if (inputs[0]->connection) { + which_input=((int)((Signal_node*)inputs[0]->connection)->get_output(requested))%image_inputs.size(); + } + if (image_inputs.size()) { + if (image_inputs[which_input]->connection){ + return (((Image_node*)image_inputs[which_input]->connection)->get_output(frame)); + } + } + return nullptr; + } + Video_cycler* clone(map &_settings) { return new Video_cycler(_settings);}; + private: + }; //------------------------------------------------------------------- class Node_factory{ public: @@ -484,7 +523,7 @@ bool flessorequal(const float u,const float v){ vector find_nodes(const string &type); Node* find_node(const string &type); bool signal_render(string &signal_xml,const float framerate); - bool video_render(const string &output_filename,const string &audio_filename,const float framerate); + bool video_render(const string &output_filename,const string &audio_filename,const float framerate,float& progress); int load(Poco::UUID uid); bool load(string &graph_filename); UUID save(); //save to DB, returns UUID of saved graph @@ -526,6 +565,7 @@ bool flessorequal(const float u,const float v){ audio_thumb=new Audio_thumbnailer(); state=IDLE; output_framerate=25.0f; + audio_loaded=false; }; void runTask(); void add_queue(int item); @@ -538,7 +578,7 @@ bool flessorequal(const float u,const float v){ bool load_video(const string &nodeID,const string &filename);//can be performance or clip private: int state; - double progress; //for a locking process: audio analysis or rendering + float progress; //for a locking process: audio analysis or rendering //thread only does one thing at once std::deque work_queue; Poco::Mutex mutex; //lock for access from parent thread @@ -550,6 +590,7 @@ bool flessorequal(const float u,const float v){ Graph graph; Node_factory factory; float output_framerate; + bool audio_loaded; }; } diff --git a/rotord/utils.cpp b/rotord/utils.cpp new file mode 100644 index 0000000..d357319 --- /dev/null +++ b/rotord/utils.cpp @@ -0,0 +1,19 @@ +#include "utils.h" + +using namespace std; + +//float equality +bool fequal(const float u,const float v){ + if (abs(u-v)<.001) return true; + else return false; +}; +bool flessorequal(const float u,const float v){ + //v is less or equal to u + if (u-v>-.001) return true; + else return false; +}; +bool fmoreorequal(const float u,const float v){ + //v is more or equal to u + if (v-u>-.001) return true; + else return false; +}; diff --git a/rotord/utils.h b/rotord/utils.h new file mode 100644 index 0000000..e9084ff --- /dev/null +++ b/rotord/utils.h @@ -0,0 +1,6 @@ +#include + +//float equality +bool fequal(const float u,const float v); +bool flessorequal(const float u,const float v); +bool fmoreorequal(const float u,const float v); -- cgit v1.2.3