From c2237c2116ca551c0755821beadae3fac54547e7 Mon Sep 17 00:00:00 2001 From: Tim Redfern Date: Tue, 30 Jul 2013 13:52:22 +0100 Subject: perfecting draw node --- rotord/src/cvimage.cpp | 7 +++ rotord/src/cvimage.h | 5 +- rotord/src/libavwrapper.cpp | 22 +++++---- rotord/src/libavwrapper.h | 11 ----- rotord/src/nodes_drawing.h | 39 ++++++++++++--- rotord/src/rotor.cpp | 77 +++++++---------------------- rotord/src/rotor.h | 118 ++++++++++++++++++++++++++++++-------------- 7 files changed, 154 insertions(+), 125 deletions(-) (limited to 'rotord/src') 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=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;iRGBdata[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 &settings) { + image=nullptr; base_settings(settings); + if(CAIRO_HAS_IMAGE_SURFACE==1) { + cerr<<"cairo has image surface"< &_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 "<loadMovie(uri)){ - player->play(); - player->setPaused(true); - player->setFrameByFrame(true); - player->update(); - cerr<<"Rotor::Video_loader: "<getDuration()<<" seconds "<<", "<getWidth()<<"x"<getHeight()<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 "<getCurrentFrame()<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))<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))<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: "< @@ -70,10 +78,12 @@ extern "C" { #define AUDIO_INBUF_SIZE 20480 #define AUDIO_REFILL_THRESH 4096 +#include //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 &_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"<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 &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 &_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 &settings) { - base_settings(settings); - isLoaded=false; - }; - ~Video_loader(){}; - bool load(const string &filename); - Image *output(const Frame_spec &frame); - Video_loader* clone(map &_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 &settings) { + base_settings(settings); + isLoaded=false; + }; + ~Video_loader(){}; + bool load(const string &filename); + Image *output(const Frame_spec &frame); + Video_loader* clone(map &_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 &settings) { + base_settings(settings); + isLoaded=false; + }; + ~CVideo_loader(){}; + bool load(const string &filename); + Image *output(const Frame_spec &frame); + CVideo_loader* clone(map &_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 &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 &_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: -- cgit v1.2.3