result.push_back(std::make_shared<std::vector<int16_t>>(format_desc_.audio_samples_per_frame, 0));\r
else if(!packets_.empty())\r
{ \r
- auto packet = std::move(packets_.front());\r
- packets_.pop();\r
+ auto packet = packets_.front();\r
\r
if(packet) \r
{\r
- AVPacket pkt;\r
- av_init_packet(&pkt);\r
- pkt.data = packet->data;\r
- pkt.size = packet->size;\r
-\r
- for(int n = 0; n < 64 && pkt.size > 0; ++n)\r
- result.push_back(decode(pkt));\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
+ packets_.pop();\r
}\r
}\r
\r
else\r
{\r
av_dup_packet(read_packet.get());\r
+ \r
+ // Make sure that the packet is correctly deallocated even if size and data is modified during decoding.\r
+ auto size = read_packet->size;\r
+ auto data = read_packet->data;\r
+\r
+ read_packet = std::shared_ptr<AVPacket>(read_packet.get(), [=](AVPacket* pkt)\r
+ {\r
+ read_packet->size = size;\r
+ read_packet->data = data;\r
+ });\r
\r
graph_->update_value("buffer-count", MAX_BUFFER_SIZE/static_cast<double>(buffer_.size()));\r
\r
{\r
std::shared_ptr<AVFrame> frame;\r
\r
- auto packet = std::move(packet_buffer_.front());\r
+ auto packet = packet_buffer_.front();\r
\r
if(packet)\r
{\r
- frame = decode(*packet); \r
- packet_buffer_.pop();\r
+ frame = decode(*packet); \r
+ if(packet->size == 0)\r
+ packet_buffer_.pop();\r
}\r
else\r
{\r
return result;\r
}\r
\r
- std::shared_ptr<AVFrame> decode(AVPacket& packet)\r
+ std::shared_ptr<AVFrame> decode(AVPacket& pkt)\r
{\r
std::shared_ptr<AVFrame> decoded_frame(avcodec_alloc_frame(), av_free);\r
\r
int frame_finished = 0;\r
- const int errn = avcodec_decode_video2(codec_context_.get(), decoded_frame.get(), &frame_finished, &packet);\r
+ const int ret = avcodec_decode_video2(codec_context_.get(), decoded_frame.get(), &frame_finished, &pkt);\r
\r
- if(errn < 0)\r
+ if(ret < 0)\r
{\r
BOOST_THROW_EXCEPTION(\r
invalid_operation() <<\r
- msg_info(av_error_str(errn)) <<\r
+ msg_info(av_error_str(ret)) <<\r
boost::errinfo_api_function("avcodec_decode_video") <<\r
- boost::errinfo_errno(AVUNERROR(errn)));\r
+ boost::errinfo_errno(AVUNERROR(ret)));\r
}\r
\r
+ pkt.size -= ret;\r
+ pkt.data += ret;\r
+\r
if(frame_finished != 0) \r
{\r
return decoded_frame;\r