1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 08:13:04 +04:00

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
This commit is contained in:
Alexander Alekhin
2017-07-05 13:45:08 +03:00
parent f670a99270
commit cc862e996e
4 changed files with 197 additions and 57 deletions
+115 -11
View File
@@ -168,6 +168,10 @@ protected:
gint width;
gint height;
double fps;
bool isPosFramesSupported;
bool isPosFramesEmulated;
gint64 emulatedFrameNumber;
};
/*!
@@ -191,6 +195,10 @@ void CvCapture_GStreamer::init()
width = -1;
height = -1;
fps = -1;
isPosFramesSupported = false;
isPosFramesEmulated = false;
emulatedFrameNumber = -1;
}
/*!
@@ -212,6 +220,9 @@ void CvCapture_GStreamer::close()
width = -1;
height = -1;
fps = -1;
isPosFramesSupported = false;
isPosFramesEmulated = false;
emulatedFrameNumber = -1;
}
/*!
@@ -253,6 +264,9 @@ bool CvCapture_GStreamer::grabFrame()
if(!buffer)
return false;
if (isPosFramesEmulated)
emulatedFrameNumber++;
return true;
}
@@ -408,6 +422,9 @@ void CvCapture_GStreamer::startPipeline()
return;
}
if (isPosFramesEmulated)
emulatedFrameNumber = 0;
//printf("state now playing\n");
handleMessage(pipeline);
__END__;
@@ -847,6 +864,8 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
duration = -1;
}
handleMessage(pipeline);
GstPad* pad = gst_element_get_static_pad(sink, "sink");
#if GST_VERSION_MAJOR == 0
GstCaps* buffer_caps = gst_pad_get_caps(pad);
@@ -873,9 +892,32 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
fps = (double)num/(double)denom;
// GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pipeline")
if (file)
stopPipeline();
{
GstFormat format_;
gint64 value_ = -1;
gboolean status_;
format_ = GST_FORMAT_DEFAULT;
#if GST_VERSION_MAJOR == 0
#define FORMAT &format_
#else
#define FORMAT format_
#endif
status_ = gst_element_query_position(pipeline, FORMAT, &value_);
#undef FORMAT
if (!status_ || value_ != 0 || duration < 0)
{
CV_WARN(cv::format("Cannot query video position: status=%d value=%lld duration=%lld\n",
(int)status_, (long long int)value_, (long long int)duration).c_str());
isPosFramesSupported = false;
isPosFramesEmulated = true;
emulatedFrameNumber = 0;
}
else
isPosFramesSupported = true;
}
GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pipeline");
}
__END__;
@@ -914,14 +956,22 @@ double CvCapture_GStreamer::getProperty( int propId ) const
format = GST_FORMAT_TIME;
status = gst_element_query_position(sink, FORMAT, &value);
if(!status) {
handleMessage(pipeline);
CV_WARN("GStreamer: unable to query position of stream");
return 0;
}
return value * 1e-6; // nano seconds to milli seconds
case CV_CAP_PROP_POS_FRAMES:
if (!isPosFramesSupported)
{
if (isPosFramesEmulated)
return emulatedFrameNumber;
return 0; // TODO getProperty() "unsupported" value should be changed
}
format = GST_FORMAT_DEFAULT;
status = gst_element_query_position(sink, FORMAT, &value);
if(!status) {
handleMessage(pipeline);
CV_WARN("GStreamer: unable to query position of stream");
return 0;
}
@@ -930,6 +980,7 @@ double CvCapture_GStreamer::getProperty( int propId ) const
format = GST_FORMAT_PERCENT;
status = gst_element_query_position(sink, FORMAT, &value);
if(!status) {
handleMessage(pipeline);
CV_WARN("GStreamer: unable to query position of stream");
return 0;
}
@@ -1013,24 +1064,75 @@ bool CvCapture_GStreamer::setProperty( int propId, double value )
flags = (GstSeekFlags) (GST_SEEK_FLAG_FLUSH|GST_SEEK_FLAG_ACCURATE);
if(!gst_element_seek_simple(GST_ELEMENT(pipeline), format,
flags, (gint64) (value * GST_MSECOND))) {
handleMessage(pipeline);
CV_WARN("GStreamer: unable to seek");
}
else
{
if (isPosFramesEmulated)
{
if (value == 0)
{
emulatedFrameNumber = 0;
return true;
}
else
{
isPosFramesEmulated = false; // reset frame counter emulation
}
}
}
break;
case CV_CAP_PROP_POS_FRAMES:
{
if (!isPosFramesSupported)
{
if (isPosFramesEmulated)
{
if (value == 0)
{
restartPipeline();
emulatedFrameNumber = 0;
return true;
}
}
return false;
}
format = GST_FORMAT_DEFAULT;
flags = (GstSeekFlags) (GST_SEEK_FLAG_FLUSH|GST_SEEK_FLAG_ACCURATE);
if(!gst_element_seek_simple(GST_ELEMENT(pipeline), format,
flags, (gint64) value)) {
handleMessage(pipeline);
CV_WARN("GStreamer: unable to seek");
break;
}
break;
// wait for status update
gst_element_get_state(pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
return true;
}
case CV_CAP_PROP_POS_AVI_RATIO:
format = GST_FORMAT_PERCENT;
flags = (GstSeekFlags) (GST_SEEK_FLAG_FLUSH|GST_SEEK_FLAG_ACCURATE);
if(!gst_element_seek_simple(GST_ELEMENT(pipeline), format,
flags, (gint64) (value * GST_FORMAT_PERCENT_MAX))) {
handleMessage(pipeline);
CV_WARN("GStreamer: unable to seek");
}
else
{
if (isPosFramesEmulated)
{
if (value == 0)
{
emulatedFrameNumber = 0;
return true;
}
else
{
isPosFramesEmulated = false; // reset frame counter emulation
}
}
}
break;
case CV_CAP_PROP_FRAME_WIDTH:
if(value > 0)
@@ -1719,7 +1821,7 @@ void handleMessage(GstElement * pipeline)
while(gst_bus_have_pending(bus)) {
msg = gst_bus_pop(bus);
//printf("Got %s message\n", GST_MESSAGE_TYPE_NAME(msg));
//printf("\t\tGot %s message\n", GST_MESSAGE_TYPE_NAME(msg));
if(gst_is_missing_plugin_message(msg))
{
@@ -1731,13 +1833,15 @@ void handleMessage(GstElement * pipeline)
case GST_MESSAGE_STATE_CHANGED:
GstState oldstate, newstate, pendstate;
gst_message_parse_state_changed(msg, &oldstate, &newstate, &pendstate);
//fprintf(stderr, "state changed from %s to %s (pending: %s)\n", gst_element_state_get_name(oldstate),
//fprintf(stderr, "\t\t%s: state changed from %s to %s (pending: %s)\n",
// gst_element_get_name(GST_MESSAGE_SRC (msg)),
// gst_element_state_get_name(oldstate),
// gst_element_state_get_name(newstate), gst_element_state_get_name(pendstate));
break;
case GST_MESSAGE_ERROR:
gst_message_parse_error(msg, &err, &debug);
fprintf(stderr, "GStreamer Plugin: Embedded video playback halted; module %s reported: %s\n",
gst_element_get_name(GST_MESSAGE_SRC (msg)), err->message);
//fprintf(stderr, "\t\tGStreamer Plugin: Embedded video playback halted; module %s reported: %s\n",
// gst_element_get_name(GST_MESSAGE_SRC (msg)), err->message);
g_error_free(err);
g_free(debug);
@@ -1745,14 +1849,14 @@ void handleMessage(GstElement * pipeline)
gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL);
break;
case GST_MESSAGE_EOS:
//fprintf(stderr, "reached the end of the stream.");
//fprintf(stderr, "\t\treached the end of the stream.");
break;
case GST_MESSAGE_STREAM_STATUS:
gst_message_parse_stream_status(msg,&tp,&elem);
//fprintf(stderr, "stream status: elem %s, %i\n", GST_ELEMENT_NAME(elem), tp);
//fprintf(stderr, "\t\tstream status: elem %s, %i\n", GST_ELEMENT_NAME(elem), tp);
break;
default:
//fprintf(stderr, "unhandled message %s\n",GST_MESSAGE_TYPE_NAME(msg));
//fprintf(stderr, "\t\tunhandled message %s\n",GST_MESSAGE_TYPE_NAME(msg));
break;
}
}