auto result = std::make_shared<core::audio_buffer>();\r
\r
if(!codec_context_)\r
- {\r
- result = empty_audio();\r
- return result;\r
- }\r
+ return empty_audio();\r
\r
std::shared_ptr<AVPacket> packet;\r
if(!input_->try_pop_audio(packet))\r
return result;\r
\r
- if(packet == flush_packet())\r
+ if(packet)\r
{\r
+ if(!packet->data && (codec_context_->codec->capabilities & CODEC_CAP_DELAY))\r
+ while(decode(*packet, *result));\r
+\r
+ while(packet->size > 0) \r
+ decode(*packet, *result);\r
+ } \r
+ else \r
avcodec_flush_buffers(codec_context_.get());\r
- return result;\r
- }\r
- \r
- if(packet == null_packet())\r
- {\r
- if(codec_context_->codec->capabilities & CODEC_CAP_DELAY)\r
- {\r
- AVPacket pkt = {0}; \r
- av_init_packet(&pkt);\r
- \r
- core::audio_buffer audio;\r
- while(decode(pkt, audio))\r
- boost::range::push_back(*result, audio);\r
- }\r
- return result;\r
- }\r
\r
- while(packet->size > 0)\r
- {\r
- core::audio_buffer audio;\r
- if(decode(*packet, audio))\r
- boost::range::push_back(*result, audio); \r
- }\r
- \r
- event_subject_ << monitor::event("file/audio/sample-rate") % codec_context_->sample_rate\r
- << monitor::event("file/audio/channels") % codec_context_->channels\r
- << monitor::event("file/audio/format") % u8(av_get_sample_fmt_name(codec_context_->sample_fmt))\r
- << monitor::event("file/audio/codec") % u8(codec_context_->codec->long_name); \r
- \r
return result;\r
}\r
\r
in, decoded_frame->nb_samples);\r
\r
auto ptr = reinterpret_cast<int32_t*>(buffer_.data());\r
- result = core::audio_buffer(ptr, ptr + channel_samples * format_desc_.audio_channels);\r
+ result.insert(result.end(), ptr, ptr + channel_samples * format_desc_.audio_channels); \r
\r
+ event_subject_ << monitor::event("file/audio/sample-rate") % codec_context_->sample_rate\r
+ << monitor::event("file/audio/channels") % codec_context_->channels\r
+ << monitor::event("file/audio/format") % u8(av_get_sample_fmt_name(codec_context_->sample_fmt))\r
+ << monitor::event("file/audio/codec") % u8(codec_context_->codec->long_name); \r
+\r
return true;\r
}\r
\r
\r
void push(const std::shared_ptr<AVPacket>& packet)\r
{\r
- if(packet->stream_index != index_ && packet != flush_packet() && packet != null_packet())\r
+ if(packet && packet->data && packet->stream_index != index_)\r
return;\r
\r
packets_.push(packet);\r
\r
THROW_ON_ERROR2(avformat_seek_file(format_context_.get(), default_stream_index_, std::numeric_limits<int64_t>::min(), fixed_target, fixed_target, 0), print()); \r
\r
- video_stream_.push(flush_packet());\r
- audio_stream_.push(flush_packet());\r
+ video_stream_.push(nullptr);\r
+ audio_stream_.push(nullptr);\r
}\r
\r
bool full() const\r
\r
if(is_eof(ret)) \r
{\r
- video_stream_.push(null_packet());\r
- audio_stream_.push(null_packet());\r
+ std::shared_ptr<AVPacket> eof_packet(new AVPacket());\r
+ memset(eof_packet.get(), 0, sizeof(AVPacket));\r
+ av_init_packet(eof_packet.get());\r
+\r
+ video_stream_.push(eof_packet);\r
+ audio_stream_.push(eof_packet);\r
\r
if(loop_)\r
{\r
\r
while(is_running_)\r
{\r
-\r
try\r
{\r
boost::this_thread::sleep(boost::posix_time::milliseconds(1));\r
\r
namespace caspar { namespace ffmpeg {\r
\r
-std::shared_ptr<core::audio_buffer> flush_audio()\r
-{\r
- static std::shared_ptr<core::audio_buffer> audio(new core::audio_buffer());\r
- return audio;\r
-}\r
-\r
std::shared_ptr<core::audio_buffer> empty_audio()\r
{\r
static std::shared_ptr<core::audio_buffer> audio(new core::audio_buffer());\r
return audio;\r
}\r
\r
-std::shared_ptr<AVFrame> flush_video()\r
-{\r
- static std::shared_ptr<AVFrame> video(avcodec_alloc_frame(), av_free);\r
- return video;\r
-}\r
-\r
std::shared_ptr<AVFrame> empty_video()\r
{\r
static std::shared_ptr<AVFrame> video(avcodec_alloc_frame(), av_free);\r
return video;\r
}\r
\r
-spl::shared_ptr<AVPacket> flush_packet()\r
-{\r
- static spl::shared_ptr<AVPacket> pkt(new AVPacket());\r
- return pkt;\r
-}\r
-\r
-spl::shared_ptr<AVPacket> null_packet()\r
-{\r
- static spl::shared_ptr<AVPacket> pkt(new AVPacket());\r
- return pkt;\r
-}\r
-\r
-\r
core::field_mode get_mode(const AVFrame& frame)\r
{\r
if(!frame.interlaced_frame)\r
\r
namespace caspar { namespace ffmpeg {\r
\r
-std::shared_ptr<core::audio_buffer> flush_audio();\r
std::shared_ptr<core::audio_buffer> empty_audio();\r
-std::shared_ptr<AVFrame> flush_video();\r
-std::shared_ptr<AVFrame> empty_video();\r
-\r
-spl::shared_ptr<AVPacket> flush_packet(); \r
-spl::shared_ptr<AVPacket> null_packet(); \r
+std::shared_ptr<AVFrame> empty_video(); \r
\r
// Utils\r
\r
std::shared_ptr<AVPacket> packet;\r
if(!input_->try_pop_video(packet))\r
return result;\r
-\r
- if(packet == flush_packet())\r
- {\r
- avcodec_flush_buffers(codec_context_.get());\r
- return result;\r
- }\r
- \r
- if(packet == null_packet())\r
- {\r
- if(codec_context_->codec->capabilities & CODEC_CAP_DELAY)\r
- {\r
- AVPacket pkt = {0}; \r
- av_init_packet(&pkt);\r
\r
- std::shared_ptr<AVFrame> frame;\r
- while(decode(pkt, frame))\r
- result.push_back(frame); \r
- }\r
- return result;\r
- }\r
-\r
- while(packet->size > 0)\r
+ if(packet)\r
{\r
- std::shared_ptr<AVFrame> frame;\r
- if(decode(*packet, frame))\r
- result.push_back(frame); \r
+ if(!packet->data && (codec_context_->codec->capabilities & CODEC_CAP_DELAY)) \r
+ while(decode(*packet, result)); \r
+\r
+ while(packet->size > 0)\r
+ decode(*packet, result); \r
}\r
+ else\r
+ avcodec_flush_buffers(codec_context_.get());\r
\r
return result;\r
}\r
\r
- bool decode(AVPacket& pkt, std::shared_ptr<AVFrame>& result)\r
+ bool decode(AVPacket& pkt, std::vector<std::shared_ptr<AVFrame>>& result)\r
{\r
- result = std::shared_ptr<AVFrame>(avcodec_alloc_frame(), av_free);\r
+ auto frame = std::shared_ptr<AVFrame>(avcodec_alloc_frame(), av_free);\r
\r
int got_frame = 0;\r
- auto len = THROW_ON_ERROR2(avcodec_decode_video2(codec_context_.get(), result.get(), &got_frame, &pkt), "[video_decocer]");\r
+ auto len = THROW_ON_ERROR2(avcodec_decode_video2(codec_context_.get(), frame.get(), &got_frame, &pkt), "[video_decocer]");\r
\r
if(len == 0)\r
{\r
\r
file_frame_number_ = packet_frame_number;\r
\r
- is_progressive_ = !result->interlaced_frame;\r
+ is_progressive_ = !frame->interlaced_frame;\r
\r
- if(result->repeat_pict > 0)\r
+ if(frame->repeat_pict > 0)\r
CASPAR_LOG(warning) << "[video_decoder] repeat_pict not implemented.";\r
\r
event_subject_ << monitor::event("file/video/width") % width_\r
<< monitor::event("file/video/height") % height_\r
- << monitor::event("file/video/field") % u8(!result->interlaced_frame ? "progressive" : (result->top_field_first ? "upper" : "lower"))\r
+ << monitor::event("file/video/field") % u8(!frame->interlaced_frame ? "progressive" : (frame->top_field_first ? "upper" : "lower"))\r
<< monitor::event("file/video/codec") % u8(codec_context_->codec->long_name);\r
\r
+ result.push_back(frame);\r
+\r
return true;\r
}\r
\r