\r
void load(const safe_ptr<frame_producer>& producer, bool preview, int auto_play_delta)\r
{ \r
- background_ = producer;\r
- auto_play_delta_ = auto_play_delta;\r
+ background_ = producer;\r
+\r
+ if(auto_play_delta > -1)\r
+ {\r
+ if(producer->nb_frames() > 0)\r
+ auto_play_delta_ = auto_play_delta;\r
+ else\r
+ CASPAR_LOG(warning) << producer->print() << L" Does not support auto-play.";\r
+ }\r
\r
if(preview) // Play the first frame and pause.\r
{ \r
if(is_paused_)\r
return foreground_->last_frame();\r
\r
+ const auto frames_left = foreground_->nb_frames() - (++frame_number_) - auto_play_delta_;\r
+\r
auto frame = receive_and_follow(foreground_);\r
if(frame == core::basic_frame::late())\r
return foreground_->last_frame();\r
- \r
- ++frame_number_;\r
-\r
- if(auto_play_delta_ >= 0)\r
+ \r
+ if(auto_play_delta_ == 0)\r
{\r
- const auto frames_left = foreground_->nb_frames() - frame_number_ - auto_play_delta_;\r
+ if(frame == core::basic_frame::eof())\r
+ {\r
+ CASPAR_ASSERT(frames_left == 0);\r
\r
+ CASPAR_LOG(info) << L"Automatically playing next clip with " << auto_play_delta_ << " frames offset.";\r
+ \r
+ play();\r
+ frame = receive();\r
+ }\r
+ }\r
+ else if(auto_play_delta_ > 0)\r
+ {\r
if(frames_left <= 0 || frame == core::basic_frame::eof())\r
{\r
- CASPAR_VERIFY(auto_play_delta_ != 0 || frame == core::basic_frame::eof())\r
+ CASPAR_VERIFY(frame != core::basic_frame::eof() && "Received early EOF. Media duration metadata incorrect.");\r
\r
CASPAR_LOG(info) << L"Automatically playing next clip with " << auto_play_delta_ << " frames offset.";\r
\r
tbb::task_group tasks_;\r
\r
int start_;\r
+ int64_t nb_frames_;\r
+ bool loop_;\r
\r
public:\r
explicit ffmpeg_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, const std::wstring& filter, bool loop, int start, int length) \r
, audio_decoder_(input_.context(), frame_factory->get_video_format_desc())\r
, muxer_(video_decoder_.fps(), format_desc_, frame_factory)\r
, start_(start)\r
+ , nb_frames_(video_decoder_.nb_frames() - start)\r
+ , loop_(loop)\r
{\r
graph_->add_guide("frame-time", 0.5);\r
graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
if(input_.eof())\r
frame = core::basic_frame::eof();\r
else\r
- graph_->add_tag("underflow"); \r
+ {\r
+ graph_->add_tag("underflow"); \r
+ ++nb_frames_;\r
+ }\r
}\r
else \r
frame = muxer_.pop(); \r
\r
virtual int64_t nb_frames() const\r
{\r
- return std::max<int64_t>(0, video_decoder_.nb_frames()-start_);//std::max(video_decoder_.nb_frames(), audio_decoder_.nb_frames());\r
+ return loop_ ? 0 : nb_frames_;\r
}\r
\r
virtual std::wstring print() const\r
{\r
executor_.stop();\r
\r
- CASPAR_LOG(info) << print() << " Stopping.";\r
+ CASPAR_LOG(debug) << print() << " Stopping.";\r
}\r
\r
void read_file()\r
{\r
seek_frame(start_, AVSEEK_FLAG_BACKWARD);\r
graph_->add_tag("seek"); \r
- //CASPAR_LOG(info) << print() << " Received EOF. Looping."; \r
+ CASPAR_LOG(trace) << print() << " Received EOF. Looping."; \r
} \r
else\r
{\r
stop();\r
- //CASPAR_LOG(info) << print() << " Received EOF. Stopping.";\r
+ CASPAR_LOG(trace) << print() << " Received EOF. Stopping.";\r
}\r
}\r
else if(errn < 0)\r
bool is_eof(int errn)\r
{\r
//if(errn == AVERROR(EIO))\r
- // CASPAR_LOG(warning) << print() << " Received EIO, assuming EOF";\r
+ // CASPAR_LOG(warning) << print() << " Received EIO, assuming EOF.";\r
+ //if(errn == AVERROR_EOF)\r
+ // CASPAR_LOG(info) << print() << " Received EOF.";\r
\r
return errn == AVERROR_EOF || errn == AVERROR(EIO); // av_read_frame doesn't always correctly return AVERROR_EOF;\r
}\r