Skip to content

Commit 1a4c22f

Browse files
committed
Merge pull request opencv#9095 from alalek:fix_gstreamer
2 parents 5f4c737 + cc862e9 commit 1a4c22f

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

@@ -428,6 +442,9 @@ void CvCapture_GStreamer::startPipeline()
428442
return;
429443
}
430444

445+
if (isPosFramesEmulated)
446+
emulatedFrameNumber = 0;
447+
431448
//printf("state now playing\n");
432449
handleMessage(pipeline);
433450
__END__;
@@ -879,6 +896,8 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
879896
duration = -1;
880897
}
881898

899+
handleMessage(pipeline);
900+
882901
GstPad* pad = gst_element_get_static_pad(sink, "sink");
883902
#if GST_VERSION_MAJOR == 0
884903
GstCaps* buffer_caps = gst_pad_get_caps(pad);
@@ -905,9 +924,32 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
905924

906925
fps = (double)num/(double)denom;
907926

908-
// GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pipeline")
909-
if (file)
910-
stopPipeline();
927+
{
928+
GstFormat format_;
929+
gint64 value_ = -1;
930+
gboolean status_;
931+
932+
format_ = GST_FORMAT_DEFAULT;
933+
#if GST_VERSION_MAJOR == 0
934+
#define FORMAT &format_
935+
#else
936+
#define FORMAT format_
937+
#endif
938+
status_ = gst_element_query_position(pipeline, FORMAT, &value_);
939+
#undef FORMAT
940+
if (!status_ || value_ != 0 || duration < 0)
941+
{
942+
CV_WARN(cv::format("Cannot query video position: status=%d value=%lld duration=%lld\n",
943+
(int)status_, (long long int)value_, (long long int)duration).c_str());
944+
isPosFramesSupported = false;
945+
isPosFramesEmulated = true;
946+
emulatedFrameNumber = 0;
947+
}
948+
else
949+
isPosFramesSupported = true;
950+
}
951+
952+
GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pipeline");
911953
}
912954

