summaryrefslogtreecommitdiff
path: root/rotord/src
diff options
context:
space:
mode:
authorTim Redfern <tim@herge.(none)>2013-08-08 13:32:46 +0100
committerTim Redfern <tim@herge.(none)>2013-08-08 13:32:46 +0100
commita2254447b138af7fc0719e5a107816487255736b (patch)
treefc72463364bd158b5a042ac821766f466efdfcb0 /rotord/src
parent1f8aca919df6ab2d2636cddaa30de1e388b4c09d (diff)
basic speed control for video_loader
Diffstat (limited to 'rotord/src')
-rwxr-xr-xrotord/src/libavwrapper.cpp7
-rwxr-xr-xrotord/src/libavwrapper.h9
-rwxr-xr-xrotord/src/rotor.cpp30
-rwxr-xr-xrotord/src/rotor.h13
4 files changed, 47 insertions, 12 deletions
diff --git a/rotord/src/libavwrapper.cpp b/rotord/src/libavwrapper.cpp
index 7c00b91..c21d077 100755
--- a/rotord/src/libavwrapper.cpp
+++ b/rotord/src/libavwrapper.cpp
@@ -223,6 +223,10 @@ bool libav::decoder::openUsingInitializedContainer(enum PixelFormat formatParam)
if( pCtx->time_base.num > 1000 && pCtx->time_base.den == 1 )
pCtx->time_base.den = 1000;
+ framerate=(((float)container->streams[videoStream]->r_frame_rate.num)/((float)container->streams[videoStream]->r_frame_rate.den));
+
+ //cerr<<"codecContext timebase: "<<(((float)pCtx->time_base.num)/((float)pCtx->time_base.den))<<" videostream framerate: "<<(((float)container->streams[videoStream]->r_frame_rate.num)/((float)container->streams[videoStream]->r_frame_rate.den))<<endl;
+
//cerr<<"stream frame rate:"<<container->streams[videoStream]->r_frame_rate.num<<"/"<<container->streams[videoStream]->r_frame_rate.den<<endl;
//cerr<<"video duration: "<<container->duration<<endl;
@@ -240,8 +244,7 @@ bool libav::decoder::openUsingInitializedContainer(enum PixelFormat formatParam)
if (numFrames<1){
//some codecs don't keep this info in the header
- float fr=((float)container->streams[videoStream]->r_frame_rate.num)/container->streams[videoStream]->r_frame_rate.den;
- numFrames = (int)(( container->duration / (double)AV_TIME_BASE ) * fr );
+ numFrames = (int)(( container->duration / (double)AV_TIME_BASE ) * framerate );
//this approach still doesn't seem to give quite the right answer- comes out a little too big
//could alternatively just redefine the length if the reader fails
}
diff --git a/rotord/src/libavwrapper.h b/rotord/src/libavwrapper.h
index 4c5cb02..ebe47c1 100755
--- a/rotord/src/libavwrapper.h
+++ b/rotord/src/libavwrapper.h
@@ -29,6 +29,10 @@
//http://blog.tomaka17.com/2012/03/libavcodeclibavformat-tutorial/
//great to use c++11 features
+
+//http://dranger.com/ffmpeg/
+//the mnost up to date tutorial?
+
#ifndef UINT64_C
#define UINT64_C(c) (c ## ULL)
#endif
@@ -103,6 +107,7 @@ namespace libav {
int getNumberOfFrames() const;
int getWidth() const;
int getHeight() const;
+ float getFrameRate() const{return framerate;};
int getNumberOfChannels() const;
bool readNextFrame(int targetFrameIndex = 0);
bool readNextFrameWithPacket(int targetFrameIndex, AVPacket& packet, AVFrame* pYuv);
@@ -116,6 +121,7 @@ namespace libav {
int videoStream;
int previousFrameIndex;
bool isOpen;
+
bool open(std::string& fileName, enum PixelFormat formatParam = PIX_FMT_RGB24);
bool open(char* fileName, enum PixelFormat formatParam = PIX_FMT_RGB24);
@@ -138,6 +144,9 @@ namespace libav {
size_t numBytes;
int numFrames;
int sc; // number of color channels
+ float framerate;
+ //NB representing framerate as a float implies that
+ //ABOVE ~93 HOURS AT 25FPS the calculations will be inaccurate
};
diff --git a/rotord/src/rotor.cpp b/rotord/src/rotor.cpp
index f96fbc3..c7e7bc7 100755
--- a/rotord/src/rotor.cpp
+++ b/rotord/src/rotor.cpp
@@ -282,7 +282,7 @@ bool Video_loader::load(const string &_filename){
string uri="file://"+_filename;
isLoaded=player.open(uri);
if (isLoaded){
- logger.information("Video_loader loaded "+filename+": "+ofToString(player.getNumberOfFrames())+" frames, "+ofToString(player.getWidth())+"x"+ofToString(player.getHeight()));
+ logger.information("Video_loader loaded "+filename+": "+ofToString(player.getNumberOfFrames())+" frames, "+ofToString(player.getFrameRate())+" fps, "+ofToString(player.getWidth())+"x"+ofToString(player.getHeight()));
return true;
}
@@ -293,16 +293,26 @@ bool Video_loader::load(const string &_filename){
Image* Video_loader::output(const Frame_spec &frame){
if (isLoaded){
- int wanted=(((int) ((frame.time*frame.framerate)+0.5))%(player.getNumberOfFrames()-1))+1; //+1 is necessary because 1st frame in a video is number 1?
+ //this approach is running into the inability to seek when requesting playback speed > 1.
+ //need to cache frames so as to avoid asking for a frame other than the next one.
+ //need an algorithm to find the previous keyframe and seek forward
- if (!player.fetchFrame(frame.w,frame.h,wanted)) { //seek fail
- Logger& logger = Logger::get("Rotor");
- logger.error("Video_loader failed to seek frame "+ofToString(wanted)+" of "+filename);
-
- if (image.w>0) return &image; //just return the previous frame if possible
- else return nullptr;
- };
- image.setup_fromRGB(frame.w,frame.h,player.pFrameRGB->data[0],player.pFrameRGB->linesize[0]-(frame.w*3));
+ float clipframerate=(framerate==0.0f?player.getFrameRate():framerate);
+
+ float clipspeed=(clipframerate/frame.framerate)*speed;
+
+ int wanted=(((int) ((frame.time*frame.framerate*clipspeed)+0.5))%(player.getNumberOfFrames()-1))+1; //+1 is necessary because 1st frame in a video is number 1?
+ if (wanted!=lastframe){
+ if (!player.fetchFrame(frame.w,frame.h,wanted)) { //seek fail
+ Logger& logger = Logger::get("Rotor");
+ logger.error("Video_loader failed to seek frame "+ofToString(wanted)+" of "+filename);
+
+ if (image.w>0) return &image; //just return the previous frame if possible
+ else return nullptr;
+ }
+ image.setup_fromRGB(frame.w,frame.h,player.pFrameRGB->data[0],player.pFrameRGB->linesize[0]-(frame.w*3));
+ lastframe=wanted;
+ }
return &image;
}
return nullptr;
diff --git a/rotord/src/rotor.h b/rotord/src/rotor.h
index 85e7ac4..8e37b51 100755
--- a/rotord/src/rotor.h
+++ b/rotord/src/rotor.h
@@ -1037,6 +1037,8 @@ namespace Rotor {
private:
Image *image; //is an image generator
};
+#define VIDEOFRAMES_still 1
+#define VIDEOFRAMES_blend 2
class Video_loader: public Image_node {
public:
Video_loader(){};
@@ -1044,9 +1046,16 @@ namespace Rotor {
base_settings(settings);
isLoaded=false;
filename=find_setting(settings,"filename","");
+ speed=find_setting(settings,"speed",1.0f);
+ framerate=find_setting(settings,"framerate",0.0f);
+ //0.0f signifies to use the internal framerate
if (filename!="") {
load(find_setting(settings,"media_path","")+filename);
}
+ string frame_op=find_setting(settings,"mode","still");
+ if (frame_op=="still") mode=VIDEOFRAMES_still;
+ if (frame_op=="blend") mode=VIDEOFRAMES_blend;
+ lastframe=0;
};
~Video_loader(){};
bool load(const string &filename);
@@ -1057,6 +1066,10 @@ namespace Rotor {
libav::decoder player;
Image image;
string filename;
+ float speed;
+ float framerate;
+ int mode;
+ int lastframe;
};
/*
class CVideo_loader: public Image_node {