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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user