+ auto packet = create_packet();
+
+ auto ret = av_read_frame(format_context_.get(), packet.get()); // packet is only valid until next call of av_read_frame. Use av_dup_packet to extend its life.
+
+ if(is_eof(ret))
+ {
+ frame_number_ = 0;
+
+ if(loop_)
+ {
+ queued_seek(start_);
+ graph_->set_tag(diagnostics::tag_severity::INFO, "seek");
+ CASPAR_LOG(trace) << print() << " Looping.";
+ }
+ else
+ {
+ // Needed by some decoders to decode remaining frames based on last packet.
+ auto flush_packet = create_packet();
+ flush_packet->data = nullptr;
+ flush_packet->size = 0;
+ flush_packet->pos = -1;
+
+ buffer_.push(flush_packet);
+
+ executor_.stop();
+ }
+ }
+ else
+ {
+ THROW_ON_ERROR(ret, "av_read_frame", print());
+
+ if(packet->stream_index == default_stream_index_)
+ ++frame_number_;
+
+ THROW_ON_ERROR2(av_dup_packet(packet.get()), print());
+
+ // Make sure that the packet is correctly deallocated even if size and data is modified during decoding.
+ auto size = packet->size;
+ auto data = packet->data;
+
+ packet = spl::shared_ptr<AVPacket>(packet.get(), [packet, size, data](AVPacket*)
+ {
+ packet->size = size;
+ packet->data = data;
+ });
+
+ buffer_.try_push(packet);
+ buffer_size_ += packet->size;
+
+ graph_->set_value("buffer-size", (static_cast<double>(buffer_size_)+0.001)/MAX_BUFFER_SIZE);
+ graph_->set_value("buffer-count", (static_cast<double>(buffer_.size()+0.001)/MAX_BUFFER_COUNT));
+ }
+
+ tick();