diff options
| author | Tim Redfern <tim@herge.(none)> | 2013-08-08 13:32:46 +0100 |
|---|---|---|
| committer | Tim Redfern <tim@herge.(none)> | 2013-08-08 13:32:46 +0100 |
| commit | a2254447b138af7fc0719e5a107816487255736b (patch) | |
| tree | fc72463364bd158b5a042ac821766f466efdfcb0 /rotord/src | |
| parent | 1f8aca919df6ab2d2636cddaa30de1e388b4c09d (diff) | |
basic speed control for video_loader
Diffstat (limited to 'rotord/src')
| -rwxr-xr-x | rotord/src/libavwrapper.cpp | 7 | ||||
| -rwxr-xr-x | rotord/src/libavwrapper.h | 9 | ||||
| -rwxr-xr-x | rotord/src/rotor.cpp | 30 | ||||
| -rwxr-xr-x | rotord/src/rotor.h | 13 |
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 ℑ //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 ℑ //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 ℑ } 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 { |
