diff options
Diffstat (limited to 'rotord/src')
| -rw-r--r-- | rotord/src/graph.cpp | 18 | ||||
| -rw-r--r-- | rotord/src/graph.h | 2 | ||||
| -rw-r--r-- | rotord/src/rendercontext.cpp | 73 | ||||
| -rw-r--r-- | rotord/src/rendercontext.h | 5 | ||||
| -rw-r--r-- | rotord/src/rotor.h | 44 |
5 files changed, 95 insertions, 47 deletions
diff --git a/rotord/src/graph.cpp b/rotord/src/graph.cpp index b94d04c..f904a9d 100644 --- a/rotord/src/graph.cpp +++ b/rotord/src/graph.cpp @@ -79,7 +79,7 @@ bool Graph::preview(xmlIO &XML,string &node,string &_format,int frame,int w,int return false; } -bool Graph::video_render(const string &output_filename,const float framerate) { +bool Graph::video_render(const string &output_filename,const float framerate,int start, int stop) { //https://www.adobe.com/devnet/video/articles/mp4_movie_atom.html //https://www.google.ie/search?q=ffmbc&aq=f&oq=ffmbc&aqs=chrome.0.57j0l2j60j0j60.4360j0&sourceid=chrome&ie=UTF-8#q=ffmbc+git @@ -130,9 +130,9 @@ bool Graph::video_render(const string &output_filename,const float framerate) { //25fps video and 43.06640625fps audio? hmm //how to get the timecodes correct for the interleaved files - struct timeval start, end; + struct timeval _start, _end; - gettimeofday(&start, NULL); + gettimeofday(&_start, NULL); uint16_t *audioframe=nullptr; uint16_t *audio=nullptr; @@ -148,13 +148,13 @@ bool Graph::video_render(const string &output_filename,const float framerate) { float vstep=1.0f/framerate; float v=0.0f; - float vf=0.0f; - float af=0.0f; + float vf=start*vstep; + float af=start*vstep; int aoffs=0; int audioend=0; Audio_frame *a; - int64_t sample_start=0; - while (vf<duration&&!cancelled){ //-vstep) { + int64_t sample_start=(start*audioloader.get_sample_rate())/framerate; + while (vf<min(duration,stop*vstep)&&!cancelled){ //-vstep) { if (usingaudio) { if (audioloader.get_samples(audio,sample_start,samples_in_frame)) { @@ -217,9 +217,9 @@ bool Graph::video_render(const string &output_filename,const float framerate) { exporter.finishRecord(); - gettimeofday(&end, NULL); + gettimeofday(&_end, NULL); - float mtime = ((end.tv_sec-start.tv_sec) + (end.tv_usec-start.tv_usec)/1000000.0) + 0.5; + float mtime = ((_end.tv_sec-_start.tv_sec) + (_end.tv_usec-_start.tv_usec)/1000000.0) + 0.5; logger.information("Video_output: rendered "+output_filename+": in "+toString(mtime)+" seconds"); diff --git a/rotord/src/graph.h b/rotord/src/graph.h index 3267bb3..a13bddf 100644 --- a/rotord/src/graph.h +++ b/rotord/src/graph.h @@ -44,7 +44,7 @@ namespace Rotor { vector<Node*> find_nodes(const string &type); //could be a way of finding a set based on capabilities? Node* find_node(const string &type); bool signal_render(string &signal_xml,const float framerate); - bool video_render(const string &output_filename,const float framerate); + bool video_render(const string &output_filename,const float framerate,int start, int end); bool load(string data,string media_path); bool loadFile(string &filename,string media_path); bool parseXml(string media_path); diff --git a/rotord/src/rendercontext.cpp b/rotord/src/rendercontext.cpp index 53c7c64..1beb6cc 100644 --- a/rotord/src/rendercontext.cpp +++ b/rotord/src/rendercontext.cpp @@ -36,7 +36,7 @@ void Render_context::runTask() { if(cmd.task==RENDER) { state=RENDERING; renders[cmd.uid]=Render_status(RENDERING); - if(graph.video_render(output_filename,output_framerate)){ + if(graph.video_render(output_filename,output_framerate,start,stop)){ state=IDLE; if (graph.cancelled) renders[cmd.uid].status=CANCELLED; else renders[cmd.uid].status=RENDER_READY; @@ -373,28 +373,35 @@ void Render_context::session_command(const Session_command& command,xmlIO& XML,H if (command.method=="PUT") { //get vide file location and initiate analysis if (command.body!="") { //there should be a filename + a destination node if (state!=RENDERING) { - string video_filename=media_dir+command.body; - //check file exists - Poco::File f=Poco::File(video_filename); - if (f.exists()) { - if (graph.load_video(command.commands[2],video_filename)) { - //pass to worker thread ??if engine is ready?? ??what if engine has finished but results aren't read?? - //DUMMY RESPONSE - status=HTTPResponse::HTTP_OK; - logger.information("Succesfully loaded "+command.body+" into video node "+command.commands[2]); - XML.addValue("status","Succesfully loaded "+command.body+" into video node "+command.commands[2]); + if (command.commands.size()>2) { + string video_filename=media_dir+command.body; + //check file exists + Poco::File f=Poco::File(video_filename); + if (f.exists()) { + if (graph.load_video(command.commands[2],video_filename)) { + //pass to worker thread ??if engine is ready?? ??what if engine has finished but results aren't read?? + //DUMMY RESPONSE + status=HTTPResponse::HTTP_OK; + logger.information("Succesfully loaded "+command.body+" into video node "+command.commands[2]); + XML.addValue("status","Succesfully loaded "+command.body+" into video node "+command.commands[2]); + } + else { + status=HTTPResponse::HTTP_INTERNAL_SERVER_ERROR; + logger.error("ERROR: could not load "+command.body+" into video node "+command.commands[2]); + XML.addValue("error","could not load "+command.body+" into video node "+command.commands[2]); + } } else { - status=HTTPResponse::HTTP_INTERNAL_SERVER_ERROR; - logger.error("ERROR: could not load "+command.body+" into video node "+command.commands[2]); - XML.addValue("error","could not load "+command.body+" into video node "+command.commands[2]); - } - } - else { status=HTTPResponse::HTTP_NOT_FOUND; logger.error("ERROR: "+command.body+" not found"); XML.addValue("error",command.body+" not found"); } + } + else { + status=HTTPResponse::HTTP_NOT_FOUND; + logger.error("ERROR: video loader node not specified"); + XML.addValue("error","video loader node not specified"); + } } else { status=HTTPResponse::HTTP_BAD_REQUEST; @@ -495,15 +502,31 @@ void Render_context::session_command(const Session_command& command,xmlIO& XML,H if (command.method=="PUT") { if (command.body!="") { if (state==IDLE) { - output_filename=output_dir+command.body; - if (command.body!="") { -// output_framerate=toFloat(command.body); + Poco::StringTokenizer t1(command.body,","); + if (t1.count()>1){ + output_filename=output_dir+t1[0]; + start=toInt(t1[1]); + if (t1.count()>2){ + stop=toInt(t1[2]); + if (t1.count()>3){ + float framerate=toFloat(t1[3]); + if (framerate>0.0f) { + output_framerate=framerate; + } + } } - add_queue(Session_task(command.uid,RENDER)); - status=HTTPResponse::HTTP_OK; - logger.information("Starting render: "+command.body); - XML.addValue("status","Starting render: "+command.body); - XML.addValue("render_id",command.uid); + } + else { + start=0; + stop=999999; + output_filename=output_dir+command.body; + } + add_queue(Session_task(command.uid,RENDER)); + status=HTTPResponse::HTTP_OK; + logger.information("Starting render: "+command.body); + XML.addValue("status","Starting render: "+command.body); + XML.addValue("render_id",command.uid); + XML.addValue("path",output_filename); } else { status=HTTPResponse::HTTP_BAD_REQUEST; diff --git a/rotord/src/rendercontext.h b/rotord/src/rendercontext.h index 8656df4..130c678 100644 --- a/rotord/src/rendercontext.h +++ b/rotord/src/rendercontext.h @@ -61,7 +61,8 @@ namespace Rotor { Render_context(const std::string& name): Task(name) { state=IDLE; output_framerate=25.0f; - + start=0; + stop=999999; xmlIO xml; if(xml.loadFile("settings.xml") ){ graph_dir=xml.getAttribute("Rotor","graph_dir","",0); @@ -108,7 +109,7 @@ namespace Rotor { Audio_thumbnailer *audio_thumb; Graph graph; float output_framerate; - + int start,stop; }; } diff --git a/rotord/src/rotor.h b/rotord/src/rotor.h index 72ef7d0..be6ecee 100644 --- a/rotord/src/rotor.h +++ b/rotord/src/rotor.h @@ -894,7 +894,7 @@ namespace Rotor { if (attributes["filename"]->value!="") { load(find_setting(settings,"media_path","")+attributes["filename"]->value); } - lastframe=0; + lastframe=-1; }; ~Video_loader(){}; bool load(const string &filename){ @@ -919,17 +919,40 @@ namespace Rotor { if (isLoaded){ float clipframerate=(parameters["framerate"]->value==0.0f?player.get_framerate():parameters["framerate"]->value); float clipspeed=(clipframerate/frame.framerate)*parameters["speed"]->value; - int wanted=(((int) ((frame.time*frame.framerate)+0.5))%max(1,player.get_number_frames()-1)); - if (wanted!=lastframe){ - if (!player.fetch_frame(frame.w,frame.h,wanted)) { //seek fail - Poco::Logger& logger = Poco::Logger::get("Rotor"); - logger.error("Video_loader failed to seek frame "+toString(wanted)+" of "+attributes["filename"]->value); - - if (image.w>0) return ℑ //just return the previous frame if possible - else return nullptr; + if (attributes["mode"]->intVal==VIDEOFRAMES_blend){ + float wanted=fmod(frame.time*frame.framerate,(float)player.get_number_frames()); + if (((int)wanted)!=lastframe){ + //get a new pair of frames possibly by switching the next one + if (lastframe=(int)wanted-1){ + in1=in2; + } + else { + player.fetch_frame(frame.w,frame.h,(int)wanted); + in1.setup_fromRGB(frame.w,frame.h,player.frame->Data[0],player.frame->Linesize[0]-(frame.w*3)); + } + player.fetch_frame(frame.w,frame.h,((int)wanted+1)%max(1,player.get_number_frames())); + in2.setup_fromRGB(frame.w,frame.h,player.frame->Data[0],player.frame->Linesize[0]-(frame.w*3)); } - image.setup_fromRGB(frame.w,frame.h,player.frame->Data[0],player.frame->Linesize[0]-(frame.w*3)); lastframe=wanted; + float amt=1.0f-(wanted-((int)wanted)); + image=in1; + image*=amt; + Image in2t=in2; + in2t*=(1.0f-amt); + image+=in2t; + } + else { + int wanted=(((int) ((frame.time*frame.framerate)+0.5))%max(1,player.get_number_frames())); + if (wanted!=lastframe){ + if (!player.fetch_frame(frame.w,frame.h,wanted)) { //seek fail + Poco::Logger& logger = Poco::Logger::get("Rotor"); + logger.error("Video_loader failed to seek frame "+toString(wanted)+" of "+attributes["filename"]->value); + + if (image.w>0) return ℑ //just return the previous frame if possible + else return nullptr; + } + image.setup_fromRGB(frame.w,frame.h,player.frame->Data[0],player.frame->Linesize[0]-(frame.w*3)); + } } return ℑ } @@ -941,6 +964,7 @@ namespace Rotor { //ffmpegsource::decoder player; libav::video_decoder player; int lastframe; + Image in1,in2; //for blend frames; }; class Video_output: public Image_node { //Video_output 'presents' the output movie. Aspect ratio, bars, fadein/fadeout would happen here |
