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

Working decode size detection

parent 45fb4e31
No related branches found
No related tags found
1 merge request!335Implements #374 decoder detected size
Pipeline #29192 passed
...@@ -25,7 +25,7 @@ class NvidiaDecoder : public ftl::codecs::Decoder { ...@@ -25,7 +25,7 @@ class NvidiaDecoder : public ftl::codecs::Decoder {
ftl::codecs::codec_t last_codec_; ftl::codecs::codec_t last_codec_;
MUTEX mutex_; MUTEX mutex_;
bool seen_iframe_; bool seen_iframe_;
cv::cuda::GpuMat tmp_; cv::cuda::GpuMat buffer_;
int width_; int width_;
int height_; int height_;
int last_width_; int last_width_;
......
...@@ -115,13 +115,16 @@ uint8_t* NvidiaDecoder::_decode(const uint8_t* src, uint64_t srcSize) { ...@@ -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) { bool NvidiaDecoder::decode(const ftl::codecs::Packet &pkt, cv::cuda::GpuMat &out) {
//cudaSetDevice(0); //cudaSetDevice(0);
UNIQUE_LOCK(mutex_,lk); 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 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 && 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; !(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"; LOG(ERROR) << "Invalid buffer for float frame";
return false; return false;
} }
...@@ -129,7 +132,7 @@ bool NvidiaDecoder::decode(const ftl::codecs::Packet &pkt, cv::cuda::GpuMat &out ...@@ -129,7 +132,7 @@ bool NvidiaDecoder::decode(const ftl::codecs::Packet &pkt, cv::cuda::GpuMat &out
if (!is_float_frame && out.type() != CV_8UC4) { if (!is_float_frame && out.type() != CV_8UC4) {
LOG(ERROR) << "Invalid buffer for lossy colour frame: " << out.type(); LOG(ERROR) << "Invalid buffer for lossy colour frame: " << out.type();
return false; return false;
} }*/
_create(pkt); _create(pkt);
...@@ -175,10 +178,10 @@ bool NvidiaDecoder::decode(const ftl::codecs::Packet &pkt, cv::cuda::GpuMat &out ...@@ -175,10 +178,10 @@ bool NvidiaDecoder::decode(const ftl::codecs::Packet &pkt, cv::cuda::GpuMat &out
width_ = nv_decoder_->GetWidth(); width_ = nv_decoder_->GetWidth();
height_ = nv_decoder_->GetHeight(); 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; LOG(ERROR) << "Decoded frame not same size as buffer: " << width_ << "x" << height_ << " -> " << out.cols << "x" << out.rows;
return false; return false;
} }*/
// OpenCV GpuMat for YCbCr 4:2:0 // OpenCV GpuMat for YCbCr 4:2:0
cv::cuda::GpuMat surface; cv::cuda::GpuMat surface;
...@@ -190,14 +193,23 @@ bool NvidiaDecoder::decode(const ftl::codecs::Packet &pkt, cv::cuda::GpuMat &out ...@@ -190,14 +193,23 @@ bool NvidiaDecoder::decode(const ftl::codecs::Packet &pkt, cv::cuda::GpuMat &out
if (is_float_frame) { if (is_float_frame) {
if (!islossless) { if (!islossless) {
buffer_.create(height_, width_, CV_32F);
out = buffer_;
cv::cuda::GpuMat sroi = surface(cv::Rect(0,0,width_, height_)); cv::cuda::GpuMat sroi = surface(cv::Rect(0,0,width_, height_));
cv::cuda::GpuMat csroi = surface(cv::Rect(0,height_,width_, height_/2)); cv::cuda::GpuMat csroi = surface(cv::Rect(0,height_,width_, height_/2));
ftl::cuda::vuya_to_depth(out, sroi, csroi, 16.0f, cvstream); ftl::cuda::vuya_to_depth(out, sroi, csroi, 16.0f, cvstream);
} else { } 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_); ftl::cuda::nv12_to_float(decodedPtr, width_, (float*)out.data, static_cast<uint32_t>(out.step1()), width_/2, height_, stream_);
} }
} else { } else {
buffer_.create(height_, width_, CV_8UC4);
out = buffer_;
// Flag 0x1 means frame is in RGB so needs conversion to BGR // Flag 0x1 means frame is in RGB so needs conversion to BGR
if (pkt.flags & 0x1) { if (pkt.flags & 0x1) {
Nv12ToColor32<BGRA32>(decodedPtr, width_, out.data, static_cast<int>(out.step1()), width_, height_, 0, stream_); 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" ) { ...@@ -316,21 +316,6 @@ TEST_CASE( "NvidiaDecoder::decode() - corrupted packet" ) {
cv::cuda::GpuMat in; cv::cuda::GpuMat in;
cv::cuda::GpuMat out; 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") { SECTION("Corrupted but supported codec") {
in = cv::cuda::GpuMat(cv::Size(2560,720), CV_8UC4, cv::Scalar(255,0,0,0)); 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)); 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" ) { ...@@ -379,7 +364,8 @@ TEST_CASE( "NvidiaDecoder::decode() - corrupted packet" ) {
pkt.flags = ftl::codecs::kFlagFloat; pkt.flags = ftl::codecs::kFlagFloat;
REQUIRE( r ); REQUIRE( r );
REQUIRE( !decoder.decode(pkt, out) ); REQUIRE( decoder.decode(pkt, out) );
REQUIRE( out.type() == CV_32F );
} }
SECTION("Corrupted float mapped flags") { SECTION("Corrupted float mapped flags") {
...@@ -414,7 +400,9 @@ TEST_CASE( "NvidiaDecoder::decode() - corrupted packet" ) { ...@@ -414,7 +400,9 @@ TEST_CASE( "NvidiaDecoder::decode() - corrupted packet" ) {
pkt.flags = 0; pkt.flags = 0;
REQUIRE( r ); 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") { SECTION("Missing data") {
......
...@@ -255,38 +255,13 @@ void Receiver::_processVideo(const StreamPacket &spkt, const Packet &pkt) { ...@@ -255,38 +255,13 @@ void Receiver::_processVideo(const StreamPacket &spkt, const Packet &pkt) {
auto [tx,ty] = ftl::codecs::chooseTileConfig(pkt.frame_count); 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) { if (tx == 0 || ty == 0) {
LOG(ERROR) << "No Packets"; LOG(ERROR) << "No Packets";
return; return;
} }
auto &surface = ividstate.surface[static_cast<int>(spkt.channel)]; cv::cuda::GpuMat surface;
//bool is_static = ividstate.decoders[channum] && (spkt.hint_capability & ftl::codecs::kStreamCap_Static);
// 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);
// Find or create the decoder // Find or create the decoder
_createDecoder(ividstate, channum, pkt); _createDecoder(ividstate, channum, pkt);
...@@ -297,17 +272,30 @@ void Receiver::_processVideo(const StreamPacket &spkt, const Packet &pkt) { ...@@ -297,17 +272,30 @@ void Receiver::_processVideo(const StreamPacket &spkt, const Packet &pkt) {
} }
// Do the actual decode into the surface buffer // Do the actual decode into the surface buffer
if (!is_static) { try {
try { FTL_Profile("Decode", 0.015);
FTL_Profile("Decode", 0.015); if (!decoder->decode(pkt, surface)) {
if (!decoder->decode(pkt, surface)) { LOG(ERROR) << "Decode failed on channel " << (int)spkt.channel;
LOG(ERROR) << "Decode failed on channel " << (int)spkt.channel;
return;
}
} catch (std::exception &e) {
LOG(ERROR) << "Decode failed for " << spkt.timestamp << ": " << e.what();
return; 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 // 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