gstreamer sample: fixed incorrect pipelines being generated
authorMaksim Shabunin <maksim.shabunin@gmail.com>
Wed, 20 Jun 2018 11:15:34 +0000 (14:15 +0300)
committerMaksim Shabunin <maksim.shabunin@gmail.com>
Thu, 21 Jun 2018 14:14:42 +0000 (17:14 +0300)
samples/cpp/gstreamer_pipeline.cpp

index 0d46775..4ad1daa 100644 (file)
 #include "opencv2/highgui.hpp"
 #include <string>
 #include <iostream>
+#include <map>
 
 using namespace std;
 using namespace cv;
 
-class GStreamerPipeline
+//================================================================================
+
+template<typename M>
+inline typename M::mapped_type getValue(const M &dict, const typename M::key_type &key, const string & errorMessage)
 {
- public:
-    // Preprocessing arguments command line
-    GStreamerPipeline(int argc, char *argv[])
+    typename M::const_iterator it = dict.find(key);
+    if (it == dict.end())
     {
-        const string keys =
-              "{h help usage ? |           | print help messages   }"
-              "{m mode         |           | coding mode (supported: encode, decode) }"
-              "{p pipeline     |default    | pipeline name  (supported: 'default', 'gst-basic', 'gst-vaapi', 'gst-libav', 'ffmpeg') }"
-              "{cd codec       |h264       | codec name     (supported: 'h264', 'h265', 'mpeg2', 'mpeg4', 'mjpeg', 'vp8') }"
-              "{f file path    |           | path to file }"
-              "{vr resolution  |720p       | video resolution for encoding (supported: '720p', '1080p', '4k') }"
-              "{fps            |30         | fix frame per second for encoding (supported: fps > 0) }"
-              "{fm fast        |           | fast measure fps }";
-        cmd_parser = new CommandLineParser(argc, argv, keys);
-        cmd_parser->about("This program shows how to read a video file with GStreamer pipeline with OpenCV.");
+        CV_Error(Error::StsBadArg, errorMessage);
+    }
+    return it->second;
+}
 
-        if (cmd_parser->has("help"))
-        {
-            cmd_parser->printMessage();
-            CV_Error(Error::StsBadArg, "Called help.");
-        }
+inline map<string, Size> sizeByResolution()
+{
+    map<string, Size> res;
+    res["720p"] = Size(1280, 720);
+    res["1080p"] = Size(1920, 1080);
+    res["4k"] = Size(3840, 2160);
+    return res;
+}
 
-        fast_measure = cmd_parser->has("fast");               // fast measure fps
-        fix_fps      = cmd_parser->get<int>("fps");           // fixed frame per second
-        pipeline     = cmd_parser->get<string>("pipeline"),   // gstreamer pipeline type
-        mode         = cmd_parser->get<string>("mode"),       // coding mode
-        codec        = cmd_parser->get<string>("codec"),      // codec type
-        file_name    = cmd_parser->get<string>("file"),       // path to videofile
-        resolution   = cmd_parser->get<string>("resolution"); // video resolution
+inline map<string, int> fourccByCodec()
+{
+    map<string, int> res;
+    res["h264"] = VideoWriter::fourcc('H','2','6','4');
+    res["h265"] = VideoWriter::fourcc('H','E','V','C');
+    res["mpeg2"] = VideoWriter::fourcc('M','P','E','G');
+    res["mpeg4"] = VideoWriter::fourcc('M','P','4','2');
+    res["mjpeg"] = VideoWriter::fourcc('M','J','P','G');
+    res["vp8"] = VideoWriter::fourcc('V','P','8','0');
+    return res;
+}
 
-        size_t found = file_name.rfind(".");
-        if (found != string::npos)
-        {
-            container = file_name.substr(found + 1);  // container type
-        }
-        else { CV_Error(Error::StsBadArg, "Can not parse container extension."); }
+inline map<string, string> defaultEncodeElementByCodec()
+{
+    map<string, string> res;
+    res["h264"] = "x264enc";
+    res["h265"] = "x265enc";
+    res["mpeg2"] = "mpeg2enc";
+    res["mjpeg"] = "jpegenc";
+    res["vp8"] = "vp8enc";
+    return res;
+}
 
