diff options
| author | Comment <tim@gray.(none)> | 2013-07-30 16:05:44 +0100 |
|---|---|---|
| committer | Comment <tim@gray.(none)> | 2013-07-30 16:05:44 +0100 |
| commit | 01f53fe4485b3c96c0f553e1cade69f77081b078 (patch) | |
| tree | 5717695bbc7460ff7e41649c050c50ff6f786341 /rotord/src | |
| parent | 7fd8fbbf69631a868b8274a25023023cde141a4c (diff) | |
| parent | c2237c2116ca551c0755821beadae3fac54547e7 (diff) | |
Merge branch 'master' of eclectronics.org@eclectronics.org:rotor
Diffstat (limited to 'rotord/src')
| -rw-r--r-- | rotord/src/cvimage.cpp | 7 | ||||
| -rw-r--r-- | rotord/src/cvimage.h | 5 | ||||
| -rwxr-xr-x | rotord/src/libavwrapper.cpp | 22 | ||||
| -rwxr-xr-x | rotord/src/libavwrapper.h | 11 | ||||
| -rw-r--r-- | rotord/src/nodes_drawing.h | 39 | ||||
| -rwxr-xr-x | rotord/src/rotor.cpp | 77 | ||||
| -rwxr-xr-x | rotord/src/rotor.h | 118 |
7 files changed, 154 insertions, 125 deletions
diff --git a/rotord/src/cvimage.cpp b/rotord/src/cvimage.cpp index c18c585..a03d81c 100644 --- a/rotord/src/cvimage.cpp +++ b/rotord/src/cvimage.cpp @@ -3,6 +3,13 @@ using namespace std; namespace Rotor { + //space out to 32 bit RGB padding for cairo + void Image::convert24(){ + cv::cvtColor(rgb,rgb, CV_RGBA2RGB); + } + void Image::convert32(){ + cv::cvtColor(rgb,rgb, CV_RGB2RGBA); + } Image & Image::operator+=(const Image &other) { if (other.w!=w||other.h!=h) { cerr<<"Rotor: cannot add images with different sizes! (wanted "<<w<<"x"<<h<<", got "<<other.w<<"x"<<other.h<<")"<<endl; diff --git a/rotord/src/cvimage.h b/rotord/src/cvimage.h index 2f9ed3b..336c41b 100644 --- a/rotord/src/cvimage.h +++ b/rotord/src/cvimage.h @@ -87,6 +87,9 @@ namespace Rotor { h=0; ownsRGBdata=ownsAdata=ownsZdata=false; } + //space out to 32 bit RGB padding for cairo + void convert24(); + void convert32(); int getStride(){ return w*3; } @@ -155,7 +158,7 @@ namespace Rotor { t->w=w; t->h=h; t->RGBdata=t->rgb.data; //can move to use the bare pointer eventually - t->ownsRGBdata=false; //will not be necessary + t->ownsRGBdata=false; //always just deallocate cv::Mat from stack /* for (int i=0;i<w*h*3;i++) { t->RGBdata[i]=RGBdata[i]; diff --git a/rotord/src/libavwrapper.cpp b/rotord/src/libavwrapper.cpp index a19e01a..673c2be 100755 --- a/rotord/src/libavwrapper.cpp +++ b/rotord/src/libavwrapper.cpp @@ -76,6 +76,18 @@ int64_t seekFunction(void* opaque, int64_t offset, int whence) } +void libav::maybeInitFFMpegLib() +{ + if (b_is_one_time_inited) + return; + av_register_all(); + avcodec_register_all(); + avformat_network_init(); + b_is_one_time_inited = true; +} + + + ///////////////////////////// // AVPacketWrapper methods // ///////////////////////////// @@ -484,15 +496,6 @@ void libav::decoder::initialize() maybeInitFFMpegLib(); } -void libav::maybeInitFFMpegLib() -{ - if (b_is_one_time_inited) - return; - av_register_all(); - avcodec_register_all(); - avformat_network_init(); - b_is_one_time_inited = true; -} bool libav::decoder::avtry(int result, const std::string& msg) { if ((result < 0) && (result != AVERROR_EOF)) { @@ -508,7 +511,6 @@ bool libav::decoder::avtry(int result, const std::string& msg) { - /////////////////////////// // encoder methods // /////////////////////////// diff --git a/rotord/src/libavwrapper.h b/rotord/src/libavwrapper.h index 656f885..4c5cb02 100755 --- a/rotord/src/libavwrapper.h +++ b/rotord/src/libavwrapper.h @@ -139,17 +139,6 @@ namespace libav { int numFrames; int sc; // number of color channels - // For loading from URL - /* - static const int ioBufferSize = 32768; - unsigned char * ioBuffer; - QNetworkAccessManager networkManager; - AVIOContext* avioContext; - QFile fileStream; - QNetworkReply* reply; - QBuffer fileBuffer; - QByteArray byteArray; - */ }; diff --git a/rotord/src/nodes_drawing.h b/rotord/src/nodes_drawing.h index 11df2d6..05135d6 100644 --- a/rotord/src/nodes_drawing.h +++ b/rotord/src/nodes_drawing.h @@ -9,7 +9,11 @@ namespace Rotor { public: Draw(){image=nullptr;}; Draw(map<string,string> &settings) { + image=nullptr; base_settings(settings); + if(CAIRO_HAS_IMAGE_SURFACE==1) { + cerr<<"cairo has image surface"<<endl; + } }; ~Draw(){ if (image) delete image;}; Draw* clone(map<string,string> &_settings) { return new Draw(_settings);}; @@ -20,19 +24,40 @@ namespace Rotor { if (image) delete image; image=(((Image_node*)image_inputs[0]->connection)->get_output(frame))->clone(); } - else image->setup(frame.w,frame.h); + else { + if (!image) image =new Image(); + image->setup(frame.w,frame.h); + } } - else image->setup(frame.w,frame.h); //do this twice or use a goto + else { + if (!image) image =new Image(); + image->setup(frame.w,frame.h); //do this twice or use a goto + } //draw onto new or input image + image->convert32(); //pad frame out to 32 bits for cairo + //turns out cairo doesn't draw at all if the stride definition is wrong + //crashes like this though cairo_surface_t * cs = cairo_image_surface_create_for_data (image->RGBdata, CAIRO_FORMAT_RGB24, image->w, image->h, - image->getStride()); - cairo_t *c=cairo_create(cs); - cairo_rectangle(c, image->w/2, image->h/2, image->w, image->h); - cairo_set_source_rgb(c, 1.0, 0.0, 0.0); - cairo_fill(c); + image->w*4); + cairo_t * cr = cairo_create (cs); + cairo_rectangle(cr, 0,0, image->w/2, image->h/2); + cairo_set_source_rgb(cr, 0,1.0,0); //cairo colour is 0.0->1.0 + cairo_fill(cr); + + cairo_text_extents_t te; + cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); + cairo_select_font_face (cr, "Georgia", + CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); + cairo_set_font_size (cr, 20); + cairo_text_extents (cr, "hello world!", &te); + cairo_move_to (cr, 20,20); + cairo_show_text (cr, "hello world!"); + cairo_fill(cr); + + image->convert24(); //convert frame back to 24 bits return image; } private: diff --git a/rotord/src/rotor.cpp b/rotord/src/rotor.cpp index 8b72c50..77433ac 100755 --- a/rotord/src/rotor.cpp +++ b/rotord/src/rotor.cpp @@ -268,22 +268,7 @@ bool Video_output::render(const float duration, const float framerate,const stri } bool Video_loader::load(const string &filename){ - /* - //gstreamer needs absolute paths ALWAYS - //string uri="file:///home/tim/workspace/rotor/rotord/"+filename; - Poco::Path path; - string uri="file://"+path.current()+filename; - //cerr << "video input: loading "<<uri<<endl; - if (player->loadMovie(uri)){ - player->play(); - player->setPaused(true); - player->setFrameByFrame(true); - player->update(); - cerr<<"Rotor::Video_loader: "<<filename<<", "<<player->getDuration()<<" seconds "<<", "<<player->getWidth()<<"x"<<player->getHeight()<<endl; - image->setup_fromRGB(player->getWidth(),player->getHeight(),(uint8_t*) player->getPixels()); - return true; - } - */ + if (isLoaded) { player.cleanup(); ///should be in decoder class? isLoaded=false; @@ -299,63 +284,35 @@ bool Video_loader::load(const string &filename){ return false; } Image* Video_loader::output(const Frame_spec &frame){ - //wonder about the actual mechanism used by gstreamer - //have to implment callback when seek is ready? - //presume gstreamer caches a loaded frame? - - - //deal with reolution: swscale from avcodec or put scaler in pipeline? - //can image node point to buffer in gst rather than copying the pixels? - - //to test using fp time to seek: need a short movie with synced audio - - //fix actual duration and audio file - //trace frame that is being read - /* - if (player->isLoaded()){ - //player->setPosition(frame.time); - int wanted=((int) (frame.time*frame.framerate))%(player->getTotalNumFrames()-2); //-2?? - player->setFrame(wanted); - //while (player->getCurrentFrame()!=wanted){ - // cerr << "seeking to "<<wanted<<" :"<<player->getCurrentFrame()<<endl; - //player->setFrame(wanted); - //player->update(); - // sleep(.001); - //} - player->update(); - image->RGBdata=player->getPixels(); //don't really know why this is needed every frame - //cerr<<"Video_loader: retrieving frame "<<((int) (frame.time*frame.framerate))<<endl; - return image; - } - */ if (isLoaded){ int wanted=(((int) ((frame.time*frame.framerate)+0.5))%(player.getNumberOfFrames())); //+1 is necessary because 1st frame in a video is number 1? - - //if (wanted==99){ - // cerr<<"videoloader: near the end"<<endl; - //} - - //cerr<<"videoloader: requesting frame "<<wanted<<endl; - //if (wanted==68) { - // int nothing=0; - //} - if (!player.fetchFrame(frame.w,frame.h,wanted)) { //seek fail cerr<<"Rotor: failed to seek frame"<<endl; if (image.w>0) return ℑ //just return the previous frame if possible else return nullptr; }; - //cerr<<"Video_loader: setting up frame: lineoffset="<<(player.pFrameRGB->linesize[0]-(frame.w*3))<<endl; image.setup_fromRGB(frame.w,frame.h,player.pFrameRGB->data[0],player.pFrameRGB->linesize[0]-(frame.w*3)); return ℑ } + return nullptr; +}; +/* +bool CVideo_loader::load(const string &filename){ - //confusingly, crashes with files not made with short files? - //seems to be on last frame? - returns nullptr - still tries to clone? - //can't really return 1st frame instead, should get # of frames right 1st? - //think about what echo trails does on the last frame + Poco::Path path; + string uri="file://"+filename; + isLoaded=player.open(filename); + if (isLoaded){ + cerr<<"Rotor::Video_loader: "<<filename<<", "<<player.get(CV_CAP_PROP_FRAME_COUNT)<<" frames "<<", "<<player.get(CV_CAP_PROP_FRAME_WIDTH)<<"x"<<player.get(CV_CAP_PROP_FRAME_HEIGHT)<<endl; + return true; + } + cerr<<"Rotor::Video_loader: failed to load "<<filename<<endl; + return false; +} +Image* CVideo_loader::output(const Frame_spec &frame){ return nullptr; }; +*/
\ No newline at end of file diff --git a/rotord/src/rotor.h b/rotord/src/rotor.h index f922fcf..ac11b9c 100755 --- a/rotord/src/rotor.h +++ b/rotord/src/rotor.h @@ -12,6 +12,14 @@ TODO - use try.. catch and dynamic_cast to verify node connections rather than c TODO - put the boilerplate code for checking inputs into the base class, finally call checked_output http://stackoverflow.com/questions/5261658/how-to-seek-in-ffmpeg-c-c + +300713 +trying to use opencv video loader for seeking +not so good - conflicts with included libav - seems to be incorrectly loaded + +would maybe need to do something like +http://stackoverflow.com/questions/12427928/configure-and-build-opencv-to-custom-ffmpeg-install + */ #include <unordered_map> @@ -70,10 +78,12 @@ extern "C" { #define AUDIO_INBUF_SIZE 20480 #define AUDIO_REFILL_THRESH 4096 +#include <highgui.h> //for opencv video IO + #include "xmlIO.h" #include "utils.h" //fequal -#include "libavwrapper.h" #include "cvimage.h" +#include "libavwrapper.h" namespace Rotor { #define IDLE 0 @@ -366,6 +376,12 @@ namespace Rotor { }; Arithmetic* clone(map<string,string> &_settings) { return new Arithmetic(_settings);}; const float output(const Time_spec &time) { + if (op==ARITHMETIC_divide||op==ARITHMETIC_modulo){ + if (value==0.0f) { + cerr<<"Arithmetic: caught division by zero"<<endl; + return 0.0f; + } + } if (inputs.size()) { //there should there be a way to specify number of inputs in the code rather than in xml if (inputs[0]->connection) { float in= (((Signal_node*)inputs[0]->connection)->get_output(time)); @@ -578,41 +594,6 @@ namespace Rotor { Image *image; //is an image generator //bool invert; }; - class Video_output: public Image_node { - public: - Video_output(){}; - Video_output(map<string,string> &settings) { - base_settings(settings); - }; - ~Video_output(){ }; - Image *output(const Frame_spec &frame){ - if (image_inputs[0]->connection) { - return ((Image_node*)(image_inputs[0]->connection))->get_output(frame); - } - else return nullptr; - }; - Video_output* clone(map<string,string> &_settings) { return new Video_output(_settings);}; - bool render(const float duration, const float framerate,const string &output_filename,const string &audio_filename,float& progress,int w,int h); - - private: - - }; - class Video_loader: public Image_node { - public: - Video_loader(){}; - Video_loader(map<string,string> &settings) { - base_settings(settings); - isLoaded=false; - }; - ~Video_loader(){}; - bool load(const string &filename); - Image *output(const Frame_spec &frame); - Video_loader* clone(map<string,string> &_settings) { return new Video_loader(_settings);}; - bool isLoaded; - private: - libav::decoder player; - Image image; - }; class Video_cycler: public Image_node { //cycles through video inputs in order public: @@ -1261,6 +1242,71 @@ namespace Rotor { private: Image *image; //is an image generator }; + class Video_loader: public Image_node { + public: + Video_loader(){}; + Video_loader(map<string,string> &settings) { + base_settings(settings); + isLoaded=false; + }; + ~Video_loader(){}; + bool load(const string &filename); + Image *output(const Frame_spec &frame); + Video_loader* clone(map<string,string> &_settings) { return new Video_loader(_settings);}; + bool isLoaded; + private: + libav::decoder player; + Image image; + }; + /* + class CVideo_loader: public Image_node { + + // attempt + + // /usr/bin/ld: warning: libavcodec.so.53, needed by /usr/lib/gcc/i686-linux-gnu/4.7/../../../../lib/libopencv_highgui.so, may conflict with libavcodec.so.55 + // /usr/bin/ld: warning: libavformat.so.53, needed by /usr/lib/gcc/i686-linux-gnu/4.7/../../../../lib/libopencv_highgui.so, may conflict with libavformat.so.55 + // /usr/bin/ld: warning: libavutil.so.51, needed by /usr/lib/gcc/i686-linux-gnu/4.7/../../../../lib/libopencv_highgui.so, may conflict with libavutil.so.52 + + // No URL Protocols are registered. Missing call to av_register_all()? + // libav::Error: file:///mnt/rotor/media/newsins1_360.mp4 Protocol not found + // Rotor::Video_loader: failed to load /mnt/rotor/media/newsins1_360.mp4 + // 30-07-2013 09:35:31 Rotor: ERROR: could not load newsins1_360.mp4 into video node 03 + + public: + CVideo_loader(){}; + CVideo_loader(map<string,string> &settings) { + base_settings(settings); + isLoaded=false; + }; + ~CVideo_loader(){}; + bool load(const string &filename); + Image *output(const Frame_spec &frame); + CVideo_loader* clone(map<string,string> &_settings) { return new CVideo_loader(_settings);}; + bool isLoaded; + private: + cv::VideoCapture player; + Image image; + }; + */ + class Video_output: public Image_node { + public: + Video_output(){}; + Video_output(map<string,string> &settings) { + base_settings(settings); + }; + ~Video_output(){ }; + Image *output(const Frame_spec &frame){ + if (image_inputs[0]->connection) { + return ((Image_node*)(image_inputs[0]->connection))->get_output(frame); + } + else return nullptr; + }; + Video_output* clone(map<string,string> &_settings) { return new Video_output(_settings);}; + bool render(const float duration, const float framerate,const string &output_filename,const string &audio_filename,float& progress,int w,int h); + + private: + + }; //------------------------------------------------------------------- class Node_factory{ public: |
