Skip to content
Snippets Groups Projects
opencv_decoder.cpp 2.28 KiB
Newer Older
#include <ftl/codecs/opencv_decoder.hpp>

#include <loguru.hpp>

using ftl::codecs::OpenCVDecoder;
using ftl::codecs::codec_t;

OpenCVDecoder::OpenCVDecoder() {

}

OpenCVDecoder::~OpenCVDecoder() {

}

bool OpenCVDecoder::accepts(const ftl::codecs::Packet &pkt) {
	return (pkt.codec == codec_t::JPG || pkt.codec == codec_t::PNG);
}

bool OpenCVDecoder::decode(const ftl::codecs::Packet &pkt, cv::cuda::GpuMat &out) {
Nicolas Pope's avatar
Nicolas Pope committed
	//CHECK(cv::Size(ftl::codecs::getWidth(pkt.definition), ftl::codecs::getHeight(pkt.definition)) == out.size()); 
	int chunk_dim = std::sqrt(pkt.block_total);
	int chunk_width = out.cols / chunk_dim;
	int chunk_height = out.rows / chunk_dim;

	// Build chunk head
	int cx = (pkt.block_number % chunk_dim) * chunk_width;
	int cy = (pkt.block_number / chunk_dim) * chunk_height;
	cv::Rect roi(cx,cy,chunk_width,chunk_height);
	cv::cuda::GpuMat chunkHead = out(roi);
	//LOG(INFO) << "DECODE JPEG " << (int)pkt.block_number << "/" << chunk_dim;

	cv::Mat tmp2_, tmp_;
	// Decode in temporary buffers to prevent long locks
	cv::imdecode(pkt.data, cv::IMREAD_UNCHANGED, &tmp2_);

	if (tmp2_.type() == CV_8UC3) {
		cv::cvtColor(tmp2_, tmp_, cv::COLOR_BGR2BGRA);
	} else {
		tmp_ = tmp2_;
	}

	// Apply colour correction to chunk
	//ftl::rgbd::colourCorrection(tmp_rgb, gamma_, temperature_);

	// TODO:(Nick) Decode directly into double buffer if no scaling
	// Can either check JPG/PNG headers or just use pkt definition.

	// Original size so just copy
	if (tmp_.cols == chunkHead.cols) {
		if (!tmp_.empty() && tmp_.type() == CV_16U && chunkHead.type() == CV_32F) {
			tmp_.convertTo(tmp_, CV_32FC1, 1.0f/1000.0f);
			chunkHead.upload(tmp_);
		} else if (!tmp_.empty() && tmp_.type() == CV_8UC4 && chunkHead.type() == CV_8UC4) {
			//tmp_.copyTo(chunkHead);
			chunkHead.upload(tmp_);
		} else {
			// Silent ignore?
		}
	// Downsized so needs a scale up
	} else {
		if (!tmp_.empty() && tmp_.type() == CV_16U && chunkHead.type() == CV_32F) {
			tmp_.convertTo(tmp_, CV_32FC1, 1.0f/1000.0f); //(16.0f*10.0f));
			cv::resize(tmp_, tmp_, chunkHead.size(), 0, 0, cv::INTER_NEAREST);
			chunkHead.upload(tmp_);
		} else if (!tmp_.empty() && tmp_.type() == CV_8UC4 && chunkHead.type() == CV_8UC4) {
			cv::resize(tmp_, tmp_, chunkHead.size());
			chunkHead.upload(tmp_);
		} else {
			// Silent ignore?
		}
	}

	return true;
}