, is_progressive_(true)\r
, source_([this](const video_decoder::source_element_t& packet){return packet->stream_index == index_;})\r
, target_(target)\r
- , governor_(2)\r
+ , governor_(1) // IMPORTANT: Must be 1 since avcodec_decode_video2 reuses memory.\r
{ \r
CASPAR_LOG(debug) << "[video_decoder] " << context.streams[index_]->codec->codec->long_name;\r
\r
pkt.size = 0;\r
\r
for(auto decoded_frame = decode(pkt); decoded_frame; decoded_frame = decode(pkt))\r
- {\r
- auto frame = dup_frame(make_safe_ptr(decoded_frame)); \r
- send(target_, safe_ptr<AVFrame>(frame.get(), [frame, ticket](AVFrame*){}));\r
+ { \r
+ send(target_, safe_ptr<AVFrame>(decoded_frame.get(), [decoded_frame, ticket](AVFrame*){}));\r
Context::Yield();\r
}\r
}\r
\r
// C-TODO: Avoid duplication.\r
// Need to dupliace frame data since avcodec_decode_video2 reuses it.\r
- auto frame = dup_frame(make_safe_ptr(decoded_frame));\r
- send(target_, safe_ptr<AVFrame>(frame.get(), [frame, ticket](AVFrame*){})); \r
+ send(target_, safe_ptr<AVFrame>(decoded_frame.get(), [decoded_frame, ticket](AVFrame*){})); \r
Context::Yield();\r
}\r
}\r
\r
done();\r
}\r
-\r
- safe_ptr<AVFrame> dup_frame(const safe_ptr<AVFrame>& frame)\r
- {\r
- auto desc = get_pixel_format_desc(static_cast<PixelFormat>(frame->format), frame->width, frame->height);\r
-\r
- auto count = desc.planes.size();\r
- std::array<uint8_t*, 4> org_ptrs;\r
- std::array<safe_ptr<uint8_t>, 4> new_ptrs;\r
- parallel_for<size_t>(0, count, [&](size_t n)\r
- {\r
- CASPAR_ASSERT(frame->data[n]);\r
- auto size = frame->linesize[n]*desc.planes[n].height;\r
- new_ptrs[n] = fast_memdup(frame->data[n], size);\r
- org_ptrs[n] = frame->data[n];\r
- frame->data[n] = new_ptrs[n].get();\r
- });\r
-\r
- return safe_ptr<AVFrame>(frame.get(), [frame, org_ptrs, new_ptrs, count](AVFrame*)\r
- {\r
- for(size_t n = 0; n < count; ++n)\r
- frame->data[n] = org_ptrs[n];\r
- });\r
- }\r
- \r
+ \r
double fps() const\r
{\r
return fps_;\r