summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorComment <tim@gray.(none)>2013-09-27 19:36:29 -0400
committerComment <tim@gray.(none)>2013-09-27 19:36:29 -0400
commit873f295e28a20e2e774852d8d7010ff5629549b4 (patch)
tree3237d0b7f9852d3ab0f69bdd59aac2848ed1dec1
parentf40d511775eb8dfae9a28870c5e0125b5e55b305 (diff)
fixed crash when no node specified to load video
-rw-r--r--rotord/src/graph.cpp18
-rw-r--r--rotord/src/graph.h2
-rw-r--r--rotord/src/rendercontext.cpp73
-rw-r--r--rotord/src/rendercontext.h5
-rw-r--r--rotord/src/rotor.h44
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 &image; //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 &image; //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 &image;
}
@@ -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