+ return print_.value();\r
+ }\r
+\r
+ virtual void run()\r
+ {\r
+ try\r
+ {\r
+ struct co_init\r
+ {\r
+ co_init() {CoInitialize(NULL);}\r
+ ~co_init() {CoUninitialize();}\r
+ } init;\r
+ \r
+ Concurrency::bounded_buffer<frame_packet> input_buffer(2);\r
+\r
+ std::unique_ptr<decklink_producer> producer;\r
+ { \r
+ Concurrency::scoped_oversubcription_token oversubscribe;\r
+ producer.reset(new decklink_producer(input_buffer, format_desc_, device_index_));\r
+ }\r
+\r
+ Concurrency::send(print_, producer->print());\r
+\r
+ while(is_running_)\r
+ {\r
+ auto packet = Concurrency::receive(input_buffer);\r
+ auto video = packet.first;\r
+ auto audio = packet.second;\r
+ \r
+ void* bytes = nullptr;\r
+ if(FAILED(video->GetBytes(&bytes)) || !bytes)\r
+ continue;\r
+ \r
+ safe_ptr<AVFrame> av_frame(avcodec_alloc_frame(), av_free); \r
+ avcodec_get_frame_defaults(av_frame.get());\r
+ \r
+ av_frame->data[0] = reinterpret_cast<uint8_t*>(bytes);\r
+ av_frame->linesize[0] = video->GetRowBytes(); \r
+ av_frame->format = PIX_FMT_UYVY422;\r
+ av_frame->width = video->GetWidth();\r
+ av_frame->height = video->GetHeight();\r
+ av_frame->interlaced_frame = format_desc_.field_mode != core::field_mode::progressive;\r
+ av_frame->top_field_first = format_desc_.field_mode == core::field_mode::upper ? 1 : 0;\r
+ \r
+ filter_.push(av_frame);\r
+\r
+ Concurrency::parallel_invoke(\r
+ [&]\r
+ {\r
+ while(true)\r
+ {\r
+ auto frame = filter_.poll();\r
+ if(!frame)\r
+ break;\r
+ Concurrency::send(video_frames_, ffmpeg::make_message(frame, std::make_shared<ffmpeg::token>(semaphore_)));\r
+ }\r
+ },\r
+ [&]\r
+ { \r
+ // It is assumed that audio is always equal or ahead of video.\r
+ if(audio && SUCCEEDED(audio->GetBytes(&bytes)))\r
+ {\r
+ auto sample_frame_count = audio->GetSampleFrameCount();\r
+ auto audio_data = reinterpret_cast<int32_t*>(bytes);\r
+ Concurrency::send(audio_buffers_, ffmpeg::make_message(std::make_shared<core::audio_buffer>(audio_data, audio_data + sample_frame_count*format_desc_.audio_channels), std::make_shared<ffmpeg::token>(semaphore_)));\r
+ }\r
+ else\r
+ Concurrency::send(audio_buffers_, ffmpeg::make_message(ffmpeg::empty_audio(), std::make_shared<ffmpeg::token>(semaphore_))); \r
+ });\r
+ }\r
+\r
+ }\r
+ catch(...)\r
+ {\r
+ CASPAR_LOG_CURRENT_EXCEPTION();\r
+ }\r
+ \r
+ CASPAR_LOG(info) << print() << L" Successfully Uninitialized."; \r
+\r
+ done();\r