Skip to content
Snippets Groups Projects
Commit 82a9a4a3 authored by Nicolas Pope's avatar Nicolas Pope
Browse files

Merge branch 'feature/374/decodesize' into 'master'

Implements #374 decoder detected size

Closes #374

See merge request nicolas.pope/ftl!335
parents 45fb4e31 fac18531
No related branches found
No related tags found
1 merge request!335Implements #374 decoder detected size
Pipeline #29197 passed
......@@ -25,7 +25,7 @@ class NvidiaDecoder : public ftl::codecs::Decoder {
ftl::codecs::codec_t last_codec_;
MUTEX mutex_;
bool seen_iframe_;
cv::cuda::GpuMat tmp_;
cv::cuda::GpuMat buffer_;
int width_;
int height_;
int last_width_;
......
......@@ -115,13 +115,16 @@ uint8_t* NvidiaDecoder::_decode(const uint8_t* src, uint64_t srcSize) {
bool NvidiaDecoder::decode(const ftl::codecs::Packet &pkt, cv::cuda::GpuMat &out) {
//cudaSetDevice(0);
UNIQUE_LOCK(mutex_,lk);
if (pkt.codec != codec_t::HEVC && pkt.codec != codec_t::H264 && pkt.codec != codec_t::HEVC_LOSSLESS && pkt.codec != codec_t::H264_LOSSLESS) return false;
if (pkt.codec != codec_t::HEVC && pkt.codec != codec_t::H264 && pkt.codec != codec_t::HEVC_LOSSLESS && pkt.codec != codec_t::H264_LOSSLESS) {
LOG(ERROR) << "Bad codec: " << int(pkt.codec);
return false;
}
bool is_float_frame = pkt.flags & ftl::codecs::kFlagFloat;
bool islossless = ((pkt.codec == ftl::codecs::codec_t::HEVC || pkt.codec == ftl::codecs::codec_t::H264) && is_float_frame &&
!(pkt.flags & 0x2)) || pkt.codec == ftl::codecs::codec_t::HEVC_LOSSLESS || pkt.codec == ftl::codecs::codec_t::H264_LOSSLESS;
if (is_float_frame && out.type() != CV_32F) {
/*if (is_float_frame && out.type() != CV_32F) {
LOG(ERROR) << "Invalid buffer for float frame";
return false;
}
......@@ -129,7 +132,7 @@ bool NvidiaDecoder::decode(const ftl::codecs::Packet &pkt, cv::cuda::GpuMat &out
if (!is_float_frame && out.type() != CV_8UC4) {
LOG(ERROR) << "Invalid buffer for lossy colour frame: " << out.type();
return false;
}
}*/
_create(pkt);
......@@ -175,10 +178,10 @@ bool NvidiaDecoder::decode(const ftl::codecs::Packet &pkt, cv::cuda::GpuMat &out
width_ = nv_decoder_->GetWidth();
height_ = nv_decoder_->GetHeight();
if (out.cols != ((is_float_frame && islossless) ? width_/2 : width_) || out.rows != height_) {
/*if (out.cols != ((is_float_frame && islossless) ? width_/2 : width_) || out.rows != height_) {
LOG(ERROR) << "Decoded frame not same size as buffer: " << width_ << "x" << height_ << " -> " << out.cols << "x" << out.rows;
return false;
}
}*/
// OpenCV GpuMat for YCbCr 4:2:0
cv::cuda::GpuMat surface;
......@@ -190,14 +193,23 @@ bool NvidiaDecoder::decode(const ftl::codecs::Packet &pkt, cv::cuda::GpuMat &out
if (is_float_frame) {
if (!islossless) {
buffer_.create(height_, width_, CV_32F);
out = buffer_;
cv::cuda::GpuMat sroi = surface(cv::Rect(0,0,width_, height_));
cv::cuda::GpuMat csroi = surface(cv::Rect(0,height_,width_, height_/2));
ftl::cuda::vuya_to_depth(out, sroi, csroi, 16.0f, cvstream);
} else {
buffer_.create(height_, width_/2, CV_32F);
out = buffer_;
ftl::cuda::nv12_to_float(decodedPtr, width_, (float*)out.data, static_cast<uint32_t>(out.step1()), width_/2, height_, stream_);
}
} else {
buffer_.create(height_, width_, CV_8UC4);
out = buffer_;
// Flag 0x1 means frame is in RGB so needs conversion to BGR
if (pkt.flags & 0x1) {
Nv12ToColor32<BGRA32>(decodedPtr, width_, out.data, static_cast<int>(out.step1()), width_, height_, 0, stream_);
......
......@@ -316,21 +316,6 @@ TEST_CASE( "NvidiaDecoder::decode() - corrupted packet" ) {
cv::cuda::GpuMat in;
cv::cuda::GpuMat out;
SECTION("Bad output size") {
in = cv::cuda::GpuMat(cv::Size(2560,720), CV_8UC4, cv::Scalar(255,0,0,0));
out = cv::cuda::GpuMat(cv::Size(2500,720), CV_8UC4, cv::Scalar(0,0,0,0));
ftl::codecs::Packet pkt;
pkt.codec = codec_t::Any;
pkt.bitrate = 255;
pkt.frame_count = 2;
pkt.flags = 0;
bool r = encoder.encode(in, pkt);
REQUIRE( r );
REQUIRE( !decoder.decode(pkt, out) );
}
SECTION("Corrupted but supported codec") {
in = cv::cuda::GpuMat(cv::Size(2560,720), CV_8UC4, cv::Scalar(255,0,0,0));
out = cv::cuda::GpuMat(cv::Size(2560,720), CV_8UC4, cv::Scalar(0,0,0,0));
......@@ -379,7 +364,8 @@ TEST_CASE( "NvidiaDecoder::decode() - corrupted packet" ) {
pkt.flags = ftl::codecs::kFlagFloat;
REQUIRE( r );
REQUIRE( !decoder.decode(pkt, out) );
REQUIRE( decoder.decode(pkt, out) );
REQUIRE( out.type() == CV_32F );
}
SECTION("Corrupted float mapped flags") {
......@@ -414,7 +400,9 @@ TEST_CASE( "NvidiaDecoder::decode() - corrupted packet" ) {
pkt.flags = 0;
REQUIRE( r );
REQUIRE( !decoder.decode(pkt, out) );
REQUIRE( decoder.decode(pkt, out) );
REQUIRE( out.type() == CV_8UC4 );
REQUIRE( out.cols == 2*in.cols );
}
SECTION("Missing data") {
......
......@@ -255,38 +255,13 @@ void Receiver::_processVideo(const StreamPacket &spkt, const Packet &pkt) {
auto [tx,ty] = ftl::codecs::chooseTileConfig(pkt.frame_count);
int width = ividstate.width; //calibration.width;
int height = ividstate.height; //calibration.height;
if (width <= 0 || height <= 0 || width > 9000 || height > 9000) {
// Attempt to retry the decode later
// Make a copy of the packets into a thread job
// FIXME: Check that thread pool does not explode
if (spkt.retry_count < 10) {
LOG(WARNING) << "No calibration, retrying: " << spkt.timestamp;
ftl::pool.push([this, spkt, pkt](int id) mutable {
++const_cast<StreamPacket&>(spkt).retry_count;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
_processVideo(spkt, pkt);
});
} else {
LOG(WARNING) << "No calibration, failed frame: " << spkt.timestamp;
}
return;
}
if (tx == 0 || ty == 0) {
LOG(ERROR) << "No Packets";
return;
}
auto &surface = ividstate.surface[static_cast<int>(spkt.channel)];
// Allocate a decode surface, this is a tiled image to be split later
int cvtype = ftl::codecs::type(spkt.channel);
surface.create(height*ty, width*tx, cvtype);
bool is_static = ividstate.decoders[channum] && (spkt.hint_capability & ftl::codecs::kStreamCap_Static);
cv::cuda::GpuMat surface;
//bool is_static = ividstate.decoders[channum] && (spkt.hint_capability & ftl::codecs::kStreamCap_Static);
// Find or create the decoder
_createDecoder(ividstate, channum, pkt);
......@@ -297,17 +272,30 @@ void Receiver::_processVideo(const StreamPacket &spkt, const Packet &pkt) {
}
// Do the actual decode into the surface buffer
if (!is_static) {
try {
FTL_Profile("Decode", 0.015);
if (!decoder->decode(pkt, surface)) {
LOG(ERROR) << "Decode failed on channel " << (int)spkt.channel;
return;
}
} catch (std::exception &e) {
LOG(ERROR) << "Decode failed for " << spkt.timestamp << ": " << e.what();
try {
FTL_Profile("Decode", 0.015);
if (!decoder->decode(pkt, surface)) {
LOG(ERROR) << "Decode failed on channel " << (int)spkt.channel;
return;
}
} catch (std::exception &e) {
LOG(ERROR) << "Decode failed for " << spkt.timestamp << ": " << e.what();
return;
}
int width = surface.cols / tx;
int height = surface.rows / ty;
if (width == 0 || height == 0) {
LOG(ERROR) << "Invalid decoded size: " << surface.cols << "x" << surface.rows << " (" << tx << "," << ty << ")";
return;
}
int cvtype = ftl::codecs::type(spkt.channel);
if (surface.type() != cvtype) {
LOG(ERROR) << "Invalid video format received";
return;
}
// Get the frameset
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment