#ifndef GRAPH_H #define GRAPH_H #include "Poco/StringTokenizer.h" #include "rotor.h" #include "nodes_signals.h" #include "nodes_audio_analysis.h" /*------------------------ Graph is an instance of a rotor renderer tidy up loading stuff kill xml or retain? make codebase closer -validate loader menthod get number of nodes copy nodes ` -------------------------*/ namespace Rotor { class Graph{ public: Graph(){duration=20.0f;loaded = false;outW=640;outH=360;audio_thumb=new Audio_thumbnailer();use_fragmentation=false;analysis_seed=0;}; Graph(const string& _uid,const string& _desc){ init(_uid,_desc); audio_loaded=false; bitRate=1000000; }; void init(const string& _uid,const string& _desc){ uid=_uid; description=_desc; duration=20.0f; framerate=25.0f; cancelled=false; }; ~Graph(){ clear(); delete audio_thumb;}; void clear(){ for (auto n: nodes) { delete n.second; } nodes.clear(); loaded=false; } string uid; //every version of a graph has a UUID, no particular need to actually read its data(?) //?? is it faster than using strings?? string description; std::unordered_map nodes; vector 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(xmlIO &XML,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); bool parseJson(string &data,string &media_path); bool set_resolution(int w,int h); bool preview(xmlIO &XML,string &node,string &format,int frame,int w,int h); bool check_audio(string audio,string path); bool print_features(xmlIO &XML,string &node); bool load_audio(const string &filename,vector processors); bool load_video(const string &nodeID,const string &filename);//can be performance or clip bool set_bitrate(int b){ if (b>64000){ bitRate=b; return true; } else return false; } bool set_fragmentation(bool f){ use_fragmentation=f; return true; } bool loaded; float duration; float framerate; const string graphToString(); xmlIO xml; bool audio_loaded; string audio_filename; bool cancelled; float progress; int bitRate; //Poco::Mutex mutex; //lock for access from parent thread Audio_thumbnailer *audio_thumb; private: int outW,outH; bool use_fragmentation; int analysis_seed; }; class Thumbnailer{ public: bool make(const string &inputfilename,int w,int h,const string &outputfilename) { //first try svg RsvgHandle * rsvg=rsvg_handle_new_from_file(inputfilename.c_str(),nullptr); if (rsvg) { RsvgDimensionData dims; rsvg_handle_get_dimensions(rsvg,&dims); cerr<<"Rotor: SVG loaded "<Data[0],player.frame->Linesize[0]-(w*3)); cv::Mat cp; cvtColor(i.rgb,cp,CV_RGB2BGR); cv::imwrite(outputfilename.c_str(),cp); return true; } } //fall back to audio libav::audio_decoder loader; if (loader.open(inputfilename)) { Audio_thumbnailer at; at.width=w; at.height=h; int rate = loader.get_sample_rate(); int samples = loader.get_number_samples(); int channels= loader.get_number_channels(); int bits = loader.get_bit_depth(); at.init(channels,bits,samples,rate); bool finished=false; uint16_t *audio=new uint16_t[1024*loader.get_number_channels()]; uint64_t sample=0; while (loader.get_samples(audio,sample,1024)) { at.process_frame((uint8_t*)audio,1024); sample+=1024; } cv::Mat co=cv::Mat(h,w,CV_8UC3); uchar op; for (int i=0;iabs(((float)i-h/2)/(h/2))) op=0xFF; else op=0x00; r[j*3]=op/4; r[j*3+1]=op; r[j*3+2]=op/4; } } cv::imwrite(outputfilename.c_str(),co); return true; } return false; } private: libav::video_decoder player; }; } #endif