From Rafa Gaitan, "Current ffmpeg plugin didn't support pause and seek, I have added this

functionality and I also modified osgmovie example to support "seek"."

Note from Robert Osfield, changes osgmovie to use '>' for the seek as '+' was already used in a separate submission that had been merged.
This commit is contained in:
Robert Osfield
2009-11-20 14:31:11 +00:00
parent 733431004a
commit 3ef770a9ff
5 changed files with 102 additions and 3 deletions

View File

@@ -118,6 +118,7 @@ protected:
bool _trackMouse;
ImageStreamList _imageStreamList;
unsigned int _seekIncr;
};
@@ -237,6 +238,23 @@ bool MovieEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIAction
}
return true;
}
else if (ea.getKey()=='>')
{
for(ImageStreamList::iterator itr=_imageStreamList.begin();
itr!=_imageStreamList.end();
++itr)
{
std::cout<<"Seeking"<<std::endl;
if(_seekIncr > 3) _seekIncr = 0;
double length = (*itr)->getLength();
double t_pos = (length/4.0f)*_seekIncr;
//(*itr)->rewind();
(*itr)->seek(t_pos);
(*itr)->play();
_seekIncr++;
}
return true;
}
else if (ea.getKey()=='L')
{
for(ImageStreamList::iterator itr=_imageStreamList.begin();
@@ -309,6 +327,7 @@ void MovieEventHandler::getUsage(osg::ApplicationUsage& usage) const
usage.addKeyboardMouseBinding("+","Increase speed of movie");
usage.addKeyboardMouseBinding("-","Decrease speed of movie");
usage.addKeyboardMouseBinding("o","Display frame rate of movie");
usage.addKeyboardMouseBinding(">","Advance the movie using seek");
}

View File

@@ -166,12 +166,18 @@ bool FFmpegDecoder::readNextPacket()
case NORMAL:
return readNextPacketNormal();
case PAUSE:
return false;
case END_OF_STREAM:
return readNextPacketEndOfStream();
case REWINDING:
return readNextPacketRewinding();
case SEEKING:
return readNextPacketSeeking();
default:
assert(false);
return false;
@@ -189,8 +195,32 @@ void FFmpegDecoder::rewind()
rewindButDontFlushQueues();
}
void FFmpegDecoder::seek(double time)
{
m_pending_packet.clear();
flushAudioQueue();
flushVideoQueue();
seekButDontFlushQueues(time);
}
void FFmpegDecoder::pause()
{
m_pending_packet.clear();
flushAudioQueue();
flushVideoQueue();
m_state = PAUSE;
}
void FFmpegDecoder::resume()
{
m_pending_packet.clear();
flushAudioQueue();
flushVideoQueue();
m_state = NORMAL;
}
void FFmpegDecoder::findAudioStream()
{
@@ -346,6 +376,29 @@ void FFmpegDecoder::rewindButDontFlushQueues()
m_state = REWINDING;
}
bool FFmpegDecoder::readNextPacketSeeking()
{
const FFmpegPacket packet(FFmpegPacket::PACKET_FLUSH);
if (m_audio_queue.timedPush(packet, 10) && m_video_queue.timedPush(packet, 10))
m_state = NORMAL;
return false;
}
void FFmpegDecoder::seekButDontFlushQueues(double time)
{
const AVRational AvTimeBaseQ = { 1, AV_TIME_BASE }; // = AV_TIME_BASE_Q
const int64_t pos = int64_t(m_clocks.getStartTime()+time * double(AV_TIME_BASE));
const int64_t seek_target = av_rescale_q(pos, AvTimeBaseQ, m_video_stream->time_base);
if (av_seek_frame(m_format_context.get(), m_video_index, seek_target, 0/*AVSEEK_FLAG_BYTE |*/ /*AVSEEK_FLAG_BACKWARD*/) < 0)
throw std::runtime_error("av_seek_frame failed()");
m_state = SEEKING;
}
} // namespace osgFFmpeg

View File

@@ -68,6 +68,9 @@ public:
bool readNextPacket();
void rewind();
void seek(double time);
void pause();
void resume();
void loop(bool loop);
bool loop() const;
@@ -84,8 +87,10 @@ protected:
enum State
{
NORMAL,
PAUSE,
END_OF_STREAM,
REWINDING
REWINDING,
SEEKING
};
typedef BoundedMessageQueue<FFmpegPacket> PacketQueue;
@@ -97,7 +102,10 @@ protected:
bool readNextPacketNormal();
bool readNextPacketEndOfStream();
bool readNextPacketRewinding();
bool readNextPacketSeeking();
bool readNextPacketPause();
void rewindButDontFlushQueues();
void seekButDontFlushQueues(double time);
FormatContextPtr m_format_context;
AVStream * m_audio_stream;

View File

@@ -130,6 +130,11 @@ void FFmpegImageStream::rewind()
m_commands->push(CMD_REWIND);
}
void FFmpegImageStream::seek(double time) {
m_seek_time = time;
m_commands->push(CMD_SEEK);
}
void FFmpegImageStream::quit(bool waitForThreadToExit)
@@ -234,6 +239,10 @@ bool FFmpegImageStream::handleCommand(const Command cmd)
cmdRewind();
return true;
case CMD_SEEK:
cmdSeek(m_seek_time);
return true;
case CMD_STOP:
return false;
@@ -254,6 +263,8 @@ void FFmpegImageStream::cmdPlay()
if (! m_decoder->video_decoder().isRunning())
m_decoder->video_decoder().start();
m_decoder->resume();
}
_status = PLAYING;
@@ -265,7 +276,7 @@ void FFmpegImageStream::cmdPause()
{
if (_status == PLAYING)
{
m_decoder->pause();
}
_status = PAUSED;
@@ -278,6 +289,10 @@ void FFmpegImageStream::cmdRewind()
m_decoder->rewind();
}
void FFmpegImageStream::cmdSeek(double time)
{
m_decoder->seek(time);
}
void FFmpegImageStream::publishNewFrame(const FFmpegDecoderVideo &, void * user_data)

View File

@@ -30,6 +30,7 @@ namespace osgFFmpeg
virtual void play();
virtual void pause();
virtual void rewind();
virtual void seek(double time);
virtual void quit(bool waitForThreadToExit = true);
virtual double getLength() const;
@@ -44,7 +45,8 @@ namespace osgFFmpeg
CMD_PLAY,
CMD_PAUSE,
CMD_STOP,
CMD_REWIND
CMD_REWIND,
CMD_SEEK
};
typedef MessageQueue<Command> CommandQueue;
@@ -60,6 +62,7 @@ namespace osgFFmpeg
void cmdPlay();
void cmdPause();
void cmdRewind();
void cmdSeek(double time);
static void publishNewFrame(const FFmpegDecoderVideo &, void * user_data);
@@ -69,6 +72,7 @@ namespace osgFFmpeg
Mutex m_mutex;
Condition m_frame_published_cond;
bool m_frame_published_flag;
double m_seek_time;
};
}