Skip to content

Commit

Permalink
qPCL: add support for (u)int64 pcd field types
Browse files Browse the repository at this point in the history
- update dependencies in conda.yml
- PCL 1.13.1 supports int64 and uint64 field types
- PCL dependency from vtk forced also to update ffmpeg
- qAimation: update QVideoEncoder to use newer ffmpeg API
  • Loading branch information
SamuelSandvik committed Feb 12, 2024
1 parent dde9986 commit 41551f7
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 44 deletions.
10 changes: 5 additions & 5 deletions .ci/conda.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ name: CloudCompareDev
channels:
- conda-forge
dependencies:
- eigen=3.3.*
- ffmpeg=4.2.*
- eigen=3.4.*
- ffmpeg=6.1.*
- ninja
- pcl=1.9.*
- pdal=2.1.*
- qt=5.12.*
- pcl=1.13.1
- pdal=2.6.*
- qt=5.15.*
- xerces-c=3.2.*
- zlib=1.2.*
- laszip
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ void QVideoEncoder::freeFrame()
{
if (m_ff->frame)
{
av_free(m_ff->frame);
av_frame_free(&m_ff->frame);
m_ff->frame = 0;
}
}
Expand All @@ -111,10 +111,10 @@ bool QVideoEncoder::GetSupportedOutputFormats(std::vector<OutputFormat>& formats
try
{
// list of all output formats
AVOutputFormat* prev = nullptr;
void *ofmt_opaque = nullptr;
while (true)
{
AVOutputFormat* format = av_oformat_next(prev);
const AVOutputFormat *format = av_muxer_iterate(&ofmt_opaque);
if (format)
{
//potentially skip the output formats without any extension (= test formats mostly)
Expand All @@ -130,7 +130,6 @@ bool QVideoEncoder::GetSupportedOutputFormats(std::vector<OutputFormat>& formats
}
formats.push_back(f);
}
prev = format;
}
else
{
Expand Down Expand Up @@ -161,7 +160,7 @@ bool QVideoEncoder::open(QString formatShortName, QStringList& errors)
return false;
}

AVOutputFormat* outputFormat = NULL;
const AVOutputFormat *outputFormat = NULL;
if (!formatShortName.isEmpty())
{
outputFormat = av_guess_format(qPrintable(formatShortName), NULL, NULL);
Expand Down Expand Up @@ -197,7 +196,7 @@ bool QVideoEncoder::open(QString formatShortName, QStringList& errors)
AVCodecID codec_id = m_ff->formatContext->oformat->video_codec;
//codec_id = AV_CODEC_ID_MPEG1VIDEO;
//codec_id = AV_CODEC_ID_H264;
AVCodec *pCodec = avcodec_find_encoder(codec_id);
const AVCodec *pCodec = avcodec_find_encoder(codec_id);
if (!pCodec)
{
errors << "Could not load the codec";
Expand Down Expand Up @@ -247,7 +246,7 @@ bool QVideoEncoder::open(QString formatShortName, QStringList& errors)
return false;
}
m_ff->videoStream->id = m_ff->formatContext->nb_streams-1;
m_ff->videoStream->codec = m_ff->codecContext;
avcodec_parameters_from_context(m_ff->videoStream->codecpar, m_ff->codecContext);
m_ff->videoStream->time_base.num = 1;
m_ff->videoStream->time_base.den = m_fps;

Expand All @@ -274,7 +273,7 @@ bool QVideoEncoder::open(QString formatShortName, QStringList& errors)
}

int err = avformat_write_header(m_ff->formatContext, NULL);

if ( err != 0 )
{
errors << QString("Could not write header for '%1'").arg(m_filename);
Expand All @@ -293,7 +292,7 @@ static int write_frame(FFmpegStuffEnc* ff, AVPacket *pkt)
assert(ff);
return 0;
}

//if (ff->codecContext->coded_frame->key_frame)
//{
// pkt->flags |= AV_PKT_FLAG_KEY;
Expand All @@ -314,35 +313,33 @@ bool QVideoEncoder::close()
return false;
}

int ret = avcodec_send_frame(m_ff->codecContext, 0);

// delayed frames?
while (true)
while (ret >= 0)
{
AVPacket pkt;
memset( &pkt, 0, sizeof( AVPacket ) );
memset(&pkt, 0, sizeof(AVPacket));
av_init_packet(&pkt);

int got_packet = 0;
int ret = avcodec_encode_video2(m_ff->codecContext, &pkt, 0, &got_packet);
if (ret < 0 || !got_packet)
ret = avcodec_receive_packet(m_ff->codecContext, &pkt);
if (ret < 0)
{
break;
}

write_frame(m_ff, &pkt);

av_packet_unref(&pkt);
}

av_write_trailer(m_ff->formatContext);

// close the codec
avcodec_close(m_ff->videoStream->codec);
avcodec_close(m_ff->codecContext);

// free the streams and other data
freeFrame();
for(unsigned i = 0; i < m_ff->formatContext->nb_streams; i++)
{
av_freep(&m_ff->formatContext->streams[i]->codec);
av_freep(&m_ff->formatContext->streams[i]);
}

Expand Down Expand Up @@ -372,18 +369,13 @@ bool QVideoEncoder::encodeImage(const QImage &image, int frameIndex, QString* er
return false;
}

AVPacket pkt;
memset( &pkt, 0, sizeof( AVPacket ) );
av_init_packet(&pkt);

// encode the image
int got_packet = 0;
{
//compute correct timestamp based on the input frame index
//int timestamp = ((m_ff->codecContext->time_base.num * 90000) / m_ff->codecContext->time_base.den) * frameIndex;
m_ff->frame->pts = frameIndex/*timestamp*/;

int ret = avcodec_encode_video2(m_ff->codecContext, &pkt, m_ff->frame, &got_packet);
int ret = avcodec_send_frame(m_ff->codecContext, m_ff->frame);
if (ret < 0)
{
char errorStr[AV_ERROR_MAX_STRING_SIZE] = {0};
Expand All @@ -392,23 +384,37 @@ bool QVideoEncoder::encodeImage(const QImage &image, int frameIndex, QString* er
*errorString = QString("Error encoding video frame: %1").arg(errorStr);
return false;
}
}

if (got_packet)
{
int ret = write_frame(m_ff, &pkt);
if (ret < 0)
while (ret >= 0)
{
char errorStr[AV_ERROR_MAX_STRING_SIZE] = {0};
av_make_error_string(errorStr, AV_ERROR_MAX_STRING_SIZE, ret);
if (errorString)
*errorString = QString("Error while writing video frame: %1").arg(errorStr);
return false;
AVPacket pkt;
memset(&pkt, 0, sizeof(AVPacket));
av_init_packet(&pkt);

ret = avcodec_receive_packet(m_ff->codecContext, &pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
break;
else if (ret < 0)
{
char errorStr[AV_ERROR_MAX_STRING_SIZE] = {0};
av_make_error_string(errorStr, AV_ERROR_MAX_STRING_SIZE, ret);
if (errorString)
*errorString = QString("Error receiving video frame: %1").arg(errorStr);
return false;
}

int wRet = write_frame(m_ff, &pkt);
if (wRet < 0)
{
char errorStr[AV_ERROR_MAX_STRING_SIZE] = {0};
av_make_error_string(errorStr, AV_ERROR_MAX_STRING_SIZE, wRet);
if (errorString)
*errorString = QString("Error while writing video frame: %1").arg(errorStr);
return false;
}
}
}

av_packet_unref(&pkt);

return true;
}

Expand All @@ -421,7 +427,7 @@ bool QVideoEncoder::convertImage_sws(const QImage &image, QString* errorString/*
*errorString = "Wrong image size";
return false;
}

QImage::Format format = image.format();
if ( format != QImage::Format_RGB32
&& format != QImage::Format_ARGB32
Expand Down
22 changes: 22 additions & 0 deletions plugins/core/Standard/qPCL/PclUtils/utils/my_point_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,20 @@ struct UInt8Scalar

};

struct Int64Scalar
{
std::int64_t S5c4laR;
EIGEN_MAKE_ALIGNED_OPERATOR_NEW

};

struct UInt64Scalar
{
std::uint64_t S5c4laR;
EIGEN_MAKE_ALIGNED_OPERATOR_NEW

};

//! PCL custom point type used for reading intensity data
struct OnlyNormals
{
Expand Down Expand Up @@ -232,6 +246,14 @@ POINT_CLOUD_REGISTER_POINT_STRUCT (UInt8Scalar,
(std::uint8_t, S5c4laR, S5c4laR)
)

POINT_CLOUD_REGISTER_POINT_STRUCT (Int64Scalar,
(std::int64_t, S5c4laR, S5c4laR)
)

POINT_CLOUD_REGISTER_POINT_STRUCT (UInt64Scalar,
(std::uint64_t, S5c4laR, S5c4laR)
)

POINT_CLOUD_REGISTER_POINT_STRUCT (OnlyNormals,
(float, normal_x, normal_x)
(float, normal_y, normal_y)
Expand Down
30 changes: 28 additions & 2 deletions plugins/core/Standard/qPCL/PclUtils/utils/sm2cc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ POINT_CLOUD_REGISTER_POINT_STRUCT(PointXYZTpl<double>,
(double, x, x)
(double, y, y)
(double, z, z) )

static size_t GetNumberOfPoints(const PCLCloud& pclCloud)
{
return static_cast<size_t>(pclCloud.width) * pclCloud.height;
Expand Down Expand Up @@ -211,7 +211,7 @@ bool pcl2cc::CopyNormals(const PCLCloud& pclCloud, ccPointCloud& ccCloud)
}

ccCloud.showNormals(true);

return true;
}

Expand Down Expand Up @@ -379,6 +379,32 @@ bool pcl2cc::CopyScalarField( const PCLCloud& pclCloud,
}
break;

case PCLScalarField::UINT64:
{
pcl::PointCloud<UInt64Scalar> pclScalar;
FROM_PCL_CLOUD(pclCloud, pclScalar);

for (unsigned i = 0; i < pointCount; ++i)
{
ScalarType scalar = static_cast<ScalarType>(pclScalar.points[i].S5c4laR);
newSF->addElement(scalar);
}
}
break;

case PCLScalarField::INT64:
{
pcl::PointCloud<Int64Scalar> pclScalar;
FROM_PCL_CLOUD(pclCloud, pclScalar);

for (unsigned i = 0; i < pointCount; ++i)
{
ScalarType scalar = static_cast<ScalarType>(pclScalar.points[i].S5c4laR);
newSF->addElement(scalar);
}
}
break;

default:
ccLog::Warning(QString("[PCL] Field with an unmanaged type (= %1)").arg(pclField.datatype));
newSF->release();
Expand Down

0 comments on commit 41551f7

Please sign in to comment.