}\r
}\r
\r
- virtual int64_t nb_frames() const\r
+ virtual int64_t nb_frames() const \r
{\r
if(loop_)\r
return 0;\r
\r
+ // This function estimates nb_frames until input has read all packets for one loop, at which point the count should be accurate.\r
+\r
int64_t nb_frames = input_.nb_frames();\r
+ if(input_.nb_loops() < 1) // input still hasn't counted all frames\r
+ {\r
+ int64_t video_nb_frames = video_decoder_.nb_frames();\r
+ int64_t audio_nb_frames = audio_decoder_.nb_frames();\r
+\r
+ nb_frames = std::max(nb_frames, std::max(video_nb_frames, audio_nb_frames));\r
+ }\r
+\r
+ // TODO: Might need to scale nb_frames av frame_muxer transformations.\r
\r
- if(nb_frames == 0)\r
- nb_frames = video_decoder_.nb_frames();\r
- \r
- if(nb_frames == 0)\r
- nb_frames = audio_decoder_.nb_frames();\r
- \r
return nb_frames + late_frames_ - start_;\r
}\r
\r
struct input::implementation : boost::noncopyable\r
{ \r
std::shared_ptr<AVFormatContext> format_context_; // Destroy this last\r
+ int default_stream_index_;\r
\r
safe_ptr<diagnostics::graph> graph_;\r
\r
\r
boost::thread thread_;\r
tbb::atomic<bool> is_running_;\r
+\r
tbb::atomic<size_t> nb_frames_;\r
- int64_t frame_number_;\r
+ tbb::atomic<size_t> nb_loops_;\r
\r
- int default_stream_index_;\r
public:\r
explicit implementation(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, int start) \r
: graph_(graph)\r
, loop_(loop)\r
, filename_(filename)\r
, start_(std::max(start, 0))\r
- , frame_number_(0)\r
{ \r
is_running_ = true;\r
- nb_frames_ = 0;\r
+ nb_frames_ = 0;\r
+ nb_loops_ = 0;\r
\r
AVFormatContext* weak_format_context_ = nullptr;\r
THROW_ON_ERROR2(avformat_open_input(&weak_format_context_, narrow(filename).c_str(), nullptr, nullptr), print());\r
return nb_frames_;\r
}\r
\r
+ size_t nb_loops() const\r
+ {\r
+ return nb_loops_;\r
+ }\r
+\r
private:\r
\r
void run()\r
\r
if(is_eof(ret)) \r
{\r
- if(nb_frames_ == 0)\r
- nb_frames_ = static_cast<size_t>(frame_number_);\r
+ ++nb_loops_;\r
\r
if(loop_)\r
{\r
{ \r
THROW_ON_ERROR(ret, print(), "av_read_frame");\r
\r
- if(read_packet->stream_index == default_stream_index_)\r
- ++frame_number_;\r
+ if(read_packet->stream_index == default_stream_index_ && nb_loops_ == 0)\r
+ ++nb_frames_;\r
\r
THROW_ON_ERROR2(av_dup_packet(read_packet.get()), print());\r
\r
bool input::try_pop(std::shared_ptr<AVPacket>& packet){return impl_->try_pop(packet);}\r
safe_ptr<AVFormatContext> input::context(){return make_safe(impl_->format_context_);}\r
size_t input::nb_frames() const {return impl_->nb_frames();}\r
+size_t input::nb_loops() const {return impl_->nb_loops();}\r
}
\ No newline at end of file