1 #include "../../../stdafx.h"
\r
3 #include "video_transformer.h"
\r
5 #include "../../../frame/frame_format.h"
\r
6 #include "../../../../common/image/image.h"
\r
7 #include "../../../frame/gpu_frame.h"
\r
8 #include "../../../frame/gpu_frame.h"
\r
9 #include "../../../frame/frame_factory.h"
\r
11 #include <tbb/parallel_for.h>
\r
12 #include <tbb/atomic.h>
\r
13 #include <tbb/mutex.h>
\r
14 #include <tbb/concurrent_queue.h>
\r
15 #include <tbb/scalable_allocator.h>
\r
17 #if defined(_MSC_VER)
\r
18 #pragma warning (push)
\r
19 #pragma warning (disable : 4244)
\r
23 #define __STDC_CONSTANT_MACROS
\r
24 #define __STDC_LIMIT_MACROS
\r
25 #include <libswscale/swscale.h>
\r
27 #if defined(_MSC_VER)
\r
28 #pragma warning (pop)
\r
31 namespace caspar{ namespace ffmpeg{
\r
33 typedef std::shared_ptr<SwsContext> SwsContextPtr;
\r
35 // TODO: Remove and do copy right into frame
\r
38 fill_frame(size_t width, size_t height)
\r
39 : frame(avcodec_alloc_frame(), av_free), buffer(static_cast<unsigned char*>(scalable_aligned_malloc(width*height*4, 16)), scalable_aligned_free)
\r
41 avpicture_fill(reinterpret_cast<AVPicture*>(frame.get()), buffer.get(), PIX_FMT_BGRA, width, height);
\r
43 const AVFramePtr frame;
\r
44 const std::shared_ptr<unsigned char> buffer;
\r
46 typedef std::shared_ptr<fill_frame> fill_frame_ptr;
\r
48 struct video_transformer::implementation : boost::noncopyable
\r
50 video_packet_ptr execute(const video_packet_ptr video_packet)
\r
52 assert(video_packet);
\r
57 sws_context_.reset(sws_getContext(video_packet->codec_context->width, video_packet->codec_context->height, video_packet->codec_context->pix_fmt, video_packet->format_desc.width, video_packet->format_desc.height,
\r
58 PIX_FMT_BGRA, SWS_BILINEAR, nullptr, nullptr, ¶m), sws_freeContext);
\r
62 //avcodec_get_frame_defaults(avFrame);
\r
63 //avpicture_fill(reinterpret_cast<AVPicture*>(&avFrame), video_packet->frame->data(), PIX_FMT_BGRA, video_packet->frameFormat.width, video_packet->frameFormat.height);
\r
65 auto format_desc = video_packet->format_desc;
\r
67 fill_frame fill_frame(format_desc.width, format_desc.height);
\r
68 video_packet->frame = factory_->create_frame(format_desc.width, format_desc.height);
\r
69 int result = sws_scale(sws_context_.get(), video_packet->decoded_frame->data, video_packet->decoded_frame->linesize, 0, video_packet->codec_context->height, fill_frame.frame->data, fill_frame.frame->linesize);
\r
70 video_packet->decoded_frame.reset(); // Free memory
\r
72 if(video_packet->codec->id == CODEC_ID_DVVIDEO) // Move up one field
\r
74 size_t size = format_desc.width * format_desc.height * 4;
\r
75 size_t linesize = format_desc.width * 4;
\r
76 common::image::copy(video_packet->frame->data(), fill_frame.buffer.get() + linesize, size - linesize);
\r
77 common::image::clear(video_packet->frame->data() + size - linesize, linesize);
\r
81 // This copy should be unnecessary. But it seems that when mapping the frame memory to an avframe for scaling there are some artifacts in the picture. See line 59-61.
\r
82 common::image::copy(video_packet->frame->data(), fill_frame.buffer.get(), video_packet->frame->size());
\r
85 return video_packet;
\r
88 frame_factory_ptr factory_;
\r
89 SwsContextPtr sws_context_;
\r
92 video_transformer::video_transformer() : impl_(new implementation()){}
\r
93 video_packet_ptr video_transformer::execute(const video_packet_ptr& video_packet){return impl_->execute(video_packet);}
\r
94 void video_transformer::initialize(const frame_factory_ptr& factory){impl_->factory_ = factory; }
\r