Merge pull request #3253 from asmorkalov:ocv_gstreamer2
This commit is contained in:
commit
ecbec7235f
@ -73,13 +73,14 @@
|
|||||||
#define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
|
#define CV_WARN(message) fprintf(stderr, "warning: %s (%s:%d)\n", message, __FILE__, __LINE__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if GST_VERSION_MAJOR > 0
|
#if GST_VERSION_MAJOR == 0
|
||||||
#define COLOR_ELEM "autovideoconvert"
|
|
||||||
#else
|
|
||||||
#define COLOR_ELEM "ffmpegcolorspace"
|
#define COLOR_ELEM "ffmpegcolorspace"
|
||||||
|
#elif FULL_GST_VERSION < VERSION_NUM(1,5,0)
|
||||||
|
#define COLOR_ELEM "videoconvert"
|
||||||
|
#else
|
||||||
|
#define COLOR_ELEM "autovideoconvert"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void toFraction(double decimal, double &numerator, double &denominator);
|
void toFraction(double decimal, double &numerator, double &denominator);
|
||||||
void handleMessage(GstElement * pipeline);
|
void handleMessage(GstElement * pipeline);
|
||||||
|
|
||||||
@ -555,6 +556,7 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
|
|||||||
|
|
||||||
gst_initializer::init();
|
gst_initializer::init();
|
||||||
|
|
||||||
|
bool file = false;
|
||||||
bool stream = false;
|
bool stream = false;
|
||||||
bool manualpipeline = false;
|
bool manualpipeline = false;
|
||||||
char *uri = NULL;
|
char *uri = NULL;
|
||||||
@ -591,7 +593,12 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
|
|||||||
if(uri)
|
if(uri)
|
||||||
{
|
{
|
||||||
uri = g_filename_to_uri(uri, NULL, NULL);
|
uri = g_filename_to_uri(uri, NULL, NULL);
|
||||||
if(!uri) {
|
if(uri)
|
||||||
|
{
|
||||||
|
file = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
CV_WARN("GStreamer: Error opening file\n");
|
CV_WARN("GStreamer: Error opening file\n");
|
||||||
close();
|
close();
|
||||||
return false;
|
return false;
|
||||||
@ -601,9 +608,9 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
|
|||||||
{
|
{
|
||||||
GError *err = NULL;
|
GError *err = NULL;
|
||||||
uridecodebin = gst_parse_launch(filename, &err);
|
uridecodebin = gst_parse_launch(filename, &err);
|
||||||
if(!uridecodebin) {
|
if(!uridecodebin)
|
||||||
//fprintf(stderr, "GStreamer: Error opening bin: %s\n", err->message);
|
{
|
||||||
//close();
|
fprintf(stderr, "GStreamer: Error opening bin: %s\n", err->message);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
stream = true;
|
stream = true;
|
||||||
@ -632,7 +639,7 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
|
|||||||
element_from_uri = true;
|
element_from_uri = true;
|
||||||
}else{
|
}else{
|
||||||
uridecodebin = gst_element_factory_make("uridecodebin", NULL);
|
uridecodebin = gst_element_factory_make("uridecodebin", NULL);
|
||||||
g_object_set(G_OBJECT(uridecodebin),"uri",uri, NULL);
|
g_object_set(G_OBJECT(uridecodebin), "uri", uri, NULL);
|
||||||
}
|
}
|
||||||
g_free(protocol);
|
g_free(protocol);
|
||||||
|
|
||||||
@ -744,7 +751,7 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
|
|||||||
gst_caps_unref(caps);
|
gst_caps_unref(caps);
|
||||||
|
|
||||||
// For video files only: set pipeline to PAUSED state to get its duration
|
// For video files only: set pipeline to PAUSED state to get its duration
|
||||||
if (stream)
|
if (file)
|
||||||
{
|
{
|
||||||
status = gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PAUSED);
|
status = gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PAUSED);
|
||||||
if (status == GST_STATE_CHANGE_ASYNC)
|
if (status == GST_STATE_CHANGE_ASYNC)
|
||||||
@ -772,6 +779,7 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
|
|||||||
if(!gst_element_query_duration(sink, format, &duration))
|
if(!gst_element_query_duration(sink, format, &duration))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
handleMessage(pipeline);
|
||||||
CV_WARN("GStreamer: unable to query duration of stream");
|
CV_WARN("GStreamer: unable to query duration of stream");
|
||||||
duration = -1;
|
duration = -1;
|
||||||
return true;
|
return true;
|
||||||
@ -1166,7 +1174,6 @@ const char* CvVideoWriter_GStreamer::filenameToMimetype(const char *filename)
|
|||||||
return (const char*)"video/x-msvideo";
|
return (const char*)"video/x-msvideo";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief CvVideoWriter_GStreamer::open
|
* \brief CvVideoWriter_GStreamer::open
|
||||||
* \param filename filename to output to
|
* \param filename filename to output to
|
||||||
@ -1214,7 +1221,12 @@ bool CvVideoWriter_GStreamer::open( const char * filename, int fourcc,
|
|||||||
GstEncodingVideoProfile* videoprofile = NULL;
|
GstEncodingVideoProfile* videoprofile = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GstIterator *it = NULL;
|
GstIterator* it = NULL;
|
||||||
|
gboolean done = FALSE;
|
||||||
|
GstElement *element = NULL;
|
||||||
|
gchar* name = NULL;
|
||||||
|
GstElement* splitter = NULL;
|
||||||
|
GstElement* combiner = NULL;
|
||||||
|
|
||||||
// we first try to construct a pipeline from the given string.
|
// we first try to construct a pipeline from the given string.
|
||||||
// if that fails, we assume it is an ordinary filename
|
// if that fails, we assume it is an ordinary filename
|
||||||
@ -1222,9 +1234,7 @@ bool CvVideoWriter_GStreamer::open( const char * filename, int fourcc,
|
|||||||
__BEGIN__;
|
__BEGIN__;
|
||||||
|
|
||||||
encodebin = gst_parse_launch(filename, &err);
|
encodebin = gst_parse_launch(filename, &err);
|
||||||
if(!encodebin) {
|
manualpipeline = (encodebin != NULL);
|
||||||
manualpipeline = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(manualpipeline)
|
if(manualpipeline)
|
||||||
{
|
{
|
||||||
@ -1236,10 +1246,6 @@ bool CvVideoWriter_GStreamer::open( const char * filename, int fourcc,
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
it = gst_bin_iterate_sources (GST_BIN(encodebin));
|
it = gst_bin_iterate_sources (GST_BIN(encodebin));
|
||||||
|
|
||||||
gboolean done = FALSE;
|
|
||||||
GstElement *element = NULL;
|
|
||||||
gchar* name = NULL;
|
|
||||||
GValue value = G_VALUE_INIT;
|
GValue value = G_VALUE_INIT;
|
||||||
|
|
||||||
while (!done) {
|
while (!done) {
|
||||||
@ -1289,7 +1295,9 @@ bool CvVideoWriter_GStreamer::open( const char * filename, int fourcc,
|
|||||||
if (fourcc == CV_FOURCC('M','P','2','V')) fourcc = CV_FOURCC('M', 'P', 'G' ,'2');
|
if (fourcc == CV_FOURCC('M','P','2','V')) fourcc = CV_FOURCC('M', 'P', 'G' ,'2');
|
||||||
if (fourcc == CV_FOURCC('D','R','A','C')) fourcc = CV_FOURCC('d', 'r', 'a' ,'c');
|
if (fourcc == CV_FOURCC('D','R','A','C')) fourcc = CV_FOURCC('d', 'r', 'a' ,'c');
|
||||||
|
|
||||||
|
|
||||||
//create encoder caps from fourcc
|
//create encoder caps from fourcc
|
||||||
|
|
||||||
videocaps = gst_riff_create_video_caps(fourcc, NULL, NULL, NULL, NULL, NULL);
|
videocaps = gst_riff_create_video_caps(fourcc, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (!videocaps){
|
if (!videocaps){
|
||||||
CV_ERROR( CV_StsUnsupportedFormat, "Gstreamer Opencv backend does not support this codec.");
|
CV_ERROR( CV_StsUnsupportedFormat, "Gstreamer Opencv backend does not support this codec.");
|
||||||
@ -1312,6 +1320,7 @@ bool CvVideoWriter_GStreamer::open( const char * filename, int fourcc,
|
|||||||
|
|
||||||
//create pipeline elements
|
//create pipeline elements
|
||||||
encodebin = gst_element_factory_make("encodebin", NULL);
|
encodebin = gst_element_factory_make("encodebin", NULL);
|
||||||
|
|
||||||
#if FULL_GST_VERSION >= VERSION_NUM(0,10,32)
|
#if FULL_GST_VERSION >= VERSION_NUM(0,10,32)
|
||||||
g_object_set(G_OBJECT(encodebin), "profile", containerprofile, NULL);
|
g_object_set(G_OBJECT(encodebin), "profile", containerprofile, NULL);
|
||||||
#endif
|
#endif
|
||||||
@ -1376,7 +1385,7 @@ bool CvVideoWriter_GStreamer::open( const char * filename, int fourcc,
|
|||||||
g_object_set(G_OBJECT(source), "format", GST_FORMAT_TIME, NULL);
|
g_object_set(G_OBJECT(source), "format", GST_FORMAT_TIME, NULL);
|
||||||
g_object_set(G_OBJECT(source), "block", 1, NULL);
|
g_object_set(G_OBJECT(source), "block", 1, NULL);
|
||||||
g_object_set(G_OBJECT(source), "is-live", 0, NULL);
|
g_object_set(G_OBJECT(source), "is-live", 0, NULL);
|
||||||
g_object_set(G_OBJECT(source), "emit-signals", 1, NULL);
|
|
||||||
|
|
||||||
if(!manualpipeline)
|
if(!manualpipeline)
|
||||||
{
|
{
|
||||||
@ -1387,6 +1396,63 @@ bool CvVideoWriter_GStreamer::open( const char * filename, int fourcc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if GST_VERSION_MAJOR == 0
|
||||||
|
// HACK: remove streamsplitter and streamcombiner from
|
||||||
|
// encodebin pipeline to prevent early EOF event handling
|
||||||
|
// We always fetch BGR or gray-scale frames, so combiner->spliter
|
||||||
|
// endge in graph is useless.
|
||||||
|
it = gst_bin_iterate_recurse (GST_BIN(encodebin));
|
||||||
|
while (!done) {
|
||||||
|
switch (gst_iterator_next (it, (void**)&element)) {
|
||||||
|
case GST_ITERATOR_OK:
|
||||||
|
name = gst_element_get_name(element);
|
||||||
|
if (strstr(name, "streamsplitter"))
|
||||||
|
splitter = element;
|
||||||
|
else if (strstr(name, "streamcombiner"))
|
||||||
|
combiner = element;
|
||||||
|
break;
|
||||||
|
case GST_ITERATOR_RESYNC:
|
||||||
|
gst_iterator_resync (it);
|
||||||
|
break;
|
||||||
|
case GST_ITERATOR_ERROR:
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
case GST_ITERATOR_DONE:
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_iterator_free (it);
|
||||||
|
|
||||||
|
if (splitter && combiner)
|
||||||
|
{
|
||||||
|
gst_element_unlink(splitter, combiner);
|
||||||
|
|
||||||
|
GstPad* src = gst_element_get_pad(combiner, "src");
|
||||||
|
GstPad* sink = gst_element_get_pad(combiner, "encodingsink");
|
||||||
|
|
||||||
|
GstPad* srcPeer = gst_pad_get_peer(src);
|
||||||
|
GstPad* sinkPeer = gst_pad_get_peer(sink);
|
||||||
|
|
||||||
|
gst_pad_unlink(sinkPeer, sink);
|
||||||
|
gst_pad_unlink(src, srcPeer);
|
||||||
|
|
||||||
|
gst_pad_link(sinkPeer, srcPeer);
|
||||||
|
|
||||||
|
src = gst_element_get_pad(splitter, "encodingsrc");
|
||||||
|
sink = gst_element_get_pad(splitter, "sink");
|
||||||
|
|
||||||
|
srcPeer = gst_pad_get_peer(src);
|
||||||
|
sinkPeer = gst_pad_get_peer(sink);
|
||||||
|
|
||||||
|
gst_pad_unlink(sinkPeer, sink);
|
||||||
|
gst_pad_unlink(src, srcPeer);
|
||||||
|
|
||||||
|
gst_pad_link(sinkPeer, srcPeer);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
stateret = gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);
|
stateret = gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);
|
||||||
if(stateret == GST_STATE_CHANGE_FAILURE) {
|
if(stateret == GST_STATE_CHANGE_FAILURE) {
|
||||||
handleMessage(pipeline);
|
handleMessage(pipeline);
|
||||||
@ -1437,7 +1503,7 @@ bool CvVideoWriter_GStreamer::writeFrame( const IplImage * image )
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else {
|
else {
|
||||||
CV_WARN("Invalid video format!\n");
|
CV_ERROR(CV_StsUnsupportedFormat, "cvWriteFrame() needs BGR or grayscale images\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1447,7 +1513,12 @@ bool CvVideoWriter_GStreamer::writeFrame( const IplImage * image )
|
|||||||
|
|
||||||
//gst_app_src_push_buffer takes ownership of the buffer, so we need to supply it a copy
|
//gst_app_src_push_buffer takes ownership of the buffer, so we need to supply it a copy
|
||||||
#if GST_VERSION_MAJOR == 0
|
#if GST_VERSION_MAJOR == 0
|
||||||
buffer = gst_buffer_new_and_alloc (size);
|
buffer = gst_buffer_try_new_and_alloc (size);
|
||||||
|
if (!buffer)
|
||||||
|
{
|
||||||
|
CV_ERROR(CV_StsBadSize, "Cannot create GStreamer buffer");
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(GST_BUFFER_DATA (buffer), (guint8*)image->imageData, size);
|
memcpy(GST_BUFFER_DATA (buffer), (guint8*)image->imageData, size);
|
||||||
GST_BUFFER_DURATION(buffer) = duration;
|
GST_BUFFER_DURATION(buffer) = duration;
|
||||||
GST_BUFFER_TIMESTAMP(buffer) = timestamp;
|
GST_BUFFER_TIMESTAMP(buffer) = timestamp;
|
||||||
@ -1469,7 +1540,8 @@ bool CvVideoWriter_GStreamer::writeFrame( const IplImage * image )
|
|||||||
CV_WARN("Error pushing buffer to GStreamer pipeline");
|
CV_WARN("Error pushing buffer to GStreamer pipeline");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//gst_debug_bin_to_dot_file (GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pipeline");
|
|
||||||
|
//GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(pipeline), GST_DEBUG_GRAPH_SHOW_ALL, "pipeline");
|
||||||
|
|
||||||
++num_frames;
|
++num_frames;
|
||||||
|
|
||||||
@ -1559,8 +1631,8 @@ void handleMessage(GstElement * pipeline)
|
|||||||
break;
|
break;
|
||||||
case GST_MESSAGE_ERROR:
|
case GST_MESSAGE_ERROR:
|
||||||
gst_message_parse_error(msg, &err, &debug);
|
gst_message_parse_error(msg, &err, &debug);
|
||||||
//fprintf(stderr, "GStreamer Plugin: Embedded video playback halted; module %s reported: %s\n",
|
fprintf(stderr, "GStreamer Plugin: Embedded video playback halted; module %s reported: %s\n",
|
||||||
// gst_element_get_name(GST_MESSAGE_SRC (msg)), err->message);
|
gst_element_get_name(GST_MESSAGE_SRC (msg)), err->message);
|
||||||
|
|
||||||
g_error_free(err);
|
g_error_free(err);
|
||||||
g_free(debug);
|
g_free(debug);
|
||||||
|
@ -92,7 +92,9 @@ const VideoFormat g_specific_fmt_list[] =
|
|||||||
VideoFormat("mkv", VideoWriter::fourcc('X', 'V', 'I', 'D')),
|
VideoFormat("mkv", VideoWriter::fourcc('X', 'V', 'I', 'D')),
|
||||||
VideoFormat("mkv", VideoWriter::fourcc('M', 'P', 'E', 'G')),
|
VideoFormat("mkv", VideoWriter::fourcc('M', 'P', 'E', 'G')),
|
||||||
VideoFormat("mkv", VideoWriter::fourcc('M', 'J', 'P', 'G')),
|
VideoFormat("mkv", VideoWriter::fourcc('M', 'J', 'P', 'G')),
|
||||||
|
#ifndef HAVE_GSTREAMER
|
||||||
VideoFormat("mov", VideoWriter::fourcc('m', 'p', '4', 'v')),
|
VideoFormat("mov", VideoWriter::fourcc('m', 'p', '4', 'v')),
|
||||||
|
#endif
|
||||||
VideoFormat()
|
VideoFormat()
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@ -490,7 +492,13 @@ void CV_VideoIOTest::SpecificVideoTest(const string& dir, const cvtest::VideoFor
|
|||||||
if (fourcc == VideoWriter::fourcc('M', 'P', 'E', 'G') && ext == "mkv")
|
if (fourcc == VideoWriter::fourcc('M', 'P', 'E', 'G') && ext == "mkv")
|
||||||
allowed_extra_frames = 1;
|
allowed_extra_frames = 1;
|
||||||
|
|
||||||
if (FRAME_COUNT < IMAGE_COUNT || FRAME_COUNT > IMAGE_COUNT + allowed_extra_frames)
|
// Hack! Some GStreamer encoding pipelines drop last frame in the video
|
||||||
|
int allowed_frame_frop = 0;
|
||||||
|
#ifdef HAVE_GSTREAMER
|
||||||
|
allowed_frame_frop = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (FRAME_COUNT < IMAGE_COUNT - allowed_frame_frop || FRAME_COUNT > IMAGE_COUNT + allowed_extra_frames)
|
||||||
{
|
{
|
||||||
ts->printf(ts->LOG, "\nFrame count checking for video_%s.%s...\n", fourcc_str.c_str(), ext.c_str());
|
ts->printf(ts->LOG, "\nFrame count checking for video_%s.%s...\n", fourcc_str.c_str(), ext.c_str());
|
||||||
ts->printf(ts->LOG, "Video codec: %s\n", fourcc_str.c_str());
|
ts->printf(ts->LOG, "Video codec: %s\n", fourcc_str.c_str());
|
||||||
@ -505,7 +513,7 @@ void CV_VideoIOTest::SpecificVideoTest(const string& dir, const cvtest::VideoFor
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; (size_t)i < IMAGE_COUNT; i++)
|
for (int i = 0; (size_t)i < IMAGE_COUNT-allowed_frame_frop; i++)
|
||||||
{
|
{
|
||||||
Mat frame; cap >> frame;
|
Mat frame; cap >> frame;
|
||||||
if (frame.empty())
|
if (frame.empty())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user