\r
std::vector<std::shared_ptr<std::vector<int16_t>>> poll()\r
{\r
+ std::vector<std::shared_ptr<std::vector<int16_t>>> result;\r
+\r
+ if(packets_.empty())\r
+ return result;\r
+\r
if(!codec_context_)\r
return empty_poll();\r
+ \r
+ auto packet = packets_.front();\r
\r
- std::vector<std::shared_ptr<std::vector<int16_t>>> result;\r
-\r
- while(!packets_.empty() && result.empty())\r
- { \r
- auto packet = packets_.front();\r
-\r
- if(packet) \r
- {\r
- result.push_back(decode(*packet));\r
- if(packet->size == 0) \r
- packets_.pop();\r
- }\r
- else \r
- { \r
- avcodec_flush_buffers(codec_context_.get());\r
- result.push_back(nullptr);\r
+ if(packet) \r
+ {\r
+ result.push_back(decode(*packet));\r
+ if(packet->size == 0) \r
packets_.pop();\r
- } \r
}\r
+ else \r
+ { \r
+ avcodec_flush_buffers(codec_context_.get());\r
+ result.push_back(nullptr);\r
+ packets_.pop();\r
+ } \r
\r
return result;\r
}\r
\r
std::vector<std::shared_ptr<std::vector<int16_t>>> empty_poll()\r
{\r
- if(packets_.empty())\r
- return std::vector<std::shared_ptr<std::vector<int16_t>>>();\r
- \r
auto packet = packets_.front();\r
packets_.pop();\r
\r
\r
bool ready() const\r
{\r
- return !codec_context_ || packets_.size() > 2;\r
+ return !packets_.empty();\r
}\r
};\r
\r
{\r
graph_->add_guide("frame-time", 0.5);\r
graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
- graph_->set_color("video-time", diagnostics::color(1.0f, 1.0f, 0.0f));\r
- graph_->set_color("audio-time", diagnostics::color(0.2f, 1.0f, 0.2f));\r
graph_->set_color("underflow", diagnostics::color(0.6f, 0.3f, 0.9f)); \r
\r
- for(int n = 0; n < 32 && muxer_.size() < 2; ++n)\r
+ for(int n = 0; n < 32 && muxer_.empty(); ++n)\r
decode_frame(0);\r
}\r
\r
\r
for(int n = 0; n < 64 && muxer_.empty(); ++n)\r
decode_frame(hints);\r
+ \r
+ graph_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()*format_desc_.fps*0.5));\r
\r
if(!muxer_.empty())\r
frame = last_frame_ = muxer_.pop(); \r
}\r
}\r
\r
- graph_->update_value("frame-time", static_cast<float>(frame_timer_.elapsed()*format_desc_.fps*0.5));\r
- \r
return frame;\r
}\r
\r
tbb::parallel_invoke(\r
[&]\r
{\r
- if(!muxer_.video_ready())\r
- {\r
- video_timer_.restart();\r
+ if(muxer_.video_ready())\r
+ return;\r
\r
- auto video_frames = video_decoder_.poll();\r
- BOOST_FOREACH(auto& video, video_frames) \r
- muxer_.push(video, hints); \r
-\r
- graph_->update_value("video-time", static_cast<float>(video_timer_.elapsed()*format_desc_.fps*0.5));\r
- }\r
+ auto video_frames = video_decoder_.poll();\r
+ BOOST_FOREACH(auto& video, video_frames) \r
+ muxer_.push(video, hints); \r
},\r
[&]\r
{\r
- if(!muxer_.audio_ready())\r
- {\r
- audio_timer_.restart();\r
+ if(muxer_.audio_ready())\r
+ return;\r
\r
- auto audio_samples = audio_decoder_.poll();\r
- BOOST_FOREACH(auto& audio, audio_samples)\r
- muxer_.push(audio); \r
-\r
- graph_->update_value("audio-time", static_cast<float>(audio_timer_.elapsed()*format_desc_.fps*0.5));\r
- }\r
+ auto audio_samples = audio_decoder_.poll();\r
+ BOOST_FOREACH(auto& audio, audio_samples)\r
+ muxer_.push(audio); \r
});\r
\r
muxer_.commit();\r
\r
return samples;\r
}\r
-\r
+ \r
bool video_ready() const\r
- {\r
- return video_frames() > 1 && video_streams_.size() >= audio_streams_.size();\r
+ { \r
+ return video_streams_.size() >= audio_streams_.size() && video_ready2();\r
}\r
\r
bool audio_ready() const\r
{\r
- return audio_chunks() > 1 && audio_streams_.size() >= video_streams_.size();\r
+ return audio_streams_.size() >= video_streams_.size() && audio_ready2();\r
}\r
\r
- size_t video_frames() const\r
- {\r
- return video_streams_.back().size();\r
+ bool video_ready2() const\r
+ { \r
+ switch(display_mode_)\r
+ {\r
+ case display_mode::deinterlace_bob_reinterlace: \r
+ case display_mode::interlace: \r
+ return video_streams_.front().size() >= 2;\r
+ default: \r
+ return !video_streams_.front().empty();\r
+ }\r
}\r
-\r
- size_t audio_chunks() const\r
+ \r
+ bool audio_ready2() const\r
{\r
- return audio_streams_.back().size() / format_desc_.audio_samples_per_frame;\r
+ switch(display_mode_)\r
+ {\r
+ case display_mode::duplicate: \r
+ return audio_streams_.front().size()/2 >= format_desc_.audio_samples_per_frame;\r
+ default: \r
+ return audio_streams_.front().size() >= format_desc_.audio_samples_per_frame;\r
+ }\r
}\r
- \r
+ \r
void commit()\r
{\r
- if(video_streams_.size() > 1 && audio_streams_.size() > 1 && !ready())\r
+ if(video_streams_.size() > 1 && audio_streams_.size() > 1 && (!video_ready2() || !audio_ready2()))\r
{\r
if(!video_streams_.front().empty() || !audio_streams_.front().empty())\r
CASPAR_LOG(debug) << "Truncating: " << video_streams_.front().size() << L" video-frames, " << audio_streams_.front().size() << L" audio-samples.";\r
audio_streams_.pop_front();\r
}\r
\r
- if(!ready())\r
+ if(!video_ready2() || !audio_ready2())\r
return;\r
\r
switch(display_mode_)\r
default: BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("invalid display-mode"));\r
}\r
}\r
-\r
- bool ready()\r
- {\r
- switch(display_mode_)\r
- {\r
- case display_mode::deinterlace_bob:\r
- case display_mode::deinterlace:\r
- case display_mode::simple: return !video_streams_.front().empty() && audio_streams_.front().size() >= format_desc_.audio_samples_per_frame;\r
- case display_mode::duplicate: return !video_streams_.front().empty() && audio_streams_.front().size()/2 >= format_desc_.audio_samples_per_frame;\r
- case display_mode::half: \r
- case display_mode::deinterlace_bob_reinterlace: \r
- case display_mode::interlace: return video_streams_.front().size() >= 2 && audio_streams_.front().size() >= format_desc_.audio_samples_per_frame;\r
- default: return false;\r
- }\r
- }\r
-\r
+ \r
void simple(std::deque<safe_ptr<basic_frame>>& dest)\r
{ \r
auto frame1 = pop_video();\r
\r
std::vector<std::shared_ptr<AVFrame>> poll()\r
{ \r
+ std::vector<std::shared_ptr<AVFrame>> result;\r
+\r
+ if(packets_.empty())\r
+ return result;\r
+\r
if(!codec_context_)\r
return empty_poll();\r
\r
- std::vector<std::shared_ptr<AVFrame>> result;\r
-\r
- while(!packets_.empty() && result.empty())\r
- {\r
- auto packet = packets_.front();\r
+ auto packet = packets_.front();\r
\r
- if(packet)\r
- {\r
- auto frame = decode(*packet);\r
+ if(packet)\r
+ { \r
+ BOOST_FOREACH(auto& frame, decode(*packet))\r
boost::range::push_back(result, filter_.execute(frame));\r
- if(packet->size == 0)\r
- packets_.pop();\r
- }\r
- else\r
+\r
+ if(packet->size == 0)\r
+ packets_.pop();\r
+ }\r
+ else\r
+ {\r
+ if(codec_context_->codec->capabilities & CODEC_CAP_DELAY)\r
{\r
- if(codec_context_->codec->capabilities & CODEC_CAP_DELAY)\r
- {\r
- AVPacket pkt;\r
- av_init_packet(&pkt);\r
- pkt.data = nullptr;\r
- pkt.size = 0;\r
- auto frame = decode(pkt);\r
+ AVPacket pkt;\r
+ av_init_packet(&pkt);\r
+ pkt.data = nullptr;\r
+ pkt.size = 0;\r
+\r
+ BOOST_FOREACH(auto& frame, decode(pkt))\r
boost::range::push_back(result, filter_.execute(frame)); \r
- }\r
-\r
- if(result.empty())\r
- { \r
- packets_.pop();\r
- avcodec_flush_buffers(codec_context_.get());\r
- result.push_back(nullptr);\r
- }\r
+ }\r
+\r
+ if(result.empty())\r
+ { \r
+ packets_.pop();\r
+ avcodec_flush_buffers(codec_context_.get());\r
+ result.push_back(nullptr);\r
}\r
}\r
\r
}\r
\r
std::vector<std::shared_ptr<AVFrame>> empty_poll()\r
- { \r
- if(packets_.empty())\r
- return std::vector<std::shared_ptr<AVFrame>>();\r
- \r
+ { \r
auto packet = packets_.front();\r
packets_.pop();\r
\r
return boost::assign::list_of(frame); \r
}\r
\r
- std::shared_ptr<AVFrame> decode(AVPacket& pkt)\r
+ std::vector<std::shared_ptr<AVFrame>> decode(AVPacket& pkt)\r
{\r
std::shared_ptr<AVFrame> decoded_frame(avcodec_alloc_frame(), av_free);\r
\r
pkt.data = nullptr;\r
pkt.size = 0;\r
\r
- if(frame_finished != 0) \r
- {\r
- if(decoded_frame->repeat_pict != 0)\r
- CASPAR_LOG(warning) << "video_decoder: repeat_pict not implemented.";\r
- return decoded_frame;\r
- }\r
+ if(frame_finished == 0) \r
+ return std::vector<std::shared_ptr<AVFrame>>();\r
\r
- return nullptr;\r
+ if(decoded_frame->repeat_pict % 2 > 0)\r
+ CASPAR_LOG(warning) << "[video_decoder]: Field repeat_pict not implemented.";\r
+ \r
+ return std::vector<std::shared_ptr<AVFrame>>(1 + decoded_frame->repeat_pict/2, decoded_frame);\r
}\r
\r
bool ready() const\r
{\r
- return !codec_context_ || packets_.size() > 2;\r
+ return !packets_.empty();\r
}\r
\r
double fps() const\r