DataRecorder.cpp 3.72 KB
Newer Older
Thiago Santini's avatar
Thiago Santini committed
1 2 3 4
#include "DataRecorder.h"

using namespace cv;

5 6
DataRecorder::DataRecorder(QString id, QString header, QObject *parent)
    : id(id),
Thiago Santini's avatar
Thiago Santini committed
7 8 9 10 11 12 13
      header(header),
      videoWriter(NULL),
      dataFile(NULL),
      dataStream(NULL),
      framerate(0),
      QObject(parent)
{
14 15
    if (!id.contains("Journal"))
        pmIdx = gPerformanceMonitor.enrol(id, "Data Recorder");
Thiago Santini's avatar
Thiago Santini committed
16 17 18 19 20 21 22 23 24
}

DataRecorder::~DataRecorder()
{
    stopRecording();
}

void DataRecorder::startRecording()
{
25
    QString fileName = id + "Data.csv";
Thiago Santini's avatar
Thiago Santini committed
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
    dataFile = new QFile( fileName );
    if ( !dataFile->open(QIODevice::WriteOnly) ) {
        qWarning() << "Recording failure." << QString("Could not open %1").arg(fileName);
        delete dataFile;
        dataFile = NULL;
    }
    dataStream = new QTextStream(dataFile);
    *dataStream << header << gDataNewline;
}

void DataRecorder::startRecording(double fps)
{
    startRecording();
    videoWriter = new VideoWriter();
    firstFrame = true;
    videoIdx = 1;
    this->fps = fps;
}

void DataRecorder::stopRecording()
{
    if (videoWriter)
        videoWriter->release();

    if (dataFile){
        dataFile->close();
        dataFile->deleteLater();
    }
    delete dataStream;
    delete videoWriter;

    dataStream = NULL;
    dataFile = NULL;
    videoWriter = NULL;
}

void DataRecorder::newData(EyeData eyeData)
{
    storeData(eyeData);
}

void DataRecorder::newData(FieldData fieldData)
{
    storeData(fieldData);
}

void DataRecorder::newData(DataTuple dataTuple)
{
74 75 76
    // Note that the Journal data recorder doesn't registered with the
    // performance monitor since it's cheap to store its data.

Thiago Santini's avatar
Thiago Santini committed
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
    if (dataStream == NULL)
        return;

    if (dataStream->status() == QTextStream::Ok) {
        *dataStream << dataTuple.toQString();
        *dataStream << gDataNewline;
    }
}

bool DataRecorder::splitVideoFile()
{
    currentVideoFileInfo.refresh();
    if (currentVideoFileInfo.size() >= 1001390080 ) // to deal with opencv's avi size limitation (i.e., 2GB)
        return true;
    else
        return false;
}

template <class T>
void DataRecorder::storeData(T &data)
{
98
    if (firstFrame) {
Thiago Santini's avatar
Thiago Santini committed
99 100
        firstFrame = false;

101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
        // TODO: Make the container and codecs parametrizable
        // Alternative containers are .mkv and .mov, for which ffmpeg seems to use
        // fourcc codes

        /* OpenCV seems capable of using other containers now :D
         *
         * ffmpeg seems to use its own codes for tags instead of regular fourcc codes
         * when mp4 container is selected; for most fourcc codes end up being invalid
         * and it falls back to a default tag.
         *
         * From the ffmpeg source (libavformat/isom.c)
         *
         *    { AV_CODEC_ID_MPEG4       , 0x20 },
         *    { AV_CODEC_ID_H264        , 0x21 },
         *    { AV_CODEC_ID_MJPEG       , 0x6C }, // 10918-1
         *
         *
         * 	MPEG4 and H264 are compressed.
         *  MJPEG is uncompressed (and therefore gives huge files!)
         *
         */
        QString fileName = id + ".mp4";
123
		int codec = 0x6C;
Thiago Santini's avatar
Thiago Santini committed
124 125 126 127 128 129 130 131 132 133 134 135

        if (videoWriter->isOpened())
            videoWriter->release();

        if (!videoWriter->open(fileName.toStdString(), codec, this->fps, Size(data.input.cols, data.input.rows), data.input.channels() == 1 ? false : true))
            qWarning() << "Recording failure." << QString("Could not open %1").arg(fileName);

        currentVideoFileInfo.setFile(fileName);

        videoIdx++;
    }

136 137 138
    if ( gPerformanceMonitor.shouldDrop(pmIdx, gTimer.elapsed() - data.timestamp, 1000) )
        return;

Thiago Santini's avatar
Thiago Santini committed
139 140 141
    if (videoWriter->isOpened())
        *videoWriter << data.input;
    if (dataStream->status() == QTextStream::Ok)
Thiago Santini's avatar
Thiago Santini committed
142 143 144
		*dataStream << data.toQString() << gDataNewline;

	// TODO: add recording timestamp?
Thiago Santini's avatar
Thiago Santini committed
145
}