913955
__END__;
@@ -946,14 +988,22 @@ double CvCapture_GStreamer::getProperty( int propId ) const
946988
format = GST_FORMAT_TIME;
947989
status = gst_element_query_position(sink, FORMAT, &value);
948990
if(!status) {
991+
handleMessage(pipeline);
949992
CV_WARN("GStreamer: unable to query position of stream");
950993
return 0;
951994
}
952995
return value * 1e-6; // nano seconds to milli seconds
953996
case CV_CAP_PROP_POS_FRAMES:
997+
if (!isPosFramesSupported)
998+
{
999+
if (isPosFramesEmulated)
1000+
return emulatedFrameNumber;
1001+
return 0; // TODO getProperty() "unsupported" value should be changed
1002+
}
9541003
format = GST_FORMAT_DEFAULT;
9551004
status = gst_element_query_position(sink, FORMAT, &value);
9561005
if(!status) {
1006+
handleMessage(pipeline);
9571007
CV_WARN("GStreamer: unable to query position of stream");
9581008
return 0;
9591009
}
@@ -962,6 +1012,7 @@ double CvCapture_GStreamer::getProperty( int propId ) const
9621012
format = GST_FORMAT_PERCENT;
9631013
status = gst_element_query_position(sink, FORMAT, &value);
9641014
if(!status) {
1015+
handleMessage(pipeline);
9651016
CV_WARN("GStreamer: unable to query position of stream");
9661017
return 0;
9671018
}
@@ -1045,24 +1096,75 @@ bool CvCapture_GStreamer::setProperty( int propId, double value )
10451096
flags = (GstSeekFlags) (GST_SEEK_FLAG_FLUSH|GST_SEEK_FLAG_ACCURATE);
10461097
if(!gst_element_seek_simple(GST_ELEMENT(pipeline), format,
10471098
flags, (gint64) (value * GST_MSECOND))) {
1099+
handleMessage(pipeline);
10481100
CV_WARN("GStreamer: unable to seek");
10491101
}
1102+
else
1103+
{
1104+
if (isPosFramesEmulated)
1105+
{
1106+
if (value == 0)
1107+
{
1108+
emulatedFrameNumber = 0;
1109+
return true;
1110+
}
1111+
else
1112+
{
1113+
isPosFramesEmulated = false; // reset frame counter emulation
1114+
}
1115+
}
1116+
}
10501117
break;
10511118
case CV_CAP_PROP_POS_FRAMES:
1119+
{
1120+
if (!isPosFramesSupported)
1121+
{
1122+
if (isPosFramesEmulated)
1123+
{
1124+
if (value == 0)
1125+
{
1126+
restartPipeline();
1127+
emulatedFrameNumber = 0;
1128+
return true;
1129+
}
1130+
}
1131+
return false;
1132+
}
10521133
format = GST_FORMAT_DEFAULT;
10531134
flags = (GstSeekFlags) (GST_SEEK_FLAG_FLUSH|GST_SEEK_FLAG_ACCURATE);
10541135
if(!gst_element_seek_simple(GST_ELEMENT(pipeline), format,
10551136
flags, (gint64) value)) {
1137+
handleMessage(pipeline);
10561138
CV_WARN("GStreamer: unable to seek");
1139+
break;
10571140
}
1058-
break;
1141+
// wait for status update
1142+
gst_element_get_state(pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
1143+
return true;
1144+
}
10591145
case CV_CAP_PROP_POS_AVI_RATIO:
10601146
format = GST_FORMAT_PERCENT;
10611147
flags = (GstSeekFlags) (GST_SEEK_FLAG_FLUSH|GST_SEEK_FLAG_ACCURATE);
10621148
if(!gst_element_seek_simple(GST_ELEMENT(pipeline), format,
10631149
flags, (gint64) (value * GST_FORMAT_PERCENT_MAX))) {
1150+
handleMessage(pipeline);
10641151
CV_WARN("GStreamer: unable to seek");
10651152
}
1153+
else
1154+
{
1155+
if (isPosFramesEmulated)
1156+
{
1157+
if (value == 0)
1158+
{
1159+
emulatedFrameNumber = 0;
1160+
return true;
1161+
}
1162+
else
1163+
{
1164+
isPosFramesEmulated = false; // reset frame counter emulation
1165+
}
1166+
}
1167+
}
10661168
break;
10671169
case CV_CAP_PROP_FRAME_WIDTH:
10681170
if(value > 0)
@@ -1751,7 +1853,7 @@ void handleMessage(GstElement * pipeline)
17511853
while(gst_bus_have_pending(bus)) {
17521854
msg = gst_bus_pop(bus);
17531855

1754-
//printf("Got %s message\n", GST_MESSAGE_TYPE_NAME(msg));
1856+
//printf("\t\tGot %s message\n", GST_MESSAGE_TYPE_NAME(msg));
17551857

17561858
if(gst_is_missing_plugin_message(msg))
17571859
{
@@ -1763,28 +1865,30 @@ void handleMessage(GstElement * pipeline)
17631865
case GST_MESSAGE_STATE_CHANGED:
17641866
GstState oldstate, newstate, pendstate;
17651867
gst_message_parse_state_changed(msg, &oldstate, &newstate, &pendstate);
1766-
//fprintf(stderr, "state changed from %s to %s (pending: %s)\n", gst_element_state_get_name(oldstate),
1868+
//fprintf(stderr, "\t\t%s: state changed from %s to %s (pending: %s)\n",
1869+
// gst_element_get_name(GST_MESSAGE_SRC (msg)),
1870+
// gst_element_state_get_name(oldstate),
17671871
// gst_element_state_get_name(newstate), gst_element_state_get_name(pendstate));
17681872
break;
17691873
case GST_MESSAGE_ERROR:
17701874
gst_message_parse_error(msg, &err, &debug);
1771-
fprintf(stderr, "GStreamer Plugin: Embedded video playback halted; module %s reported: %s\n",
1772-
gst_element_get_name(GST_MESSAGE_SRC (msg)), err->message);
1875+
//fprintf(stderr, "\t\tGStreamer Plugin: Embedded video playback halted; module %s reported: %s\n",
1876+
// gst_element_get_name(GST_MESSAGE_SRC (msg)), err->message);
17731877

17741878
g_error_free(err);
17751879
g_free(debug);
17761880

17771881
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL);
17781882
break;
17791883
case GST_MESSAGE_EOS:
1780-
//fprintf(stderr, "reached the end of the stream.");
1884+
//fprintf(stderr, "\t\treached the end of the stream.");
17811885
break;
17821886
case GST_MESSAGE_STREAM_STATUS:
17831887
gst_message_parse_stream_status(msg,&tp,&elem);
1784-
//fprintf(stderr, "stream status: elem %s, %i\n", GST_ELEMENT_NAME(elem), tp);
1888+
//fprintf(stderr, "\t\tstream status: elem %s, %i\n", GST_ELEMENT_NAME(elem), tp);
17851889
break;
17861890
default:
1787-
//fprintf(stderr, "unhandled message %s\n",GST_MESSAGE_TYPE_NAME(msg));
1891+
//fprintf(stderr, "\t\tunhandled message %s\n",GST_MESSAGE_TYPE_NAME(msg));
17881892
break;
17891893
}
17901894
}

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)