diff options
Diffstat (limited to 'videoutils/videoutils.cpp')
-rw-r--r-- | videoutils/videoutils.cpp | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/videoutils/videoutils.cpp b/videoutils/videoutils.cpp new file mode 100644 index 0000000..343469c --- /dev/null +++ b/videoutils/videoutils.cpp @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2019 TOYOTA MOTOR CORPORATION + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "videoutils.h" +#include <opencv2/core.hpp> +#include <opencv2/imgproc/imgproc.hpp> + +#include <iostream> +#include <unistd.h> +#include <stdlib.h> +#include <boost/algorithm/string.hpp> +#include <glib.h> +#include <sys/time.h> + +using namespace VIDEO_UTILS; + +GMainLoop * mainloop = NULL; +static int grabImage(void *data); +static void printhelp(const char *argv0); +static void mainLoopQuit(int sig); + +VideoUtils::VideoUtils(int device, int framerate, int wid, int hght, std::string file, std::string co) + : fps(framerate), width(wid), height(hght), deviceno(device), codec(co), filename(file) +{ + cvCapture = std::unique_ptr < cv::VideoCapture > (new cv::VideoCapture()); + cvWriter = std::unique_ptr < cv::VideoWriter > (new cv::VideoWriter()); + + isReady = false; + framecount = 0; + + if (cvCapture && !cvCapture->isOpened()) + { + if (cvCapture->open(deviceno)) + { + cvCapture->set(cv::CAP_PROP_FRAME_WIDTH, width); + cvCapture->set(cv::CAP_PROP_FRAME_HEIGHT, height); + + if (cvWriter && !cvWriter->isOpened()) + { + isReady = openVideoWriter(); + } + } + } +} + +void VideoUtils::releaseSource() +{ + if (cvCapture && cvCapture->isOpened()) + { + cvCapture->release(); + } + + if (cvWriter && cvWriter->isOpened()) + { + cvWriter->release(); + } +} + +bool VideoUtils::openVideoWriter() +{ + if (!cvCapture || !cvCapture->isOpened() || !cvWriter) + { + return false; + } + + /* Get the size of a frame from the device. */ + cv::Size framesize = cv::Size((int) cvCapture->get(cv::CAP_PROP_FRAME_WIDTH), (int) cvCapture->get(cv::CAP_PROP_FRAME_HEIGHT)); + + /* Get the CODEC. */ + if (codec.empty() || codec.size() != 4) + { + codec = "MJPG"; + } + boost::algorithm::to_upper(codec); + + return cvWriter->open(filename, cv::VideoWriter::fourcc(codec.at(0), codec.at(1), codec.at(2), codec.at(3)), fps, framesize); +} + +void VideoUtils::writeVideoFrame(const cv::UMat& f) +{ + if (!cvWriter || !cvWriter->isOpened()) + { + return; + } + + if (framecount < fps) + { + framecount++; + return; + } + + cv::Mat frame; + f.copyTo(frame); + + /* Put the current time into the frame. */ + int fontFace = cv::FONT_HERSHEY_SIMPLEX; + double fontScale = 0.6; + int baseline = 0; + int thickness = 2; + std::stringstream datestr; + + datestr << getCurrentTime(); + + cv::Size dateTextSize = cv::getTextSize(datestr.str(), fontFace, fontScale, thickness, &baseline); + + for (; fontScale > 0.1 && dateTextSize.width > frame.cols; ) + { + fontScale -= 0.2; + dateTextSize = cv::getTextSize(datestr.str(), fontFace, fontScale, thickness, &baseline); + } + + cv::Point dateOrg(frame.cols - dateTextSize.width, dateTextSize.height); + + cv::putText(frame, datestr.str(), dateOrg, fontFace, fontScale, cv::Scalar(255, 255, 255), thickness); + + /* Write the frame into the log file. */ + *(cvWriter.get()) << frame; +} + +std::string VideoUtils::getCurrentTime() +{ + time_t seconds; + struct tm currenttime; + if (time(&seconds) == (time_t) - 1) + { + return ""; + } + localtime_r(&seconds, ¤ttime); + + char timestr[] = "1900/01/01/00/00/00"; + + sprintf(timestr, "%04d/%02d/%02d %02d:%02d:%02d", currenttime.tm_year + 1900, currenttime.tm_mon + 1, currenttime.tm_mday, currenttime.tm_hour, currenttime.tm_min, currenttime.tm_sec); + + return timestr; +} + +static int grabImage(void *data) +{ + VideoUtils* utils = reinterpret_cast<VideoUtils*>(data); + + if (!utils->cvCapture || !utils->cvCapture->isOpened()) + { + return false; + } + + cv::UMat frame; + *(utils->cvCapture.get()) >> frame; + + if (!frame.empty()) + { + /* Write the frame into the log file. */ + utils->writeVideoFrame(frame); + return true; + } + else + { + return false; + } +} + +static void printhelp(const char *argv0) +{ + printf("Usage: %s [args]\n" + " [-d|--device <0-5> ] set the device\n" + " [-w|--width] specify the width\n" + " [-h|--height] specify the height\n" + " [-r]--frame rate] specify the frame rate\n" + " [-c]--codec] specify the codec\n" + " [-f]--folder name] specify a folder to save the video file\n", argv0); +} + +static void mainLoopQuit(int sig) +{ + if ((sig == SIGUSR1) && (mainloop != NULL)) + { + g_main_loop_quit(mainloop); + } +} + +int main(int argc, char **argv) +{ + static int opt; + int device = 0; + int framerate = 30; + int width = 640; + int height = 480; + std::string filename = "/tmp/temp.avi"; + std::string codec = "MP42"; + + while ((opt = getopt(argc, argv, "d:w:h:r:f:c:")) != -1) + { + switch (opt) + { + case 'd': + device = atoi(optarg); + break; + case 'w': + width = atoi(optarg); + break; + case 'h': + height = atoi(optarg); + break; + case 'r': + framerate = atoi(optarg); + break; + case 'f': + filename.assign(optarg); + break; + case 'c': + codec.assign(optarg); + break; + default: + printhelp(basename(argv[0])); + return (0); + } + } + + VideoUtils utils(device, framerate, width, height, filename, codec); + + if (utils.isReady && framerate > 0) + { + void (*oldSigUsr1Handler)(int); + + oldSigUsr1Handler = signal(SIGUSR1, mainLoopQuit); + + mainloop = g_main_loop_new(NULL, FALSE); + + g_timeout_add(1000 / framerate, grabImage, &utils); + + g_main_loop_run(mainloop); + g_main_loop_unref(mainloop); + + if (oldSigUsr1Handler != SIG_ERR) + { + signal(SIGUSR1, oldSigUsr1Handler); + } + } + + utils.releaseSource(); + + return 0; +} |