You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
267 lines
6.8 KiB
267 lines
6.8 KiB
9 years ago
|
//------------------------------------------------------------------------------
|
||
|
//
|
||
|
// Project: Anonymizer
|
||
|
//
|
||
|
// Brno University of Technology
|
||
|
// Faculty of Information Technology
|
||
|
//
|
||
|
//------------------------------------------------------------------------------
|
||
|
//
|
||
|
// This project was financially supported by project VG20102015006 funds
|
||
|
// provided by Ministry of the Interior of the Czech republic.
|
||
|
//
|
||
|
//------------------------------------------------------------------------------
|
||
|
/*!
|
||
|
|
||
|
@file videoframe.cpp
|
||
|
@brief Implementation of methods ...
|
||
|
@details Details
|
||
|
@authors Martin Borek (mborekcz@gmail.com)
|
||
|
@authors Filip Orsag (orsag@fit.vutbr.cz)
|
||
|
@date 2014-2015
|
||
|
@note This project was supported by MV CR project VG20102015006.
|
||
|
@copyright BUT OPEN SOURCE LICENCE (see License.txt)
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include "videoframe.h"
|
||
|
|
||
|
#include <QDebug>
|
||
|
|
||
|
VideoFrame::VideoFrame():
|
||
|
scalingMethod(VIDEOTRACKING_DEFAULT_SCALING_METHOD)
|
||
|
{
|
||
|
matFrame = nullptr;
|
||
|
avFrame = nullptr;
|
||
|
width = 0;
|
||
|
height = 0;
|
||
|
}
|
||
|
|
||
|
VideoFrame::VideoFrame(unsigned int width, unsigned int height):
|
||
|
scalingMethod(VIDEOTRACKING_DEFAULT_SCALING_METHOD),
|
||
|
width(width),
|
||
|
height(height)
|
||
|
{
|
||
|
matFrame = nullptr;
|
||
|
avFrame = nullptr;
|
||
|
}
|
||
|
|
||
|
//VideoFrame::VideoFrame(cv::Mat const &newFrame, int64_t timestamp, unsigned long timePosition):
|
||
|
// Does not copy avFrame because it is not needed and would make it slower
|
||
|
VideoFrame::VideoFrame(VideoFrame const &obj):
|
||
|
scalingMethod(VIDEOTRACKING_DEFAULT_SCALING_METHOD)
|
||
|
{
|
||
|
avFrame = nullptr;
|
||
|
|
||
|
if (obj.matFrame)
|
||
|
matFrame = new cv::Mat(*(obj.matFrame));
|
||
|
else
|
||
|
matFrame = nullptr;
|
||
|
|
||
|
height = obj.height;
|
||
|
width = obj.width;
|
||
|
timestamp = obj.timestamp;
|
||
|
timePosition = obj.timePosition;
|
||
|
}
|
||
|
|
||
|
VideoFrame::~VideoFrame()
|
||
|
{
|
||
|
if (matFrame)
|
||
|
{
|
||
|
delete matFrame;
|
||
|
matFrame = nullptr;
|
||
|
}
|
||
|
if (avFrame)
|
||
|
{
|
||
|
av_free(avFrame->data[0]);
|
||
|
av_frame_free(&avFrame);
|
||
|
avFrame = nullptr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool VideoFrame::set_frame(AVFrame const *newFrame)
|
||
|
{
|
||
|
if (!matFrame) // matFrame is nullptr and was not allocated yet
|
||
|
{
|
||
|
if (!width || !height) // equals one of them zero?
|
||
|
return false;
|
||
|
else
|
||
|
matFrame = new cv::Mat(height, width, CV_8UC3); // CV_8UC3->3 channels of unsigned 8-bit int
|
||
|
}
|
||
|
|
||
|
return AVFrame2Mat(newFrame, matFrame);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
unsigned long VideoFrame::get_time_position() const
|
||
|
{
|
||
|
return timePosition;
|
||
|
}
|
||
|
|
||
|
int64_t VideoFrame::get_timestamp() const
|
||
|
{
|
||
|
return timestamp;
|
||
|
}
|
||
|
|
||
|
unsigned long VideoFrame::get_frame_number() const
|
||
|
{
|
||
|
return frameNumber;
|
||
|
}
|
||
|
|
||
|
unsigned int VideoFrame::get_width() const
|
||
|
{
|
||
|
return width;
|
||
|
}
|
||
|
|
||
|
unsigned int VideoFrame::get_height() const
|
||
|
{
|
||
|
return height;
|
||
|
}
|
||
|
|
||
|
void VideoFrame::set_size(unsigned int newWidth, unsigned int newHeight)
|
||
|
{
|
||
|
width = newWidth;
|
||
|
height = newHeight;
|
||
|
|
||
|
// size changed -> allocated memory incorrect; free memory; it will be allocated when needed
|
||
|
if (matFrame)
|
||
|
{
|
||
|
delete matFrame;
|
||
|
matFrame = nullptr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void VideoFrame::set_timestamp(int64_t newTimestamp)
|
||
|
{
|
||
|
timestamp = newTimestamp;
|
||
|
}
|
||
|
|
||
|
void VideoFrame::set_time_position(unsigned long newTimePosition)
|
||
|
{
|
||
|
timePosition = newTimePosition;
|
||
|
}
|
||
|
|
||
|
void VideoFrame::set_frame_number(unsigned long newFrameNumber)
|
||
|
{
|
||
|
frameNumber = newFrameNumber;
|
||
|
}
|
||
|
|
||
|
AVFrame const *VideoFrame::get_av_frame()
|
||
|
//AVFrame *VideoFrame::get_av_frame()
|
||
|
{
|
||
|
if (matFrame == nullptr) // There is not a valid frame that could be converted to AVFrame
|
||
|
return nullptr;
|
||
|
|
||
|
if (!avFrame)
|
||
|
{
|
||
|
avFrame = av_frame_alloc();
|
||
|
if (avFrame == nullptr)
|
||
|
{
|
||
|
qDebug() << "Not allocated";
|
||
|
exit(1);
|
||
|
}
|
||
|
int numBytes = avpicture_get_size((enum AVPixelFormat)outputFormat, width, height);
|
||
|
if (numBytes < 0)
|
||
|
{
|
||
|
qDebug() << "Error: avpicture_get_size()";
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
uint8_t *buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
|
||
|
if (buffer == nullptr)
|
||
|
{
|
||
|
qDebug() << "Not allocated";
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
if (avpicture_fill((AVPicture *)avFrame, buffer, (enum AVPixelFormat)outputFormat, width, height) < 0)
|
||
|
{
|
||
|
qDebug() << "Error: avpicture_fill()";
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Mat2AVFrame(*matFrame, avFrame, outputFormat);
|
||
|
avFrame->pts = timestamp;
|
||
|
return avFrame;
|
||
|
}
|
||
|
|
||
|
cv::Mat const *VideoFrame::get_mat_frame() const
|
||
|
{
|
||
|
return matFrame;
|
||
|
}
|
||
|
|
||
|
// dstMat must be allocated before
|
||
|
bool VideoFrame::AVFrame2Mat(AVFrame const *src, cv::Mat *dstMat) const
|
||
|
{
|
||
|
assert(src != nullptr);
|
||
|
//assert(dstMat != nullptr);
|
||
|
|
||
|
AVFrame *dst = nullptr;
|
||
|
dst = av_frame_alloc(); // Calls also memset, xal
|
||
|
|
||
|
dst->data[0] = (uint8_t *)dstMat->data; //dstMat->data is used as a buffer
|
||
|
|
||
|
// note: avpicture_fill does not perform a deep copy
|
||
|
if (avpicture_fill((AVPicture *)dst, dst->data[0], AV_PIX_FMT_BGR24, src->width, src->height) < 0)
|
||
|
{
|
||
|
qDebug() << "Error - AVFrame2Mat: avpicture_fill";
|
||
|
av_frame_free(&dst);
|
||
|
dst = nullptr;
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
SwsContext *conversionContext = nullptr; // Context is needed for sws_scale
|
||
|
conversionContext = sws_getContext(src->width, src->height, (enum AVPixelFormat)src->format,
|
||
|
src->width, src->height, AV_PIX_FMT_BGR24,
|
||
|
scalingMethod, NULL, NULL, NULL); // xal
|
||
|
|
||
|
|
||
|
sws_scale(conversionContext, src->data, src->linesize, 0, src->height,
|
||
|
dst->data, dst->linesize);
|
||
|
|
||
|
// free allocated memories
|
||
|
sws_freeContext(conversionContext);
|
||
|
conversionContext = nullptr;
|
||
|
av_frame_free(&dst);
|
||
|
dst = nullptr;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool VideoFrame::Mat2AVFrame(cv::Mat const &src, AVFrame *dstAVFrame, const int dstFormat) const
|
||
|
{
|
||
|
//assert(src != nullptr);
|
||
|
assert(dstAVFrame != nullptr);
|
||
|
|
||
|
static const int width = src.cols;
|
||
|
static const int height = src.rows;
|
||
|
|
||
|
AVFrame *srcAV = av_frame_alloc(); // Calls also memset, xal
|
||
|
if (srcAV == nullptr)
|
||
|
{
|
||
|
qDebug() << "Not allocated";
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
avpicture_fill((AVPicture *)srcAV, (uint8_t *)src.data, AV_PIX_FMT_BGR24, width, height);
|
||
|
|
||
|
// all frames have same width, height, format ...
|
||
|
SwsContext *conversionContext = sws_getContext(width, height, AV_PIX_FMT_BGR24,
|
||
|
width, height, (enum AVPixelFormat)dstFormat,
|
||
|
scalingMethod, NULL, NULL, NULL); // xal
|
||
|
|
||
|
|
||
|
sws_scale(conversionContext, srcAV->data, srcAV->linesize, 0, height,
|
||
|
dstAVFrame->data, dstAVFrame->linesize);
|
||
|
|
||
|
// free allocated memories
|
||
|
sws_freeContext(conversionContext);
|
||
|
conversionContext = nullptr;
|
||
|
av_frame_free(&srcAV);
|
||
|
srcAV = nullptr;
|
||
|
|
||
|
return true;
|
||
|
}
|