-        if (!cmd_parser->check())
-        {
-            cmd_parser->printErrors();
-            CV_Error(Error::StsBadArg, "Failed parse arguments.");
-        }
-    }
+inline map<string, string> VAAPIEncodeElementByCodec()
+{
+    map<string, string> res;
+    res["h264"] = "parsebin ! vaapih264enc";
+    res["h265"] = "parsebin ! vaapih265enc";
+    res["mpeg2"] = "parsebin ! vaapimpeg2enc";
+    res["mjpeg"] = "parsebin ! vaapijpegenc";
+    res["vp8"] = "parsebin ! vaapivp8enc";
+    return res;
+}
 
-    ~GStreamerPipeline() { delete cmd_parser; }
+inline map<string, string> mfxDecodeElementByCodec()
+{
+    map<string, string> res;
+    res["h264"] = "parsebin ! mfxh264dec";
+    res["h265"] = "parsebin ! mfxhevcdec";
+    res["mpeg2"] = "parsebin ! mfxmpeg2dec";
+    res["mjpeg"] = "parsebin ! mfxjpegdec";
+    return res;
+}
 
-    // Start pipeline
-    int run()
-    {
-        if      (mode == "decode") { if (createDecodePipeline() < 0) return -1; }
-        else if (mode == "encode") { if (createEncodePipeline() < 0) return -1; }
-        else
-        {
-            cout << "Unsupported mode: " << mode << endl;
-            cmd_parser->printErrors();
-            return -1;
-        }
-        cout << "_____________________________________" << endl;
-        cout << "Pipeline " << mode << ":" << endl;
-        cout << stream_pipeline.str() << endl;
-        // Choose a show video or only measure fps
-        cout << "_____________________________________" << endl;
-        cout << "Start measure frame per seconds (fps)" << endl;
-        cout << "Loading ..." << endl;
+inline map<string, string> mfxEncodeElementByCodec()
+{
+    map<string, string> res;
+    res["h264"] = "mfxh264enc";
+    res["h265"] = "mfxhevcenc";
+    res["mpeg2"] = "mfxmpeg2enc";
+    res["mjpeg"] = "mfxjpegenc";
+    return res;
+}
 
-        vector<double> tick_counts;
+inline map<string, string> libavDecodeElementByCodec()
+{
+    map<string, string> res;
+    res["h264"] = "parsebin ! avdec_h264";
+    res["h265"] = "parsebin ! avdec_h265";
+    res["mpeg2"] = "parsebin ! avdec_mpeg2video";
+    res["mpeg4"] = "parsebin ! avdec_mpeg4";
+    res["mjpeg"] = "parsebin ! avdec_mjpeg";
+    res["vp8"] = "parsebin ! avdec_vp8";
+    return res;
+}
 
-        cout << "Start " << mode << ": " << file_name;
-        cout << " (" << pipeline << ")" << endl;
+inline map<string, string> libavEncodeElementByCodec()
+{
+    map<string, string> res;
+    res["h264"] = "avenc_h264";
+    res["h265"] = "avenc_h265";
+    res["mpeg2"] = "avenc_mpeg2video";
+    res["mpeg4"] = "avenc_mpeg4";
+    res["mjpeg"] = "avenc_mjpeg";
+    res["vp8"] = "avenc_vp8";
+    return res;
+}
 
-        while(true)
-        {
-            int64 temp_count_tick = 0;
-            if (mode == "decode")
-            {
-                Mat frame;
-                temp_count_tick = getTickCount();
-                cap >> frame;
-                temp_count_tick = getTickCount() - temp_count_tick;
-                if (frame.empty()) { break; }
-            }
-            else if (mode == "encode")
-            {
-                Mat element;
-                while(!cap.grab());
-                cap.retrieve(element);
-                temp_count_tick = getTickCount();
-                wrt << element;
-                temp_count_tick = getTickCount() - temp_count_tick;
-            }
+inline map<string, string> demuxPluginByContainer()
+{
+    map<string, string> res;
+    res["avi"] = "avidemux";
+    res["mp4"] = "qtdemux";
+    res["mov"] = "qtdemux";
+    res["mkv"] = "matroskademux";
+    return res;
+}
 
-            tick_counts.push_back(static_cast<double>(temp_count_tick));
-            if (((mode == "decode") && fast_measure && (tick_counts.size() > 1e3)) ||
-                ((mode == "encode") && (tick_counts.size() > 3e3)) ||
-                ((mode == "encode") && fast_measure && (tick_counts.size() > 1e2)))
-            { break; }
+inline map<string, string> muxPluginByContainer()
+{
+    map<string, string> res;
+    res["avi"] = "avimux";
+    res["mp4"] = "qtmux";
+    res["mov"] = "qtmux";
+    res["mkv"] = "matroskamux";
+    return res;
+}
 
-        }
-        double time_fps = sum(tick_counts)[0] / getTickFrequency();
+//================================================================================
 
-        if (tick_counts.size() != 0)
-        {
-            cout << "Finished: " << tick_counts.size() << " in " << time_fps <<" sec ~ " ;
-            cout << tick_counts.size() / time_fps <<" fps " << endl;
-        }
-        else
-        {
-            cout << "Failed " << mode << ": " << file_name;
-            cout << " (" << pipeline << ")" << endl;
-            return -1;
-        }
-        return 0;
+inline string containerByName(const string &name)
+{
+    size_t found = name.rfind(".");
+    if (found != string::npos)
+    {
+        return name.substr(found + 1);  // container type
     }
+    return string();
+}
+
+//================================================================================
 
-    // Free video resource
-    void close()
+inline Ptr<VideoCapture> createCapture(const string &backend, const string &file_name, const string &codec)
+{
+    if (backend == "gst-default")
     {
-        cap.release();
-        wrt.release();
+        cout << "Created GStreamer capture ( " << file_name << " )" << endl;
+        return makePtr<VideoCapture>(file_name, CAP_GSTREAMER);
     }
-
- private:
-    // Choose the constructed GStreamer pipeline for decode
-    int createDecodePipeline()
+    else if (backend.find("gst") == 0)
     {
-        if (pipeline == "default") {
-            cap = VideoCapture(file_name, CAP_GSTREAMER);
-        }
-        else if (pipeline.find("gst") == 0)
-        {
-            stream_pipeline << "filesrc location=\"" << file_name << "\"";
-            stream_pipeline << " ! " << getGstMuxPlugin();
-
-            if (pipeline.find("basic") == 4)
-            {
-                stream_pipeline << getGstDefaultCodePlugin();
-            }
-            else if (pipeline.find("vaapi1710") == 4)
-            {
-                stream_pipeline << getGstVaapiCodePlugin();
-            }
-            else if (pipeline.find("libav") == 4)
-            {
-                stream_pipeline << getGstAvCodePlugin();
-            }
-            else
-            {
-                cout << "Unsupported pipeline: " << pipeline << endl;
-                cmd_parser->printErrors();
-                return -1;
-            }
-
-            stream_pipeline << " ! videoconvert n-threads=" << getNumThreads();
-            stream_pipeline << " ! appsink sync=false";
-            cap = VideoCapture(stream_pipeline.str(), CAP_GSTREAMER);
-        }
-        else if (pipeline == "ffmpeg")
-        {
-            cap = VideoCapture(file_name, CAP_FFMPEG);
-            stream_pipeline << "default pipeline for ffmpeg" << endl;
-        }
+        ostringstream line;
+        line << "filesrc location=\"" << file_name << "\"";
+        line << " ! ";
+        line << getValue(demuxPluginByContainer(), containerByName(file_name), "Invalid container");
+        line << " ! ";
+        if (backend.find("basic") == 4)
+            line << "decodebin";
+        else if (backend.find("vaapi") == 4)
+            line << "vaapidecodebin";
+        else if (backend.find("libav") == 4)
+            line << getValue(libavDecodeElementByCodec(), codec, "Invalid codec");
+        else if (backend.find("mfx") == 4)
+            line << getValue(mfxDecodeElementByCodec(), codec, "Invalid or unsupported codec");
         else
-        {
-            cout << "Unsupported pipeline: " << pipeline << endl;
-            cmd_parser->printErrors();
-            return -1;
-        }
-        return 0;
+            return Ptr<VideoCapture>();
+        line << " ! videoconvert n-threads=" << getNumThreads();
+        line << " ! appsink sync=false";
+        cout << "Created GStreamer capture  ( " << line.str() << " )" << endl;
+        return makePtr<VideoCapture>(line.str(), CAP_GSTREAMER);
     }
-
-    // Choose the constructed GStreamer pipeline for encode
-    int createEncodePipeline()
+    else if (backend == "ffmpeg")
     {
-        if (checkConfiguration() < 0) return -1;
-        ostringstream test_pipeline;
-        test_pipeline << "videotestsrc pattern=smpte";
-        test_pipeline << " ! video/x-raw, " << getVideoSettings();
-        test_pipeline << " ! appsink sync=false";
-        cap = VideoCapture(test_pipeline.str(), CAP_GSTREAMER);
-
-        if (pipeline == "default") {
-            wrt = VideoWriter(file_name, CAP_GSTREAMER, getFourccCode(), fix_fps, fix_size, true);
-        }
-        else if (pipeline.find("gst") == 0)
-        {
-            stream_pipeline << "appsrc ! videoconvert n-threads=" << getNumThreads() << " ! ";
+        cout << "Created FFmpeg capture ( " << file_name << " )" << endl;
+        return makePtr<VideoCapture>(file_name, CAP_FFMPEG);
+    }
+    return Ptr<VideoCapture>();
+}
 
-            if (pipeline.find("basic") == 4)
-            {
-                stream_pipeline << getGstDefaultCodePlugin();
-            }
-            else if (pipeline.find("vaapi1710") == 4)
-            {
-                stream_pipeline << getGstVaapiCodePlugin();
-            }
-            else if (pipeline.find("libav") == 4)
-            {
-                stream_pipeline << getGstAvCodePlugin();
-            }
-            else
-            {
-                cout << "Unsupported pipeline: " << pipeline << endl;
-                cmd_parser->printErrors();
-                return -1;
-            }
+inline Ptr<VideoCapture> createSynthSource(Size sz, unsigned fps)
+{
+    ostringstream line;
+    line << "videotestsrc pattern=smpte";
+    line << " ! video/x-raw";
+    line << ",width=" << sz.width << ",height=" << sz.height;
+    if (fps > 0)
+        line << ",framerate=" << fps << "/1";
+    line << " ! appsink sync=false";
+    cout << "Created synthetic video source ( " << line.str() << " )" << endl;
+    return makePtr<VideoCapture>(line.str(), CAP_GSTREAMER);
+}
 
-            stream_pipeline << " ! " << getGstMuxPlugin();
-            stream_pipeline << " ! filesink location=\"" << file_name << "\"";
-            wrt = VideoWriter(stream_pipeline.str(), CAP_GSTREAMER, 0, fix_fps, fix_size, true);
-        }
-        else if (pipeline == "ffmpeg")
-        {
-            wrt = VideoWriter(file_name, CAP_FFMPEG, getFourccCode(), fix_fps, fix_size, true);
-            stream_pipeline << "default pipeline for ffmpeg" << endl;
-        }
-        else
-        {
-            cout << "Unsupported pipeline: " << pipeline << endl;
-            cmd_parser->printErrors();
-            return -1;
-        }
-        return 0;
+inline Ptr<VideoWriter> createWriter(const string &backend, const string &file_name, const string &codec, Size sz, unsigned fps)
+{
+    if (backend == "gst-default")
+    {
+        cout << "Created GStreamer writer ( " << file_name << ", FPS=" << fps << ", Size=" << sz << ")" << endl;
+        return makePtr<VideoWriter>(file_name, CAP_GSTREAMER, getValue(fourccByCodec(), codec, "Invalid codec"), fps, sz, true);
     }
-
-    // Choose video resolution for encoding
-    string getVideoSettings()
+    else if (backend.find("gst") == 0)
     {
-        ostringstream video_size;
-        if (fix_fps > 0) { video_size << "framerate=" << fix_fps << "/1, "; }
-        else
-        {
-            cout << "Unsupported fps (< 0): " << fix_fps << endl;
-            cmd_parser->printErrors();
-            return string();
-        }
-
-        if      (resolution == "720p")  { fix_size = Size(1280, 720);  }
-        else if (resolution == "1080p") { fix_size = Size(1920, 1080); }
-        else if (resolution == "4k")    { fix_size = Size(3840, 2160); }
+        ostringstream line;
+        line << "appsrc ! videoconvert n-threads=" << getNumThreads() << " ! ";
+        if (backend.find("basic") == 4)
+            line << getValue(defaultEncodeElementByCodec(), codec, "Invalid codec");
+        else if (backend.find("vaapi") == 4)
+            line << getValue(VAAPIEncodeElementByCodec(), codec, "Invalid codec");
+        else if (backend.find("libav") == 4)
+            line << getValue(libavEncodeElementByCodec(), codec, "Invalid codec");
+        else if (backend.find("mfx") == 4)
+            line << getValue(mfxEncodeElementByCodec(), codec, "Invalid codec");
         else
-        {
-            cout << "Unsupported video resolution: " << resolution << endl;
-            cmd_parser->printErrors();
-            return string();
-        }
-
-        video_size << "width=" << fix_size.width << ", height=" << fix_size.height;
-        return video_size.str();
+            return Ptr<VideoWriter>();
+        line << " ! ";
+        line << getValue(muxPluginByContainer(), containerByName(file_name), "Invalid container");
+        line << " ! ";
+        line << "filesink location=\"" << file_name << "\"";
+        cout << "Created GStreamer writer ( " << line.str() << " )" << endl;
+        return makePtr<VideoWriter>(line.str(), CAP_GSTREAMER, 0, fps, sz, true);
     }
-
-    // Choose a video container
-    string getGstMuxPlugin()
+    else if (backend == "ffmpeg")
     {
-        ostringstream plugin;
-        if      (container == "avi") { plugin << "avi"; }
-        else if (container == "mp4") { plugin << "qt";  }
-        else if (container == "mov") { plugin << "qt";  }
-        else if (container == "mkv") { plugin << "matroska"; }
-        else
-        {
-            cout << "Unsupported container: " << container << endl;
-            cmd_parser->printErrors();
-            return string();
-        }
+        cout << "Created FFMpeg writer ( " << file_name << ", FPS=" << fps << ", Size=" << sz << " )" << endl;
+        return makePtr<VideoWriter>(file_name, CAP_FFMPEG, getValue(fourccByCodec(), codec, "Invalid codec"), fps, sz, true);
+    }
+    return Ptr<VideoWriter>();
+}
 
-        if      (mode == "decode") { plugin << "demux"; }
-        else if (mode == "encode") { plugin << "mux"; }
-        else
-        {
-            cout << "Unsupported mode: " << mode << endl;
-            cmd_parser->printErrors();
-            return string();
-        }
+//================================================================================
 
-        return plugin.str();
+int main(int argc, char *argv[])
+{
+    const string keys =
+        "{h help usage ? |           | print help messages   }"
+        "{m mode         |decode     | coding mode (supported: encode, decode) }"
+        "{b backend      |default    | video backend (supported: 'gst-default', 'gst-basic', 'gst-vaapi', 'gst-libav', 'gst-mfx', 'ffmpeg') }"
+        "{c codec        |h264       | codec name     (supported: 'h264', 'h265', 'mpeg2', 'mpeg4', 'mjpeg', 'vp8') }"
+        "{f file path    |           | path to file }"
+        "{r resolution   |720p       | video resolution for encoding (supported: '720p', '1080p', '4k') }"
+        "{fps            |30         | fix frame per second for encoding (supported: fps > 0) }"
+        "{fast           |           | fast measure fps }";
+    CommandLineParser cmd_parser(argc, argv, keys);
+    cmd_parser.about("This program measures performance of video encoding and decoding using different backends OpenCV.");
+    if (cmd_parser.has("help"))
+    {
+        cmd_parser.printMessage();
+        return 0;
     }
-
-    // Choose a libav codec
-    string getGstAvCodePlugin()
+    bool fast_measure = cmd_parser.has("fast");               // fast measure fps
+    unsigned fix_fps      = cmd_parser.get<unsigned>("fps");      // fixed frame per second
+    string backend     = cmd_parser.get<string>("backend");   // video backend
+    string mode         = cmd_parser.get<string>("mode");       // coding mode
+    string codec        = cmd_parser.get<string>("codec");      // codec type
+    string file_name    = cmd_parser.get<string>("file");       // path to videofile
+    string resolution   = cmd_parser.get<string>("resolution"); // video resolution
+    if (!cmd_parser.check())
     {
-        ostringstream plugin;
-        if (mode == "decode")
-        {
-            if      (codec == "h264")  { plugin << "h264parse ! "; }
-            else if (codec == "h265")  { plugin << "h265parse ! "; }
-            plugin << "avdec_";
-        }
-        else if (mode == "encode") { plugin << "avenc_"; }
-        else
-        {
-            cout << "Unsupported mode: " << mode << endl;
-            cmd_parser->printErrors();
-            return string();
-        }
-
-        if      (codec == "h264")  { plugin << "h264";       }
-        else if (codec == "h265")  { plugin << "h265";       }
-        else if (codec == "mpeg2") { plugin << "mpeg2video"; }
-        else if (codec == "mpeg4") { plugin << "mpeg4";      }
-        else if (codec == "mjpeg") { plugin << "mjpeg";      }
-        else if (codec == "vp8")   { plugin << "vp8";        }
-        else
-        {
-            cout << "Unsupported libav codec: " << codec << endl;
-            cmd_parser->printErrors();
-            return string();
-        }
-
-        return plugin.str();
+        cmd_parser.printErrors();
+        return -1;
     }
+    if (mode != "encode" && mode != "decode")
+    {
+        cout << "Unsupported mode: " << mode << endl;
+        return -1;
+    }
+    cout << "Mode: " << mode << ", Backend: " << backend << ", File: " << file_name << ", Codec: " << codec << endl;
 
-    // Choose a vaapi codec
-    string getGstVaapiCodePlugin()
+    TickMeter total;
+    Ptr<VideoCapture> cap;
+    Ptr<VideoWriter> wrt;
+    try
     {
-        ostringstream plugin;
         if (mode == "decode")
         {
-            plugin << "vaapidecodebin";
-            if (container == "mkv") { plugin << " ! autovideoconvert"; }
-            else { plugin << " ! video/x-raw, format=YV12"; }
+            cap = createCapture(backend, file_name, codec);
+            if (!cap)
+            {
+                cout << "Failed to create video capture" << endl;
+                return -3;
+            }
+            if (!cap->isOpened())
+            {
+                cout << "Capture is not opened" << endl;
+                return -4;
+            }
         }
         else if (mode == "encode")
         {
-            if      (codec == "h264")     { plugin << "vaapih264enc";  }
-            else if (codec == "h265")     { plugin << "vaapih265enc";  }
-            else if (codec == "mpeg2")    { plugin << "vaapimpeg2enc"; }
-            else if (codec == "mjpeg")    { plugin << "vaapijpegenc";  }
-            else if (codec == "vp8")      { plugin << "vaapivp8enc";   }
-            else
+            Size sz = getValue(sizeByResolution(), resolution, "Invalid resolution");
+            cout << "FPS: " << fix_fps << ", Frame size: " << sz << endl;
+            cap = createSynthSource(sz, fix_fps);
+            wrt = createWriter(backend, file_name, codec, sz, fix_fps);
+            if (!cap || !wrt)
             {
-                cout << "Unsupported vaapi codec: " << codec << endl;
-                cmd_parser->printErrors();
-                return string();
+                cout << "Failed to create synthetic video source or video writer" << endl;
+                return -3;
+            }
+            if (!cap->isOpened() || !wrt->isOpened())
+            {
+                cout << "Synthetic video source or video writer is not opened" << endl;
+                return -4;
             }
         }
-        else
-        {
-            cout << "Unsupported mode: " << resolution << endl;
-            cmd_parser->printErrors();
-            return string();
-        }
-        return plugin.str();
+    }
+    catch (...)
+    {
+        cout << "Unsupported parameters" << endl;
+        return -2;
     }
 
-    // Choose a default codec
-    string getGstDefaultCodePlugin()
+    TickMeter tick;
+    Mat frame;
+    Mat element;
+    total.start();
+    while(true)
     {
-        ostringstream plugin;
         if (mode == "decode")
         {
-            plugin << " ! decodebin";
+            tick.start();
+            if (!cap->grab())
+            {
+                cout << "No more frames - break" << endl;
+                break;
+            }
+            if (!cap->retrieve(frame))
+            {
+                cout << "Failed to retrieve frame - break" << endl;
+                break;
+            }
+            if (frame.empty())
+            {
+                cout << "Empty frame received - break" << endl;
+                break;
+            }
+            tick.stop();
         }
         else if (mode == "encode")
         {
-            if      (codec == "h264")     { plugin << "x264enc";  }
-            else if (codec == "h265")     { plugin << "x265enc";  }
-            else if (codec == "mpeg2")    { plugin << "mpeg2enc"; }
-            else if (codec == "mjpeg")    { plugin << "jpegenc";  }
-            else if (codec == "vp8")      { plugin << "vp8enc";   }
-            else
+            int limit = 100;
+            while (!cap->grab() && --limit != 0)
             {
-                cout << "Unsupported default codec: " << codec << endl;
-                cmd_parser->printErrors();
-                return string();
+                cout << "Skipping empty input frame - " << limit << endl;
             }
+            cap->retrieve(element);
+            tick.start();
+            *wrt << element;
+            tick.stop();
         }
-        else
-        {
-            cout << "Unsupported mode: " << resolution << endl;
-            cmd_parser->printErrors();
-            return string();
-        }
-        return plugin.str();
-    }
-    // Get fourcc for codec
-    int getFourccCode()
-    {
-        if      (codec == "h264")  { return VideoWriter::fourcc('H','2','6','4'); }
-        else if (codec == "h265")  { return VideoWriter::fourcc('H','E','V','C'); }
-        else if (codec == "mpeg2") { return VideoWriter::fourcc('M','P','E','G'); }
-        else if (codec == "mpeg4") { return VideoWriter::fourcc('M','P','4','2'); }
-        else if (codec == "mjpeg") { return VideoWriter::fourcc('M','J','P','G'); }
-        else if (codec == "vp8")   { return VideoWriter::fourcc('V','P','8','0'); }
-        else
+
+        if (fast_measure && tick.getCounter() >= 1000)
         {
-            cout << "Unsupported ffmpeg codec: " << codec << endl;
-            cmd_parser->printErrors();
-            return 0;
+            cout << "Fast mode frame limit reached - break" << endl;
+            break;
         }
-    }
-
-    // Check bad configuration
-    int checkConfiguration()
-    {
-        if ((codec == "mpeg2" && getGstMuxPlugin() == "qtmux")  ||
-            (codec == "h265"  && getGstMuxPlugin() == "avimux") ||
-            (pipeline == "gst-libav" && (codec == "h264" || codec == "h265"))   ||
-            (pipeline == "gst-vaapi1710" && codec=="mpeg2" && resolution=="4k") ||
-            (pipeline == "gst-vaapi1710" && codec=="mpeg2" && resolution=="1080p" && fix_fps > 30))
+        if (mode == "encode" && tick.getCounter() >= 1000)
         {
-            cout << "Unsupported configuration" << endl;
-            cmd_parser->printErrors();
-            return -1;
+            cout << "Encode frame limit reached - break" << endl;
+            break;
         }
-        return 0;
     }
-
-    bool   fast_measure;     // fast measure fps
-    string pipeline,         // gstreamer pipeline type
-           container,        // container type
-           mode,             // coding mode
-           codec,            // codec type
-           file_name,        // path to videofile
-           resolution;       // video resolution
-    int    fix_fps;          // fixed frame per second
-    Size   fix_size;         // fixed frame size
-    VideoWriter  wrt;
-    VideoCapture cap;
-    ostringstream stream_pipeline;
-    CommandLineParser* cmd_parser;
-};
-
-int main(int argc, char *argv[])
-{
-    try
+    total.stop();
+    if (tick.getCounter() == 0)
     {
-        GStreamerPipeline pipe(argc, argv);
-        return pipe.run();
+        cout << "No frames have been processed" << endl;
+        return -10;
     }
-    catch(const Exception& e)
+    else
     {
-        cerr << e.what() << endl;
-        return 1;
+        double res_fps = tick.getCounter() / tick.getTimeSec();
+        cout << tick.getCounter() << " frames in " << tick.getTimeSec() << " sec ~ " << res_fps << " FPS" << " (total time: " << total.getTimeSec() << " sec)" << endl;
     }
+    return 0;
 }