Skip to content

Commit cc862e9

Browse files
committed
videoio: fixes for GStreamer support
- emulated frame counter (with autodetection of GStreamer broken behavior) - skip 'seek' tests if seeking is not supported by backend - update 'fps' and total frames checks (increase error tolerance) - update synthetic image generation
1 parent f670a99 commit cc862e9

File tree

4 files changed

+195
-55
lines changed

4 files changed

+195
-55
lines changed

modules/videoio/src/cap_gstreamer.cpp

Lines changed: 115 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ class CvCapture_GStreamer : public CvCapture
168168
gint width;
169169
gint height;
170170
double fps;
171+
172+
bool isPosFramesSupported;
173+
bool isPosFramesEmulated;
174+
gint64 emulatedFrameNumber;
171175
};
172176

173177
/*!
@@ -191,6 +195,10 @@ void CvCapture_GStreamer::init()
191195
width = -1;
192196
height = -1;
193197
fps = -1;
198+
199+
isPosFramesSupported = false;
200+
isPosFramesEmulated = false;
201+
emulatedFrameNumber = -1;
194202
}
195203

196204
/*!
@@ -212,6 +220,9 @@ void CvCapture_GStreamer::close()
212220
width = -1;
213221
height = -1;
214222
fps = -1;
223+
isPosFramesSupported = false;
224+
isPosFramesEmulated = false;
225+
emulatedFrameNumber = -1;
215226
}
216227

217228
/*!
@@ -253,6 +264,9 @@ bool CvCapture_GStreamer::grabFrame()
253264
if(!buffer)
254265
return false;
255266

267+
if (isPosFramesEmulated)
268+
emulatedFrameNumber++;
269+
256270
return true;
257271
}
258272

@@ -408,6 +422,9 @@ void CvCapture_GStreamer::startPipeline()
408422
return;
409423
}
410424

425+
if (isPosFramesEmulated)
426+
emulatedFrameNumber = 0;
427+
411428
//printf("state now playing\n");
412429
handleMessage(pipeline);
413430
__END__;
@@ -847,6 +864,8 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
847864
duration = -1;
848865
}
849866

867+
handleMessage(pipeline);
868+
850869
GstPad* pad = gst_element_get_static_pad(sink, "sink");
851870
#if GST_VERSION_MAJOR == 0
852871
GstCaps* buffer_caps = gst_pad_get_caps(pad);
@@ -873,9 +892,32 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
873892

874893
fps = (double)num/(double)denom;
875894

876-
// GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pipeline")
877-
if (file)
878-
stopPipeline();
895+
{
896+
GstFormat format_;
897+
gint64 value_ = -1;
898+
gboolean status_;
899+
900+
format_ = GST_FORMAT_DEFAULT;
901+
#if GST_VERSION_MAJOR == 0
902+
#define FORMAT &format_
903+
#else
904+
#define FORMAT format_
905+
#endif
906+
status_ = gst_element_query_position(pipeline, FORMAT, &value_);
907+
#undef FORMAT
908+
if (!status_ || value_ != 0 || duration < 0)
909+
{
910+
CV_WARN(cv::format("Cannot query video position: status=%d value=%lld duration=%lld\n",
911+
(int)status_, (long long int)value_, (long long int)duration).c_str());
912+
isPosFramesSupported = false;
913+
isPosFramesEmulated = true;
914+
emulatedFrameNumber = 0;
915+
}
916+
else
917+
isPosFramesSupported = true;
918+
}
919+
920+
GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pipeline");
879921
}
880922

881923
__END__;
@@ -914,14 +956,22 @@ double CvCapture_GStreamer::getProperty( int propId ) const
914956
format = GST_FORMAT_TIME;
915957
status = gst_element_query_position(sink, FORMAT, &value);
916958
if(!status) {
959+
handleMessage(pipeline);
917960
CV_WARN("GStreamer: unable to query position of stream");
918961
return 0;
919962
}
920963
return value * 1e-6; // nano seconds to milli seconds
921964
case CV_CAP_PROP_POS_FRAMES:
965+
if (!isPosFramesSupported)
966+
{
967+
if (isPosFramesEmulated)
968+
return emulatedFrameNumber;
969+
return 0; // TODO getProperty() "unsupported" value should be changed
970+
}
922971
format = GST_FORMAT_DEFAULT;
923972
status = gst_element_query_position(sink, FORMAT, &value);
924973
if(!status) {
974+
handleMessage(pipeline);
925975
CV_WARN("GStreamer: unable to query position of stream");
926976
return 0;
927977
}
@@ -930,6 +980,7 @@ double CvCapture_GStreamer::getProperty( int propId ) const
930980
format = GST_FORMAT_PERCENT;
931981
status = gst_element_query_position(sink, FORMAT, &value);
932982
if(!status) {
983+
handleMessage(pipeline);
933984
CV_WARN("GStreamer: unable to query position of stream");
934985
return 0;
935986
}
@@ -1013,24 +1064,75 @@ bool CvCapture_GStreamer::setProperty( int propId, double value )
10131064
flags = (GstSeekFlags) (GST_SEEK_FLAG_FLUSH|GST_SEEK_FLAG_ACCURATE);
10141065
if(!gst_element_seek_simple(GST_ELEMENT(pipeline), format,
10151066
flags, (gint64) (value * GST_MSECOND))) {
1067+
handleMessage(pipeline);
10161068
CV_WARN("GStreamer: unable to seek");
10171069
}
1070+
else
1071+
{
1072+
if (isPosFramesEmulated)
1073+
{
1074+
if (value == 0)
1075+
{
1076+
emulatedFrameNumber = 0;
1077+
return true;
1078+
}
1079+
else
1080+
{
1081+
isPosFramesEmulated = false; // reset frame counter emulation
1082+
}
1083+
}
1084+
}
10181085
break;
10191086
case CV_CAP_PROP_POS_FRAMES:
1087+
{
1088+
if (!isPosFramesSupported)
1089+
{
1090+
if (isPosFramesEmulated)
1091+
{
1092+
if (value == 0)
1093+
{
1094+
restartPipeline();
1095+
emulatedFrameNumber = 0;
1096+
return true;
1097+
}
1098+
}
1099+
return false;
1100+
}
10201101
format = GST_FORMAT_DEFAULT;
10211102
flags = (GstSeekFlags) (GST_SEEK_FLAG_FLUSH|GST_SEEK_FLAG_ACCURATE);
10221103
if(!gst_element_seek_simple(GST_ELEMENT(pipeline), format,
10231104
flags, (gint64) value)) {
1105+
handleMessage(pipeline);
10241106
CV_WARN("GStreamer: unable to seek");
1107+
break;
10251108
}
1026-
break;
1109+
// wait for status update
1110+
gst_element_get_state(pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
1111+
return true;
1112+
}
10271113
case CV_CAP_PROP_POS_AVI_RATIO:
10281114
format = GST_FORMAT_PERCENT;
10291115
flags = (GstSeekFlags) (GST_SEEK_FLAG_FLUSH|GST_SEEK_FLAG_ACCURATE);
10301116
if(!gst_element_seek_simple(GST_ELEMENT(pipeline), format,
10311117
flags, (gint64) (value * GST_FORMAT_PERCENT_MAX))) {
1118+
handleMessage(pipeline);
10321119
CV_WARN("GStreamer: unable to seek");
10331120
}
1121+
else
1122+
{
1123+
if (isPosFramesEmulated)
1124+
{
1125+
if (value == 0)
1126+
{
1127+
emulatedFrameNumber = 0;
1128+
return true;
1129+
}
1130+
else
1131+
{
1132+
isPosFramesEmulated = false; // reset frame counter emulation
1133+
}
1134+
}
1135+
}
10341136
break;
10351137
case CV_CAP_PROP_FRAME_WIDTH:
10361138
if(value > 0)
@@ -1719,7 +1821,7 @@ void handleMessage(GstElement * pipeline)
17191821
while(gst_bus_have_pending(bus)) {
17201822
msg = gst_bus_pop(bus);
17211823

1722-
//printf("Got %s message\n", GST_MESSAGE_TYPE_NAME(msg));
1824+
//printf("\t\tGot %s message\n", GST_MESSAGE_TYPE_NAME(msg));
17231825

17241826
if(gst_is_missing_plugin_message(msg))
17251827
{
@@ -1731,28 +1833,30 @@ void handleMessage(GstElement * pipeline)
17311833
case GST_MESSAGE_STATE_CHANGED:
17321834
GstState oldstate, newstate, pendstate;
17331835
gst_message_parse_state_changed(msg, &oldstate, &newstate, &pendstate);
1734-
//fprintf(stderr, "state changed from %s to %s (pending: %s)\n", gst_element_state_get_name(oldstate),
1836+
//fprintf(stderr, "\t\t%s: state changed from %s to %s (pending: %s)\n",
1837+
// gst_element_get_name(GST_MESSAGE_SRC (msg)),
1838+
// gst_element_state_get_name(oldstate),
17351839
// gst_element_state_get_name(newstate), gst_element_state_get_name(pendstate));
17361840
break;
17371841
case GST_MESSAGE_ERROR:
17381842
gst_message_parse_error(msg, &err, &debug);
1739-
fprintf(stderr, "GStreamer Plugin: Embedded video playback halted; module %s reported: %s\n",
1740-
gst_element_get_name(GST_MESSAGE_SRC (msg)), err->message);
1843+
//fprintf(stderr, "\t\tGStreamer Plugin: Embedded video playback halted; module %s reported: %s\n",
1844+
// gst_element_get_name(GST_MESSAGE_SRC (msg)), err->message);
17411845

17421846
g_error_free(err);
17431847
g_free(debug);
17441848

17451849
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL);
17461850
break;
17471851
case GST_MESSAGE_EOS:
1748-
//fprintf(stderr, "reached the end of the stream.");
1852+
//fprintf(stderr, "\t\treached the end of the stream.");
17491853
break;
17501854
case GST_MESSAGE_STREAM_STATUS:
17511855
gst_message_parse_stream_status(msg,&tp,&elem);
1752-
//fprintf(stderr, "stream status: elem %s, %i\n", GST_ELEMENT_NAME(elem), tp);
1856+
//fprintf(stderr, "\t\tstream status: elem %s, %i\n", GST_ELEMENT_NAME(elem), tp);
17531857
break;
17541858
default:
1755-
//fprintf(stderr, "unhandled message %s\n",GST_MESSAGE_TYPE_NAME(msg));
1859+
//fprintf(stderr, "\t\tunhandled message %s\n",GST_MESSAGE_TYPE_NAME(msg));
17561860
break;
17571861
}
17581862
}

modules/videoio/test/test_mfx.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,7 @@ const int FRAME_COUNT = 20;
7171

7272
inline void generateFrame(int i, Mat & frame)
7373
{
74-
frame = 0;
75-
ostringstream buf; buf << "Frame " << setw(2) << setfill('0') << i + 1;
76-
int baseLine = 0;
77-
Size box = getTextSize(buf.str(), FONT_HERSHEY_COMPLEX, 2, 5, &baseLine);
78-
putText(frame, buf.str(), Point((frame.cols - box.width) / 2, (frame.rows - box.height) / 2 + baseLine),
79-
FONT_HERSHEY_COMPLEX, 2, Scalar(255, 255, 255), 5, LINE_AA);
80-
Point p(i * frame.cols / (FRAME_COUNT - 1), i * frame.rows / (FRAME_COUNT - 1));
81-
circle(frame, p, 20, Scalar(200, 25, 55), 5, LINE_AA);
74+
generateFrame(i, FRAME_COUNT, frame);
8275
}
8376

8477
inline int fourccByExt(const String &ext)

modules/videoio/test/test_precomp.hpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,20 @@ inline void generateFrame(int i, int FRAME_COUNT, cv::Mat & frame)
3333
{
3434
using namespace cv;
3535
using namespace std;
36-
frame = Scalar(30, 140, 10);
36+
int offset = (((i * 5) % FRAME_COUNT) - FRAME_COUNT / 2) * (frame.cols / 2) / FRAME_COUNT;
37+
frame(cv::Rect(0, 0, frame.cols / 2 + offset, frame.rows)) = Scalar(255, 255, 255);
38+
frame(cv::Rect(frame.cols / 2 + offset, 0, frame.cols - frame.cols / 2 - offset, frame.rows)) = Scalar(0, 0, 0);
3739
ostringstream buf; buf << "Frame " << setw(2) << setfill('0') << i + 1;
3840
int baseLine = 0;
3941
Size box = getTextSize(buf.str(), FONT_HERSHEY_COMPLEX, 2, 5, &baseLine);
4042
putText(frame, buf.str(), Point((frame.cols - box.width) / 2, (frame.rows - box.height) / 2 + baseLine),
41-
FONT_HERSHEY_COMPLEX, 2, Scalar(255, 255, 255), 5, LINE_AA);
43+
FONT_HERSHEY_COMPLEX, 2, Scalar(0, 0, 255), 5, LINE_AA);
4244
Point p(i * frame.cols / (FRAME_COUNT - 1), i * frame.rows / (FRAME_COUNT - 1));
43-
circle(frame, p, 20, Scalar(200, 25, 55), 5, LINE_AA);
45+
circle(frame, p, 50, Scalar(200, 25, 55), 8, LINE_AA);
46+
#if 0
47+
imshow("frame", frame);
48+
waitKey();
49+
#endif
4450
}
4551

4652
#endif

0 commit comments

Comments
 (0)