virtual safe_ptr<basic_frame> receive(int) override { auto format_desc = consumer_->get_video_format_desc(); if(frame_buffer_.size() > 0) { auto frame = frame_buffer_.front(); frame_buffer_.pop(); return last_frame_ = frame; } auto read_frame = consumer_->receive(); if(!read_frame || read_frame->image_data().empty()) return basic_frame::late(); frame_number_++; core::pixel_format_desc desc; bool double_speed = std::abs(frame_factory_->get_video_format_desc().fps / 2.0 - format_desc.fps) < 0.01; bool half_speed = std::abs(format_desc.fps / 2.0 - frame_factory_->get_video_format_desc().fps) < 0.01; if(half_speed && frame_number_ % 2 == 0) // Skip frame return receive(0); desc.pix_fmt = core::pixel_format::bgra; desc.planes.push_back(core::pixel_format_desc::plane(format_desc.width, format_desc.height, 4)); auto frame = frame_factory_->create_frame(this, desc, read_frame->multichannel_view().channel_layout()); bool copy_audio = !double_speed && !half_speed; if (copy_audio) { frame->audio_data().reserve(read_frame->audio_data().size()); boost::copy(read_frame->audio_data(), std::back_inserter(frame->audio_data())); } fast_memcpy(frame->image_data().begin(), read_frame->image_data().begin(), read_frame->image_data().size()); frame->commit(); frame_buffer_.push(frame); if(double_speed) frame_buffer_.push(frame); return receive(0); }
safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params) { if(params.empty() || !boost::iequals(params[0], "decklink")) return core::frame_producer::empty(); auto device_index = get_param(L"DEVICE", params, -1); if(device_index == -1) device_index = boost::lexical_cast<int>(params.at(1)); auto filter_str = get_param(L"FILTER", params); auto length = get_param(L"LENGTH", params, std::numeric_limits<uint32_t>::max()); auto format_desc = core::video_format_desc::get(get_param(L"FORMAT", params, L"INVALID")); boost::replace_all(filter_str, L"DEINTERLACE", L"YADIF=0:-1"); boost::replace_all(filter_str, L"DEINTERLACE_BOB", L"YADIF=1:-1"); if(format_desc.format == core::video_format::invalid) format_desc = frame_factory->get_video_format_desc(); return create_producer_print_proxy( create_producer_destroy_proxy( make_safe<decklink_producer_proxy>(frame_factory, format_desc, device_index, filter_str, length))); }