Commit 1367a58b authored by Alexander Nesterov's avatar Alexander Nesterov

Added encode-pipeline to sample

parent 9615f8c9
...@@ -8,144 +8,430 @@ ...@@ -8,144 +8,430 @@
using namespace std; using namespace std;
using namespace cv; using namespace cv;
string getGstDemuxPlugin(string container); class GStreamerPipeline
string getGstAvDecodePlugin(string codec);
int main(int argc, char *argv[])
{ {
const string keys = public:
"{h help usage ? | | print help messages }" // Preprocessing arguments command line
"{p pipeline |gst-default| pipeline name (supported: 'gst-default', 'gst-vaapi', 'gst-libav', 'ffmpeg') }" GStreamerPipeline(int argc, char *argv[])
"{ct container |mp4 | container name (supported: 'mp4', 'mov', 'avi', 'mkv') }" {
"{cd codec |h264 | codec name (supported: 'h264', 'h265', 'mpeg2', 'mpeg4', 'mjpeg', 'vp8') }" const string keys =
"{f file path | | path to file }" "{h help usage ? | | print help messages }"
"{fm fast | | fast measure fps }"; "{m mode | | coding mode (supported: encode, decode) }"
"{p pipeline |default | pipeline name (supported: 'default', 'gst-basic', 'gst-vaapi', 'gst-libav', 'ffmpeg') }"
"{ct container |mp4 | container name (supported: 'mp4', 'mov', 'avi', 'mkv') }"
"{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.");
if (cmd_parser->has("help"))
{
cmd_parser->printMessage();
exit_code = -1;
}
CommandLineParser parser(argc, argv, keys); 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
container = cmd_parser->get<string>("container"), // container 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
if (!cmd_parser->check())
{
cmd_parser->printErrors();
exit_code = -1;
}
exit_code = 0;
}
parser.about("This program shows how to read a video file with GStreamer pipeline with OpenCV."); ~GStreamerPipeline() { delete cmd_parser; }
if (parser.has("help")) // Start pipeline
int run()
{ {
parser.printMessage(); if (exit_code < 0) { return exit_code; }
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;
vector<double> tick_counts;
cout << "Start " << mode << ": " << file_name;
cout << " (" << pipeline << ")" << endl;
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;
}
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; }
}
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; return 0;
} }
bool arg_fast_measure = parser.has("fast"); // fast measure fps // Free video resource
string arg_pipeline = parser.get<string>("pipeline"), // GStreamer pipeline type void close()
arg_container = parser.get<string>("container"), // container type {
arg_codec = parser.get<string>("codec"), // codec type cap.release();
arg_file_name = parser.get<string>("file"); // path to videofile wrt.release();
VideoCapture cap; }
if (!parser.check()) private:
// Choose the constructed GStreamer pipeline for decode
int createDecodePipeline()
{ {
parser.printErrors(); 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;
}
else
{
cout << "Unsupported pipeline: " << pipeline << endl;
cmd_parser->printErrors();
return -1;
}
return 0; return 0;
} }
// Choose the constructed GStreamer pipeline // Choose the constructed GStreamer pipeline for encode
if (arg_pipeline.find("gst") == 0) int createEncodePipeline()
{ {
ostringstream pipeline; if (checkConfiguration() < 0) return -1;
pipeline << "filesrc location=\"" << arg_file_name << "\""; ostringstream test_pipeline;
pipeline << " ! " << getGstDemuxPlugin(arg_container); test_pipeline << "videotestsrc pattern=smpte";
test_pipeline << " ! video/x-raw, " << getVideoSettings();
test_pipeline << " ! appsink sync=false";
cap = VideoCapture(test_pipeline.str(), CAP_GSTREAMER);
if (arg_pipeline.find("default") == 4) { if (pipeline == "default") {
pipeline << " ! decodebin"; wrt = VideoWriter(file_name, CAP_GSTREAMER, getFourccCode(), fix_fps, fix_size, true);
} }
else if (arg_pipeline.find("vaapi1710") == 4) else if (pipeline.find("gst") == 0)
{ {
pipeline << " ! vaapidecodebin"; stream_pipeline << "appsrc ! videoconvert n-threads=" << getNumThreads() << " ! ";
if (arg_container == "mkv")
if (pipeline.find("basic") == 4)
{
stream_pipeline << getGstDefaultCodePlugin();
}
else if (pipeline.find("vaapi1710") == 4)
{ {
pipeline << " ! autovideoconvert"; stream_pipeline << getGstVaapiCodePlugin();
}
else if (pipeline.find("libav") == 4)
{
stream_pipeline << getGstAvCodePlugin();
} }
else else
{ {
pipeline << " ! video/x-raw, format=YV12"; cout << "Unsupported pipeline: " << pipeline << endl;
cmd_parser->printErrors();
return -1;
} }
stream_pipeline << " ! " << getGstMuxPlugin();
stream_pipeline << " ! filesink location=\"" << file_name << "\"";
wrt = VideoWriter(stream_pipeline.str(), CAP_GSTREAMER, 0, fix_fps, fix_size, true);
} }
else if (arg_pipeline.find("libav") == 4) else if (pipeline == "ffmpeg")
{ {
pipeline << " ! " << getGstAvDecodePlugin(arg_codec); wrt = VideoWriter(file_name, CAP_FFMPEG, getFourccCode(), fix_fps, fix_size, true);
stream_pipeline << "default pipeline for ffmpeg" << endl;
} }
else else
{ {
parser.printMessage(); cout << "Unsupported pipeline: " << pipeline << endl;
cout << "Unsupported pipeline: " << arg_pipeline << endl; cmd_parser->printErrors();
return -4; return -1;
} }
return 0;
pipeline << " ! videoconvert";
pipeline << " n-threads=" << getNumThreads();
pipeline << " ! appsink sync=false";
cap = VideoCapture(pipeline.str(), CAP_GSTREAMER);
} }
else if (arg_pipeline == "ffmpeg")
// Choose video resolution for encoding
string getVideoSettings()
{ {
cap = VideoCapture(arg_file_name, CAP_FFMPEG); 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); }
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();
} }
else
// Choose a video container
string getGstMuxPlugin()
{ {
parser.printMessage(); ostringstream plugin;
cout << "Unsupported pipeline: " << arg_pipeline << endl; if (container == "avi") { plugin << "avi"; }
return -4; 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();
}
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();
} }
// Choose a show video or only measure fps // Choose a libav codec
cout << "_____________________________________" << '\n'; string getGstAvCodePlugin()
cout << "Start measure frame per seconds (fps)" << '\n'; {
cout << "Loading ..." << '\n'; 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();
}
Mat frame; if (codec == "h264") { plugin << "h264"; }
vector<double> tick_counts; 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();
}
cout << "Start decoding: " << arg_file_name; return plugin.str();
cout << " (" << arg_pipeline << ")" << endl; }
while(true) // Choose a vaapi codec
string getGstVaapiCodePlugin()
{ {
int64 temp_count_tick = getTickCount(); ostringstream plugin;
cap >> frame; if (mode == "decode")
temp_count_tick = getTickCount() - temp_count_tick; {
if (frame.empty()) { break; } plugin << "vaapidecodebin";
tick_counts.push_back(static_cast<double>(temp_count_tick)); if (container == "mkv") { plugin << " ! autovideoconvert"; }
if (arg_fast_measure && (tick_counts.size() > 1000)) { break; } else { plugin << " ! video/x-raw, format=YV12"; }
}
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
{
cout << "Unsupported vaapi codec: " << codec << endl;
cmd_parser->printErrors();
return string();
}
}
else
{
cout << "Unsupported mode: " << resolution << endl;
cmd_parser->printErrors();
return string();
}
return plugin.str();
} }
double time_fps = sum(tick_counts)[0] / getTickFrequency();
if (tick_counts.size() != 0) // Choose a default codec
string getGstDefaultCodePlugin()
{
ostringstream plugin;
if (mode == "decode")
{
plugin << " ! decodebin";
}
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
{
cout << "Unsupported default codec: " << codec << endl;
cmd_parser->printErrors();
return string();
}
}
else
{
cout << "Unsupported mode: " << resolution << endl;
cmd_parser->printErrors();
return string();
}
return plugin.str();
}
// Get fourcc for codec
int getFourccCode()
{ {
cout << "Finished: " << tick_counts.size() << " in " << time_fps <<" sec ~ " ; if (codec == "h264") { return VideoWriter::fourcc('H','2','6','4'); }
cout << tick_counts.size() / time_fps <<" fps " << endl; 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
{
cout << "Unsupported ffmpeg codec: " << codec << endl;
cmd_parser->printErrors();
return 0;
}
} }
else
// Check bad configuration
int checkConfiguration()
{ {
cout << "Failed decoding: " << arg_file_name; if ((codec == "mpeg2" && getGstMuxPlugin() == "qtmux") ||
cout << " (" << arg_pipeline << ")" << endl; (codec == "h265" && getGstMuxPlugin() == "avimux") ||
return -5; (pipeline == "gst-libav" && (codec == "h264" || codec == "h265")) ||
(pipeline == "gst-vaapi1710" && codec=="mpeg2" && resolution=="4k") ||
(pipeline == "gst-vaapi1710" && codec=="mpeg2" && resolution=="1080p" && fix_fps > 30))
{
cout << "Unsupported configuration" << endl;
cmd_parser->printErrors();
return -1;
}
return 0;
} }
return 0;
}
// Choose a video container bool fast_measure; // fast measure fps
string getGstDemuxPlugin(string container) { string pipeline, // gstreamer pipeline type
if (container == "avi") { return "avidemux"; } container, // container type
else if (container == "mp4") { return "qtdemux"; } mode, // coding mode
else if (container == "mov") { return "qtdemux"; } codec, // codec type
else if (container == "mkv") { return "matroskademux"; } file_name, // path to videofile
return string(); resolution; // video resolution
} int fix_fps; // fixed frame per second
Size fix_size; // fixed frame size
int exit_code;
VideoWriter wrt;
VideoCapture cap;
ostringstream stream_pipeline;
CommandLineParser* cmd_parser;
};
// Choose a codec int main(int argc, char *argv[])
string getGstAvDecodePlugin(string codec) { {
if (codec == "h264") { return "h264parse ! avdec_h264"; } GStreamerPipeline pipe(argc, argv);
else if (codec == "h265") { return "h265parse ! avdec_h265"; } return pipe.run();
else if (codec == "mpeg2") { return "avdec_mpeg2video"; }
else if (codec == "mpeg4") { return "avdec_mpeg4"; }
else if (codec == "mjpeg") { return "avdec_mjpeg"; }
else if (codec == "vp8") { return "avdec_vp8"; }
return string();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment