2
#include "FFmpegDecoder.hpp"
5
#include <osgDB/FileNameUtils>
18
FFmpegDecoder::FFmpegDecoder() :
23
m_audio_decoder(m_audio_queue, m_clocks),
24
m_video_decoder(m_video_queue, m_clocks),
33
FFmpegDecoder::~FFmpegDecoder()
39
bool FFmpegDecoder::open(const std::string & filename)
44
AVFormatContext * p_format_context = 0;
46
if (filename.compare(0, 5, "/dev/")==0)
48
avdevice_register_all();
50
osg::notify(osg::NOTICE)<<"Attempting to stream "<<filename<<std::endl;
52
AVFormatParameters formatParams;
53
memset(&formatParams, 0, sizeof(AVFormatParameters));
54
AVInputFormat *iformat;
56
formatParams.channel = 0;
57
formatParams.standard = 0;
59
formatParams.width = 320;
60
formatParams.height = 240;
62
formatParams.width = 640;
63
formatParams.height = 480;
65
formatParams.time_base.num = 1;
66
formatParams.time_base.den = 30;
68
std::string format = "video4linux2";
69
iformat = av_find_input_format(format.c_str());
73
osg::notify(osg::NOTICE)<<"Found input format: "<<format<<std::endl;
77
osg::notify(osg::NOTICE)<<"Failed to find input format: "<<format<<std::endl;
80
int error = av_open_input_file(&p_format_context, filename.c_str(), iformat, 0, &formatParams);
83
std::string error_str;
86
//case AVERROR_UNKNOWN: error_str = "AVERROR_UNKNOWN"; break; // same value as AVERROR_INVALIDDATA
87
case AVERROR_IO: error_str = "AVERROR_IO"; break;
88
case AVERROR_NUMEXPECTED: error_str = "AVERROR_NUMEXPECTED"; break;
89
case AVERROR_INVALIDDATA: error_str = "AVERROR_INVALIDDATA"; break;
90
case AVERROR_NOMEM: error_str = "AVERROR_NOMEM"; break;
91
case AVERROR_NOFMT: error_str = "AVERROR_NOFMT"; break;
92
case AVERROR_NOTSUPP: error_str = "AVERROR_NOTSUPP"; break;
93
case AVERROR_NOENT: error_str = "AVERROR_NOENT"; break;
94
case AVERROR_PATCHWELCOME: error_str = "AVERROR_PATCHWELCOME"; break;
95
default: error_str = "Unknown error"; break;
98
throw std::runtime_error("av_open_input_file() failed : " + error_str);
103
if (av_open_input_file(&p_format_context, filename.c_str(), 0, 0, 0) !=0 )
104
throw std::runtime_error("av_open_input_file() failed");
107
m_format_context.reset(p_format_context);
109
// Retrieve stream info
110
if (av_find_stream_info(p_format_context) < 0)
111
throw std::runtime_error("av_find_stream_info() failed");
113
m_duration = double(m_format_context->duration) / AV_TIME_BASE;
114
m_start = double(m_format_context->start_time) / AV_TIME_BASE;
116
// TODO move this elsewhere
117
m_clocks.reset(m_start);
119
// Dump info to stderr
120
dump_format(p_format_context, 0, filename.c_str(), false);
122
// Find and open the first video and audio streams (note that audio stream is optional and only opened if possible)
127
m_video_decoder.open(m_video_stream);
131
m_audio_decoder.open(m_audio_stream);
134
catch (const std::runtime_error & error)
136
osg::notify(osg::WARN) << "FFmpegImageStream::open audio failed, audio stream will be disabled: " << error.what() << std::endl;
140
catch (const std::runtime_error & error)
142
osg::notify(osg::WARN) << "FFmpegImageStream::open : " << error.what() << std::endl;
151
void FFmpegDecoder::close(bool waitForThreadToExit)
156
m_audio_decoder.close(waitForThreadToExit);
157
m_video_decoder.close(waitForThreadToExit);
162
bool FFmpegDecoder::readNextPacket()
167
return readNextPacketNormal();
173
return readNextPacketEndOfStream();
176
return readNextPacketRewinding();
179
return readNextPacketSeeking();
189
void FFmpegDecoder::rewind()
191
m_pending_packet.clear();
195
rewindButDontFlushQueues();
198
void FFmpegDecoder::seek(double time)
200
m_pending_packet.clear();
204
seekButDontFlushQueues(time);
207
void FFmpegDecoder::pause()
209
m_pending_packet.clear();
216
void FFmpegDecoder::findAudioStream()
218
for (unsigned int i = 0; i < m_format_context->nb_streams; ++i)
220
if (m_format_context->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO)
222
m_audio_stream = m_format_context->streams[i];
229
m_audio_index = std::numeric_limits<unsigned int>::max();
234
void FFmpegDecoder::findVideoStream()
236
for (unsigned int i = 0; i < m_format_context->nb_streams; ++i)
238
if (m_format_context->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO)
240
m_video_stream = m_format_context->streams[i];
246
throw std::runtime_error("could not find a video stream");
251
inline void FFmpegDecoder::flushAudioQueue()
253
FFmpegPacketClear pc;
254
m_audio_queue.flush(pc);
259
inline void FFmpegDecoder::flushVideoQueue()
261
FFmpegPacketClear pc;
262
m_video_queue.flush(pc);
267
bool FFmpegDecoder::readNextPacketNormal()
271
if (! m_pending_packet)
273
bool end_of_stream = false;
275
// Read the next frame packet
276
if (av_read_frame(m_format_context.get(), &packet) < 0)
278
if (url_ferror(m_format_context->pb) == 0)
279
end_of_stream = true;
281
throw std::runtime_error("av_read_frame() failed");
286
// If we reach the end of the stream, change the decoder state
289
m_clocks.reset(m_start);
290
rewindButDontFlushQueues();
293
m_state = END_OF_STREAM;
299
// Make the packet data available beyond av_read_frame() logical scope.
300
if (av_dup_packet(&packet) < 0)
301
throw std::runtime_error("av_dup_packet() failed");
303
m_pending_packet = FFmpegPacket(packet);
308
if (m_pending_packet.type == FFmpegPacket::PACKET_DATA)
310
if (m_pending_packet.packet.stream_index == m_audio_index)
312
if (m_audio_queue.timedPush(m_pending_packet, 10)) {
313
m_pending_packet.release();
317
else if (m_pending_packet.packet.stream_index == m_video_index)
319
if (m_video_queue.timedPush(m_pending_packet, 10)) {
320
m_pending_packet.release();
326
m_pending_packet.clear();
336
bool FFmpegDecoder::readNextPacketEndOfStream()
338
const FFmpegPacket packet(FFmpegPacket::PACKET_END_OF_STREAM);
340
m_audio_queue.timedPush(packet, 10);
341
m_video_queue.timedPush(packet, 10);
348
bool FFmpegDecoder::readNextPacketRewinding()
350
const FFmpegPacket packet(FFmpegPacket::PACKET_FLUSH);
352
if (m_audio_queue.timedPush(packet, 10) && m_video_queue.timedPush(packet, 10))
360
void FFmpegDecoder::rewindButDontFlushQueues()
362
const AVRational AvTimeBaseQ = { 1, AV_TIME_BASE }; // = AV_TIME_BASE_Q
364
const int64_t pos = int64_t(m_clocks.getStartTime() * double(AV_TIME_BASE));
365
const int64_t seek_target = av_rescale_q(pos, AvTimeBaseQ, m_video_stream->time_base);
367
if (av_seek_frame(m_format_context.get(), m_video_index, seek_target, 0/*AVSEEK_FLAG_BYTE |*/ /*AVSEEK_FLAG_BACKWARD*/) < 0)
368
throw std::runtime_error("av_seek_frame failed()");
374
bool FFmpegDecoder::readNextPacketSeeking()
376
const FFmpegPacket packet(FFmpegPacket::PACKET_FLUSH);
378
if (m_audio_queue.timedPush(packet, 10) && m_video_queue.timedPush(packet, 10))
384
void FFmpegDecoder::seekButDontFlushQueues(double time)
386
const AVRational AvTimeBaseQ = { 1, AV_TIME_BASE }; // = AV_TIME_BASE_Q
388
const int64_t pos = int64_t(m_clocks.getStartTime()+time * double(AV_TIME_BASE));
389
const int64_t seek_target = av_rescale_q(pos, AvTimeBaseQ, m_video_stream->time_base);
391
m_clocks.setSeekTime(time);
393
if (av_seek_frame(m_format_context.get(), m_video_index, seek_target, 0/*AVSEEK_FLAG_BYTE |*/ /*AVSEEK_FLAG_BACKWARD*/) < 0)
394
throw std::runtime_error("av_seek_frame failed()");
402
} // namespace osgFFmpeg