summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rotord/Makefile13
-rw-r--r--rotord/rotord.cbp59
-rw-r--r--rotord/src/cvimage.cpp7
-rw-r--r--rotord/src/cvimage.h5
-rwxr-xr-xrotord/src/libavwrapper.cpp22
-rwxr-xr-xrotord/src/libavwrapper.h11
-rw-r--r--rotord/src/nodes_drawing.h39
-rwxr-xr-xrotord/src/rotor.cpp77
-rwxr-xr-xrotord/src/rotor.h118
9 files changed, 194 insertions, 157 deletions
diff --git a/rotord/Makefile b/rotord/Makefile
index d7bd454..8fea700 100644
--- a/rotord/Makefile
+++ b/rotord/Makefile
@@ -10,6 +10,7 @@ MY_CFLAGS = -fpermissive -std=c++11 -I /usr/include/opencv -I /usr/include/cairo
# The linker options.libgstaasinklibgstaasink.so
MY_LIBS = -lcairo -lopencv_core -lopencv_video -lopencv_imgproc -lPocoNet -lPocoXML -lPocoUtil -lPocoFoundation -lvamp-hostsdk -lsndfile -L /usr/local/lib -lswscale -lavcodec -lavformat -lavfilter -lavdevice -lavutil -lstdc++ -lm
+#-lopencv_highgui
#MY_LIBS = -lPocoNet -lPocoXML -lPocoUtil -lPocoFoundation -lvamp-hostsdk -lsndfile -L /usr/local/lib -lswscale -lavcodec -lavformat -lavfilter -lavdevice -lavutil $(shell pkg-config gstreamer-0.10 gstreamer-video-0.10 gstreamer-base-0.10 --libs)
# -lgstreamer-0.10 -lgstreamer-video-0.10 -lgstreamer-base-0.10 -lglib-2.0 -lgstapp-0.10
#MY_LIBS = ../libavcodec/ffmpeg/libavcodec/libavcodec.a ../libavcodec/ffmpeg/libavutil/libavutil.a ../libavcodec/ffmpeg/libavformat/libavformat.a ../libavcodec/ffmpeg/libavfilter/libavfilter.a ../libavcodec/ffmpeg/libavdevice/libavdevice.a -lPocoNet -lPocoXML -lPocoUtil -lPocoFoundation -lvamp-hostsdk
@@ -27,7 +28,7 @@ SRCDIRS = src
# The executable file name.
# If not specified, current directory name or `a.out' will be used.
-PROGRAM = bin/rotord
+PROGRAM =
OBJ_OUTPUT = obj/
@@ -198,11 +199,13 @@ ctags: $(HEADERS) $(SOURCES)
#-------------------------------------
$(PROGRAM):$(OBJS)
ifeq ($(SRC_CXX),) # C program
- $(LINK.c) $(OBJS) $(MY_LIBS) -o $@
- @echo Type ./$@ to execute the program.
+ $(LINK.c) $(OBJS) $(MY_LIBS) -o bin/$@
+ @echo cd bin
+ @echo ./$@ to execute the program.
else # C++ program
- $(LINK.cxx) $(OBJS) $(MY_LIBS) -o $@
- @echo Type ./$@ to execute the program.
+ $(LINK.cxx) $(OBJS) $(MY_LIBS) -o bin/$@
+ @echo cd bin
+ @echo ./$@ to execute the program.
endif
ifndef NODEP
diff --git a/rotord/rotord.cbp b/rotord/rotord.cbp
index 80f2270..6ee182e 100644
--- a/rotord/rotord.cbp
+++ b/rotord/rotord.cbp
@@ -48,36 +48,41 @@
<Compiler>
<Add option="-Wall" />
</Compiler>
- <Unit filename="Makefile" />
- <Unit filename="Pixels.cpp" />
- <Unit filename="Pixels.h" />
- <Unit filename="graph.cpp" />
- <Unit filename="libavaudioloader.cpp" />
- <Unit filename="libavaudioloader.h" />
- <Unit filename="libavwrapper.cpp" />
- <Unit filename="libavwrapper.h" />
- <Unit filename="ofUtils.cpp" />
- <Unit filename="ofUtils.h" />
- <Unit filename="rendercontext.cpp" />
- <Unit filename="rotor.cpp" />
- <Unit filename="rotor.h" />
- <Unit filename="rotord.cpp" />
- <Unit filename="rotord.h" />
- <Unit filename="system.h" />
- <Unit filename="tinyxml.cpp" />
- <Unit filename="tinyxml.h" />
- <Unit filename="tinyxmlerror.cpp" />
- <Unit filename="tinyxmlparser.cpp" />
- <Unit filename="utils.cpp" />
- <Unit filename="utils.h" />
- <Unit filename="vampHost.cpp" />
- <Unit filename="vampHost.h" />
- <Unit filename="xmlIO.cpp" />
- <Unit filename="xmlIO.h" />
+ <Unit filename="src/Pixels.cpp" />
+ <Unit filename="src/Pixels.h" />
+ <Unit filename="src/cvimage.cpp" />
+ <Unit filename="src/cvimage.h" />
+ <Unit filename="src/graph.cpp" />
+ <Unit filename="src/image.h" />
+ <Unit filename="src/libavwrapper.cpp" />
+ <Unit filename="src/libavwrapper.h" />
+ <Unit filename="src/nodes_audio_analysis.h" />
+ <Unit filename="src/nodes_drawing.h" />
+ <Unit filename="src/ofUtils.cpp" />
+ <Unit filename="src/ofUtils.h" />
+ <Unit filename="src/params.h" />
+ <Unit filename="src/rendercontext.cpp" />
+ <Unit filename="src/rotor.cpp" />
+ <Unit filename="src/rotor.h" />
+ <Unit filename="src/rotord.cpp" />
+ <Unit filename="src/rotord.h" />
+ <Unit filename="src/system.h" />
+ <Unit filename="src/tinyxml.cpp" />
+ <Unit filename="src/tinyxml.h" />
+ <Unit filename="src/tinyxmlerror.cpp" />
+ <Unit filename="src/tinyxmlparser.cpp" />
+ <Unit filename="src/utils.cpp" />
+ <Unit filename="src/utils.h" />
+ <Unit filename="src/vampHost.cpp" />
+ <Unit filename="src/vampHost.h" />
+ <Unit filename="src/xmlIO.cpp" />
+ <Unit filename="src/xmlIO.h" />
<Extensions>
<envvars />
<code_completion />
- <debugger />
+ <debugger>
+ <search_path add="/home/tim/workspace/rotor/rotord/src" />
+ </debugger>
<lib_finder disable_auto="1" />
</Extensions>
</Project>
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 &image; //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 &image;
}
+ 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: