Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
db48f7b5
Commit
db48f7b5
authored
Jun 27, 2018
by
Vadim Pisarevsky
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #11804 from mshabunin:gst-sample
parents
75ee536d
fe20fa83
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
301 additions
and
372 deletions
+301
-372
gstreamer_pipeline.cpp
samples/cpp/gstreamer_pipeline.cpp
+301
-372
No files found.
samples/cpp/gstreamer_pipeline.cpp
View file @
db48f7b5
...
...
@@ -4,444 +4,373 @@
#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"
)
{
c
ap
.
release
()
;
wrt
.
release
(
);
c
out
<<
"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
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment