Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv
Commits
80da1d40
Commit
80da1d40
authored
Apr 23, 2011
by
Nils Hasler
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
removed private copy of gstappsink because appsink is now part of gstreamer base.
parent
e7e72d24
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
13 additions
and
930 deletions
+13
-930
CMakeLists.txt
CMakeLists.txt
+1
-1
cvconfig.h.cmake
cvconfig.h.cmake
+0
-3
CMakeLists.txt
modules/highgui/CMakeLists.txt
+0
-4
cap_gstreamer.cpp
modules/highgui/src/cap_gstreamer.cpp
+12
-68
gstappsink.cpp
modules/highgui/src/gstappsink.cpp
+0
-765
gstappsink.h
modules/highgui/src/gstappsink.h
+0
-89
No files found.
CMakeLists.txt
View file @
80da1d40
...
...
@@ -372,7 +372,7 @@ if(UNIX)
endif
()
if
(
WITH_GSTREAMER
)
CHECK_MODULE
(
gstreamer-base-0.10 HAVE_GSTREAMER
)
CHECK_MODULE
(
gstreamer-app-0.10 HAVE_GSTREAMER
_APP
)
CHECK_MODULE
(
gstreamer-app-0.10 HAVE_GSTREAMER
)
CHECK_MODULE
(
gstreamer-video-0.10 HAVE_GSTREAMER
)
else
()
set
(
HAVE_GSTREAMER FALSE
)
...
...
cvconfig.h.cmake
View file @
80da1d40
...
...
@@ -43,9 +43,6 @@
/* GStreamer multimedia framework */
#cmakedefine HAVE_GSTREAMER
/* GStreamer with gstappsink & gstappsrc */
#cmakedefine HAVE_GSTREAMER_APP
/* GTK+ 2.0 Thread support */
#cmakedefine HAVE_GTHREAD
...
...
modules/highgui/CMakeLists.txt
View file @
80da1d40
...
...
@@ -132,10 +132,6 @@ if(UNIX)
if
(
HAVE_GSTREAMER
)
set
(
highgui_srcs
${
highgui_srcs
}
src/cap_gstreamer.cpp
)
if
(
NOT HAVE_GSTREAMER_APP
)
set
(
highgui_srcs
${
highgui_srcs
}
src/gstappsink.cpp
)
set
(
highgui_hdrs
${
highgui_hdrs
}
src/gstappsink.h
)
endif
()
endif
()
if
(
HAVE_UNICAP
)
...
...
modules/highgui/src/cap_gstreamer.cpp
View file @
80da1d40
...
...
@@ -10,7 +10,7 @@
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2008, Nils Hasler, all rights reserved.
// Copyright (C) 2008,
2011,
Nils Hasler, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
...
...
@@ -55,15 +55,10 @@
#include <map>
#include <gst/gst.h>
#include <gst/video/video.h>
#ifdef HAVE_GSTREAMER_APP
#include <gst/app/gstappsink.h>
#include <gst/app/gstappsrc.h>
#include <gst/riff/riff-media.h>
#else
#include "gstappsink.h"
#endif
#ifdef NDEBUG
#define CV_WARN(message)
#else
...
...
@@ -168,28 +163,14 @@ bool CvCapture_GStreamer::grabFrame()
if
(
!
pipeline
)
return
false
;
if
(
gst_app_sink_is_eos
(
GST_APP_SINK
(
sink
)))
{
//printf("end of stream\n");
if
(
gst_app_sink_is_eos
(
GST_APP_SINK
(
sink
)))
return
false
;
}
if
(
buffer
)
gst_buffer_unref
(
buffer
);
handleMessage
();
#ifndef HAVE_GSTREAMER_APP
if
(
gst_app_sink_get_queue_length
(
GST_APP_SINK
(
sink
)))
{
// printf("peeking buffer, %d buffers in queue\n",
buffer
=
gst_app_sink_peek_buffer
(
GST_APP_SINK
(
sink
));
}
else
#endif
{
// printf("pulling buffer\n");
buffer
=
gst_app_sink_pull_buffer
(
GST_APP_SINK
(
sink
));
// printf("pulled buffer %p\n", GST_BUFFER_DATA(buffer));
}
buffer
=
gst_app_sink_pull_buffer
(
GST_APP_SINK
(
sink
));
if
(
!
buffer
)
return
false
;
...
...
@@ -204,8 +185,6 @@ IplImage * CvCapture_GStreamer::retrieveFrame(int)
if
(
!
buffer
)
return
false
;
// printf("retrieving buffer %p\n", GST_BUFFER_DATA(buffer));
if
(
!
frame
)
{
gint
height
,
width
;
GstCaps
*
buff_caps
=
gst_buffer_get_caps
(
buffer
);
...
...
@@ -220,9 +199,9 @@ IplImage * CvCapture_GStreamer::retrieveFrame(int)
gst_caps_unref
(
buff_caps
);
}
// no need to memcpy, just use gstreamer's buffer :-)
frame
->
imageData
=
(
char
*
)
GST_BUFFER_DATA
(
buffer
);
//memcpy (frame->imageData, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE (buffer));
//gst_data_copy_into (frame->imageData,GST_BUFFER_DATA(buffer));
//gst_buffer_unref(buffer);
//buffer = 0;
return
frame
;
...
...
@@ -270,7 +249,7 @@ void CvCapture_GStreamer::setFilter(const char *property, int type, int v1, int
else
caps
=
gst_caps_new_simple
(
"video/x-raw-rgb"
,
property
,
type
,
v1
,
v2
,
NULL
);
}
else
{
printf
(
"caps before setting %s
\n
"
,
gst_caps_to_string
(
caps
));
//
printf("caps before setting %s\n", gst_caps_to_string(caps));
if
(
type
==
G_TYPE_INT
)
gst_caps_set_simple
(
caps
,
"video/x-raw-rgb"
,
property
,
type
,
v1
,
NULL
);
else
...
...
@@ -312,14 +291,6 @@ void CvCapture_GStreamer::newPad(GstElement *uridecodebin,
gst_object_unref
(
sinkpad
);
}
// static int buffernum = 0;
// static GstFlowReturn newbuffer(GstAppSink *sink, gpointer data)
// {
// printf("new buffer %d\n", buffernum);
// buffernum++;
// return GST_FLOW_OK;
// }
bool
CvCapture_GStreamer
::
open
(
int
type
,
const
char
*
filename
)
{
close
();
...
...
@@ -347,11 +318,9 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
}
if
(
!
gst_uri_is_valid
(
filename
))
{
// printf("file '%s' is not uri\n", filename);
uri
=
realpath
(
filename
,
NULL
);
stream
=
false
;
if
(
uri
)
{
// printf("is file... ? %s\n", uri);
uri
=
g_filename_to_uri
(
uri
,
NULL
,
NULL
);
if
(
!
uri
)
{
CV_WARN
(
"GStreamer: Error opening file
\n
"
);
...
...
@@ -367,18 +336,14 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
return
false
;
}
stream
=
true
;
// printf("created custom bin\n");
manualpipeline
=
true
;
}
}
else
{
// printf("file '%s' is uri\n", filename);
}
else
{
stream
=
true
;
uri
=
g_strdup
(
filename
);
}
if
(
!
uridecodebin
)
{
// printf("creating uridecodebin\n");
uridecodebin
=
gst_element_factory_make
(
"uridecodebin"
,
NULL
);
g_object_set
(
G_OBJECT
(
uridecodebin
),
"uri"
,
uri
,
NULL
);
}
...
...
@@ -387,22 +352,12 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
close
();
return
false
;
}
// printf("Trying to connect to stream \n");
color
=
gst_element_factory_make
(
"ffmpegcolorspace"
,
NULL
);
//printf("%sstreaming\n", stream ? "" : "not ");
#ifdef HAVE_GSTREAMER_APP
sink
=
gst_element_factory_make
(
"appsink"
,
NULL
);
gst_app_sink_set_max_buffers
(
GST_APP_SINK
(
sink
),
1
);
if
(
stream
)
{
gst_app_sink_set_drop
(
GST_APP_SINK
(
sink
),
true
);
}
// GstAppSinkCallbacks cb = {0, 0, newbuffer, 0};
// gst_app_sink_set_callbacks(GST_APP_SINK(sink), &cb, 0, 0);
#else
sink
=
gst_element_factory_make
(
"opencv-appsink"
,
NULL
);
#endif
gst_app_sink_set_max_buffers
(
GST_APP_SINK
(
sink
),
1
);
if
(
stream
)
gst_app_sink_set_drop
(
GST_APP_SINK
(
sink
),
true
);
GstCaps
*
caps
=
gst_caps_new_simple
(
"video/x-raw-rgb"
,
"red_mask"
,
G_TYPE_INT
,
255
,
"green_mask"
,
G_TYPE_INT
,
65280
,
...
...
@@ -413,14 +368,12 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
pipeline
=
gst_pipeline_new
(
NULL
);
//printf("adding stuff to pipeline\n");
if
(
manualpipeline
)
{
// it is easier to link elements inside the same bin
gst_bin_add_many
(
GST_BIN
(
uridecodebin
),
color
,
sink
,
NULL
);
// need the pipeline around the bin because bins don't know about timing
gst_bin_add
(
GST_BIN
(
pipeline
),
uridecodebin
);
}
else
{
}
else
{
gst_bin_add_many
(
GST_BIN
(
pipeline
),
uridecodebin
,
color
,
sink
,
NULL
);
}
...
...
@@ -428,11 +381,8 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
GstElement
*
e
=
gst_bin_get_by_name
(
GST_BIN
(
uridecodebin
),
"to-opencv"
);
if
(
e
)
{
if
(
!
gst_element_link
(
e
,
color
))
{
//printf("catching 'pad-added' for element 'to-opencv'\n");
g_signal_connect
(
e
,
"pad-added"
,
G_CALLBACK
(
newPad
),
color
);
}
/* else {
printf("linked to-opencv -> color\n");
}*/
}
gst_object_unref
(
e
);
}
else
{
CV_WARN
(
"GStreamer: no element with 'name=to-opencv'
\n
"
);
...
...
@@ -475,7 +425,7 @@ bool CvCapture_GStreamer::open( int type, const char* filename )
return
true
;
}
#ifdef HAVE_GSTREAMER_APP
//
//
// gstreamer image sequence writer
...
...
@@ -638,13 +588,7 @@ CvVideoWriter* cvCreateVideoWriter_GStreamer(const char* filename, int fourcc, d
delete
wrt
;
return
false
;
}
#else
CvVideoWriter
*
cvCreateVideoWriter_GStreamer
(
const
char
*
,
int
,
double
,
CvSize
,
int
)
{
return
false
;
}
#endif
void
CvCapture_GStreamer
::
close
()
{
if
(
pipeline
)
{
...
...
modules/highgui/src/gstappsink.cpp
deleted
100644 → 0
View file @
e7e72d24
/* GStreamer
* Copyright (C) 2007 David Schleef <ds@schleef.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#if 1
#include "precomp.hpp"
#include <gst/gst.h>
#include <gst/base/gstbasesink.h>
#include <gst/gstbuffer.h>
#include <string.h>
#include "gstappsink.h"
GST_DEBUG_CATEGORY
(
app_sink_debug
);
#define GST_CAT_DEFAULT app_sink_debug
static
const
GstElementDetails
app_sink_details
=
GST_ELEMENT_DETAILS
((
gchar
*
)
"AppSink"
,
(
gchar
*
)
"Generic/Sink"
,
(
gchar
*
)
"Allow the application to get access to raw buffer"
,
(
gchar
*
)
"David Schleef <ds@schleef.org>, Wim Taymans <wim.taymans@gmail.com"
);
enum
{
/* signals */
SIGNAL_EOS
,
SIGNAL_NEW_PREROLL
,
SIGNAL_NEW_BUFFER
,
/* acions */
SIGNAL_PULL_PREROLL
,
SIGNAL_PULL_BUFFER
,
LAST_SIGNAL
};
enum
{
PROP_0
,
PROP_CAPS
,
PROP_EOS
};
static
GstStaticPadTemplate
gst_app_sink_template
=
GST_STATIC_PAD_TEMPLATE
(
"sink"
,
GST_PAD_SINK
,
GST_PAD_ALWAYS
,
GST_STATIC_CAPS_ANY
);
static
void
gst_app_sink_dispose
(
GObject
*
object
);
static
void
gst_app_sink_finalize
(
GObject
*
object
);
static
void
gst_app_sink_set_property
(
GObject
*
object
,
guint
prop_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
);
static
void
gst_app_sink_get_property
(
GObject
*
object
,
guint
prop_id
,
GValue
*
value
,
GParamSpec
*
pspec
);
static
gboolean
gst_app_sink_start
(
GstBaseSink
*
psink
);
static
gboolean
gst_app_sink_stop
(
GstBaseSink
*
psink
);
static
gboolean
gst_app_sink_event
(
GstBaseSink
*
sink
,
GstEvent
*
event
);
static
GstFlowReturn
gst_app_sink_preroll
(
GstBaseSink
*
psink
,
GstBuffer
*
buffer
);
static
GstFlowReturn
gst_app_sink_render
(
GstBaseSink
*
psink
,
GstBuffer
*
buffer
);
static
GstCaps
*
gst_app_sink_getcaps
(
GstBaseSink
*
psink
);
static
guint
gst_app_sink_signals
[
LAST_SIGNAL
]
=
{
0
};
GST_BOILERPLATE
(
GstAppSink
,
gst_app_sink
,
GstBaseSink
,
GST_TYPE_BASE_SINK
);
static
gboolean
appsink_plugin_init
(
GstPlugin
*
plugin
)
{
GST_DEBUG_CATEGORY_INIT
(
app_sink_debug
,
"opencv-appsink"
,
0
,
"Application sink"
);
if
(
!
gst_element_register
(
plugin
,
"opencv-appsink"
,
GST_RANK_PRIMARY
,
gst_app_sink_get_type
()))
return
FALSE
;
return
TRUE
;
}
#undef PACKAGE
#define PACKAGE "highgui"
GST_PLUGIN_DEFINE_STATIC
(
GST_VERSION_MAJOR
,
GST_VERSION_MINOR
,
"opencv-appsink"
,
"Element application sink"
,
appsink_plugin_init
,
"0.1"
,
"LGPL"
,
"OpenCV's internal copy of gstappsink"
,
"OpenCV"
)
void
gst_app_marshal_OBJECT__VOID
(
GClosure
*
closure
,
GValue
*
return_value
,
guint
n_param_values
,
const
GValue
*
param_values
,
gpointer
invocation_hint
,
gpointer
marshal_data
)
{
typedef
GstBuffer
*
(
*
GMarshalFunc_OBJECT__VOID
)
(
gpointer
data1
,
gpointer
data2
);
register
GMarshalFunc_OBJECT__VOID
callback
;
register
GCClosure
*
cc
=
(
GCClosure
*
)
closure
;
register
gpointer
data1
,
data2
;
GstBuffer
*
v_return
;
//printf("appmarshalobject\n");
g_return_if_fail
(
return_value
!=
NULL
);
g_return_if_fail
(
n_param_values
==
1
);
if
(
G_CCLOSURE_SWAP_DATA
(
closure
))
{
data1
=
closure
->
data
;
data2
=
g_value_peek_pointer
(
param_values
+
0
);
}
else
{
data1
=
g_value_peek_pointer
(
param_values
+
0
);
data2
=
closure
->
data
;
}
callback
=
(
GMarshalFunc_OBJECT__VOID
)
(
marshal_data
?
marshal_data
:
cc
->
callback
);
v_return
=
callback
(
data1
,
data2
);
gst_value_take_buffer
(
return_value
,
v_return
);
}
static
void
gst_app_sink_base_init
(
gpointer
g_class
)
{
GstElementClass
*
element_class
=
GST_ELEMENT_CLASS
(
g_class
);
//printf("appsinkbaseinit\n");
GST_DEBUG_CATEGORY_INIT
(
app_sink_debug
,
"appsink"
,
0
,
"appsink element"
);
gst_element_class_set_details
(
element_class
,
&
app_sink_details
);
gst_element_class_add_pad_template
(
element_class
,
gst_static_pad_template_get
(
&
gst_app_sink_template
));
}
static
void
gst_app_sink_class_init
(
GstAppSinkClass
*
klass
)
{
GObjectClass
*
gobject_class
=
(
GObjectClass
*
)
klass
;
GstBaseSinkClass
*
basesink_class
=
(
GstBaseSinkClass
*
)
klass
;
//printf("appsinkclassinit\n");
gobject_class
->
dispose
=
gst_app_sink_dispose
;
gobject_class
->
finalize
=
gst_app_sink_finalize
;
gobject_class
->
set_property
=
gst_app_sink_set_property
;
gobject_class
->
get_property
=
gst_app_sink_get_property
;
g_object_class_install_property
(
gobject_class
,
PROP_CAPS
,
g_param_spec_boxed
(
"caps"
,
"Caps"
,
"The caps of the sink pad"
,
GST_TYPE_CAPS
,
(
GParamFlags
)
G_PARAM_READWRITE
));
g_object_class_install_property
(
gobject_class
,
PROP_EOS
,
g_param_spec_boolean
(
"eos"
,
"EOS"
,
"Check if the sink is EOS"
,
TRUE
,
G_PARAM_READABLE
));
/**
* GstAppSink::eos:
* @appsink: the appsink element that emitted the signal
*
* Signal that the end-of-stream has been reached.
*/
gst_app_sink_signals
[
SIGNAL_EOS
]
=
g_signal_new
(
"eos"
,
G_TYPE_FROM_CLASS
(
klass
),
G_SIGNAL_RUN_LAST
,
G_STRUCT_OFFSET
(
GstAppSinkClass
,
eos
),
NULL
,
NULL
,
g_cclosure_marshal_VOID__VOID
,
G_TYPE_NONE
,
0
,
G_TYPE_NONE
);
/**
* GstAppSink::new-preroll:
* @appsink: the appsink element that emitted the signal
* @buffer: the buffer that caused the preroll
*
* Signal that a new preroll buffer is available.
*/
gst_app_sink_signals
[
SIGNAL_NEW_PREROLL
]
=
g_signal_new
(
"new-preroll"
,
G_TYPE_FROM_CLASS
(
klass
),
G_SIGNAL_RUN_LAST
,
G_STRUCT_OFFSET
(
GstAppSinkClass
,
new_preroll
),
NULL
,
NULL
,
g_cclosure_marshal_VOID__OBJECT
,
G_TYPE_NONE
,
1
,
GST_TYPE_BUFFER
);
/**
* GstAppSink::new-buffer:
* @appsink: the appsink element that emitted the signal
* @buffer: the buffer that is available
*
* Signal that a new buffer is available.
*/
gst_app_sink_signals
[
SIGNAL_NEW_BUFFER
]
=
g_signal_new
(
"new-buffer"
,
G_TYPE_FROM_CLASS
(
klass
),
G_SIGNAL_RUN_LAST
,
G_STRUCT_OFFSET
(
GstAppSinkClass
,
new_buffer
),
NULL
,
NULL
,
g_cclosure_marshal_VOID__UINT
,
G_TYPE_NONE
,
1
,
G_TYPE_UINT
);
/**
* GstAppSink::pull-preroll:
* @appsink: the appsink element to emit this signal on
*
* Get the last preroll buffer on @appsink.
*/
gst_app_sink_signals
[
SIGNAL_PULL_PREROLL
]
=
g_signal_new
(
"pull-preroll"
,
G_TYPE_FROM_CLASS
(
klass
),
G_SIGNAL_RUN_LAST
,
G_STRUCT_OFFSET
(
GstAppSinkClass
,
pull_preroll
),
NULL
,
NULL
,
gst_app_marshal_OBJECT__VOID
,
GST_TYPE_BUFFER
,
0
,
G_TYPE_NONE
);
/**
* GstAppSink::pull-buffer:
* @appsink: the appsink element to emit this signal on
*
* Get the next buffer buffer on @appsink.
*/
gst_app_sink_signals
[
SIGNAL_PULL_PREROLL
]
=
g_signal_new
(
"pull-buffer"
,
G_TYPE_FROM_CLASS
(
klass
),
G_SIGNAL_RUN_LAST
,
G_STRUCT_OFFSET
(
GstAppSinkClass
,
pull_buffer
),
NULL
,
NULL
,
gst_app_marshal_OBJECT__VOID
,
GST_TYPE_BUFFER
,
0
,
G_TYPE_NONE
);
basesink_class
->
start
=
gst_app_sink_start
;
basesink_class
->
stop
=
gst_app_sink_stop
;
basesink_class
->
event
=
gst_app_sink_event
;
basesink_class
->
preroll
=
gst_app_sink_preroll
;
basesink_class
->
render
=
gst_app_sink_render
;
basesink_class
->
get_caps
=
gst_app_sink_getcaps
;
klass
->
pull_preroll
=
gst_app_sink_pull_preroll
;
klass
->
pull_buffer
=
gst_app_sink_pull_buffer
;
}
static
void
gst_app_sink_init
(
GstAppSink
*
appsink
,
GstAppSinkClass
*
klass
)
{
appsink
->
mutex
=
g_mutex_new
();
appsink
->
cond
=
g_cond_new
();
appsink
->
queue
=
g_queue_new
();
}
static
void
gst_app_sink_dispose
(
GObject
*
obj
)
{
GstAppSink
*
appsink
=
GST_APP_SINK
(
obj
);
GstBuffer
*
buffer
;
//printf("appsinkdispose\n");
if
(
appsink
->
caps
)
{
gst_caps_unref
(
appsink
->
caps
);
appsink
->
caps
=
NULL
;
}
if
(
appsink
->
preroll
)
{
gst_buffer_unref
(
appsink
->
preroll
);
appsink
->
preroll
=
NULL
;
}
g_mutex_lock
(
appsink
->
mutex
);
while
((
buffer
=
(
GstBuffer
*
)
g_queue_pop_head
(
appsink
->
queue
)))
gst_buffer_unref
(
buffer
);
g_mutex_unlock
(
appsink
->
mutex
);
G_OBJECT_CLASS
(
parent_class
)
->
dispose
(
obj
);
}
static
void
gst_app_sink_finalize
(
GObject
*
obj
)
{
GstAppSink
*
appsink
=
GST_APP_SINK
(
obj
);
g_mutex_free
(
appsink
->
mutex
);
g_cond_free
(
appsink
->
cond
);
g_queue_free
(
appsink
->
queue
);
G_OBJECT_CLASS
(
parent_class
)
->
finalize
(
obj
);
}
static
void
gst_app_sink_set_property
(
GObject
*
object
,
guint
prop_id
,
const
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstAppSink
*
appsink
=
GST_APP_SINK
(
object
);
//printf("appsinksetproperty\n");
switch
(
prop_id
)
{
case
PROP_CAPS
:
gst_app_sink_set_caps
(
appsink
,
gst_value_get_caps
(
value
));
break
;
default
:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
prop_id
,
pspec
);
break
;
}
}
static
void
gst_app_sink_get_property
(
GObject
*
object
,
guint
prop_id
,
GValue
*
value
,
GParamSpec
*
pspec
)
{
GstAppSink
*
appsink
=
GST_APP_SINK
(
object
);
//printf("appsinkgetproperty\n");
switch
(
prop_id
)
{
case
PROP_CAPS
:
{
GstCaps
*
caps
;
caps
=
gst_app_sink_get_caps
(
appsink
);
gst_value_set_caps
(
value
,
caps
);
if
(
caps
)
gst_caps_unref
(
caps
);
break
;
}
case
PROP_EOS
:
g_value_set_boolean
(
value
,
gst_app_sink_is_eos
(
appsink
));
break
;
default
:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
object
,
prop_id
,
pspec
);
break
;
}
}
static
void
gst_app_sink_flush_unlocked
(
GstAppSink
*
appsink
)
{
GstBuffer
*
buffer
;
//printf("appsinkflushunlocked\n");
GST_DEBUG_OBJECT
(
appsink
,
"flushing appsink"
);
appsink
->
is_eos
=
FALSE
;
gst_buffer_replace
(
&
appsink
->
preroll
,
NULL
);
while
((
buffer
=
(
GstBuffer
*
)
g_queue_pop_head
(
appsink
->
queue
)))
gst_buffer_unref
(
buffer
);
g_cond_signal
(
appsink
->
cond
);
}
static
gboolean
gst_app_sink_start
(
GstBaseSink
*
psink
)
{
GstAppSink
*
appsink
=
GST_APP_SINK
(
psink
);
//printf("appsinkstart\n");
g_mutex_lock
(
appsink
->
mutex
);
appsink
->
is_eos
=
FALSE
;
appsink
->
started
=
TRUE
;
GST_DEBUG_OBJECT
(
appsink
,
"starting"
);
g_mutex_unlock
(
appsink
->
mutex
);
return
TRUE
;
}
static
gboolean
gst_app_sink_stop
(
GstBaseSink
*
psink
)
{
GstAppSink
*
appsink
=
GST_APP_SINK
(
psink
);
//printf("appsinkstop\n");
g_mutex_lock
(
appsink
->
mutex
);
GST_DEBUG_OBJECT
(
appsink
,
"stopping"
);
appsink
->
started
=
FALSE
;
gst_app_sink_flush_unlocked
(
appsink
);
g_mutex_unlock
(
appsink
->
mutex
);
return
TRUE
;
}
static
gboolean
gst_app_sink_event
(
GstBaseSink
*
sink
,
GstEvent
*
event
)
{
GstAppSink
*
appsink
=
GST_APP_SINK
(
sink
);
//printf("appsinkevent\n");
switch
(
event
->
type
)
{
case
GST_EVENT_EOS
:
g_mutex_lock
(
appsink
->
mutex
);
GST_DEBUG_OBJECT
(
appsink
,
"receiving EOS"
);
appsink
->
is_eos
=
TRUE
;
g_cond_signal
(
appsink
->
cond
);
g_mutex_unlock
(
appsink
->
mutex
);
break
;
case
GST_EVENT_FLUSH_START
:
break
;
case
GST_EVENT_FLUSH_STOP
:
g_mutex_lock
(
appsink
->
mutex
);
GST_DEBUG_OBJECT
(
appsink
,
"received FLUSH_STOP"
);
gst_app_sink_flush_unlocked
(
appsink
);
g_mutex_unlock
(
appsink
->
mutex
);
break
;
default
:
break
;
}
return
TRUE
;
}
static
GstFlowReturn
gst_app_sink_preroll
(
GstBaseSink
*
psink
,
GstBuffer
*
buffer
)
{
GstAppSink
*
appsink
=
GST_APP_SINK
(
psink
);
//printf("appsinkpreroll\n");
g_mutex_lock
(
appsink
->
mutex
);
GST_DEBUG_OBJECT
(
appsink
,
"setting preroll buffer %p"
,
buffer
);
gst_buffer_replace
(
&
appsink
->
preroll
,
buffer
);
g_cond_signal
(
appsink
->
cond
);
g_mutex_unlock
(
appsink
->
mutex
);
g_signal_emit
(
psink
,
gst_app_sink_signals
[
SIGNAL_NEW_PREROLL
],
0
,
buffer
);
return
GST_FLOW_OK
;
}
static
GstFlowReturn
gst_app_sink_render
(
GstBaseSink
*
psink
,
GstBuffer
*
buffer
)
{
GstAppSink
*
appsink
=
GST_APP_SINK
(
psink
);
g_mutex_lock
(
appsink
->
mutex
);
GST_DEBUG_OBJECT
(
appsink
,
"pushing render buffer %p on queue"
,
buffer
);
g_queue_push_tail
(
appsink
->
queue
,
gst_buffer_ref
(
buffer
));
g_cond_signal
(
appsink
->
cond
);
// printf("appsinkrender, have %d buffers\n", g_queue_get_length(appsink->queue));
g_mutex_unlock
(
appsink
->
mutex
);
g_signal_emit
(
psink
,
gst_app_sink_signals
[
SIGNAL_NEW_BUFFER
],
0
,
g_queue_get_length
(
appsink
->
queue
));
return
GST_FLOW_OK
;
}
static
GstCaps
*
gst_app_sink_getcaps
(
GstBaseSink
*
psink
)
{
GstCaps
*
caps
;
//printf("appsinkgetcaps\n");
GstAppSink
*
appsink
=
GST_APP_SINK
(
psink
);
GST_OBJECT_LOCK
(
appsink
);
if
((
caps
=
appsink
->
caps
))
gst_caps_ref
(
caps
);
GST_DEBUG_OBJECT
(
appsink
,
"got caps %"
GST_PTR_FORMAT
,
caps
);
GST_OBJECT_UNLOCK
(
appsink
);
return
caps
;
}
/* external API */
/**
* gst_app_sink_set_caps:
* @appsink: a #GstAppSink
* @caps: caps to set
*
* Set the capabilities on the appsink element. This function takes
* a copy of the caps structure. After calling this method, the sink will only
* accept caps that match @caps. If @caps is non-fixed, you must check the caps
* on the buffers to get the actual used caps.
*/
void
gst_app_sink_set_caps
(
GstAppSink
*
appsink
,
const
GstCaps
*
caps
)
{
GstCaps
*
old
;
g_return_if_fail
(
appsink
!=
NULL
);
g_return_if_fail
(
GST_IS_APP_SINK
(
appsink
));
GST_OBJECT_LOCK
(
appsink
);
GST_DEBUG_OBJECT
(
appsink
,
"setting caps to %"
GST_PTR_FORMAT
,
caps
);
old
=
appsink
->
caps
;
if
(
caps
)
appsink
->
caps
=
gst_caps_copy
(
caps
);
else
appsink
->
caps
=
NULL
;
if
(
old
)
gst_caps_unref
(
old
);
GST_OBJECT_UNLOCK
(
appsink
);
}
/**
* gst_app_sink_get_caps:
* @appsink: a #GstAppSink
*
* Get the configured caps on @appsink.
*
* Returns: the #GstCaps accepted by the sink. gst_caps_unref() after usage.
*/
GstCaps
*
gst_app_sink_get_caps
(
GstAppSink
*
appsink
)
{
GstCaps
*
caps
;
g_return_val_if_fail
(
appsink
!=
NULL
,
NULL
);
g_return_val_if_fail
(
GST_IS_APP_SINK
(
appsink
),
NULL
);
GST_OBJECT_LOCK
(
appsink
);
if
((
caps
=
appsink
->
caps
))
gst_caps_ref
(
caps
);
GST_DEBUG_OBJECT
(
appsink
,
"getting caps of %"
GST_PTR_FORMAT
,
caps
);
GST_OBJECT_UNLOCK
(
appsink
);
return
caps
;
}
/**
* gst_app_sink_is_eos:
* @appsink: a #GstAppSink
*
* Check if @appsink is EOS, which is when no more buffers can be pulled because
* an EOS event was received.
*
* This function also returns %TRUE when the appsink is not in the PAUSED or
* PLAYING state.
*
* Returns: %TRUE if no more buffers can be pulled and the appsink is EOS.
*/
gboolean
gst_app_sink_is_eos
(
GstAppSink
*
appsink
)
{
gboolean
ret
;
g_return_val_if_fail
(
appsink
!=
NULL
,
FALSE
);
g_return_val_if_fail
(
GST_IS_APP_SINK
(
appsink
),
FALSE
);
g_mutex_lock
(
appsink
->
mutex
);
if
(
!
appsink
->
started
)
goto
not_started
;
if
(
appsink
->
is_eos
&&
g_queue_is_empty
(
appsink
->
queue
))
{
GST_DEBUG_OBJECT
(
appsink
,
"we are EOS and the queue is empty"
);
ret
=
TRUE
;
}
else
{
GST_DEBUG_OBJECT
(
appsink
,
"we are not yet EOS"
);
ret
=
FALSE
;
}
g_mutex_unlock
(
appsink
->
mutex
);
return
ret
;
not_started
:
{
GST_DEBUG_OBJECT
(
appsink
,
"we are stopped, return TRUE"
);
g_mutex_unlock
(
appsink
->
mutex
);
return
TRUE
;
}
}
/**
* gst_app_sink_pull_preroll:
* @appsink: a #GstAppSink
*
* Get the last preroll buffer in @appsink. This was the buffer that caused the
* appsink to preroll in the PAUSED state. This buffer can be pulled many times
* and remains available to the application even after EOS.
*
* This function is typically used when dealing with a pipeline in the PAUSED
* state. Calling this function after doing a seek will give the buffer right
* after the seek position.
*
* Note that the preroll buffer will also be returned as the first buffer
* when calling gst_app_sink_pull_buffer().
*
* If an EOS event was received before any buffers, this function returns
* %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
*
* This function blocks until a preroll buffer or EOS is received or the appsink
* element is set to the READY/NULL state.
*
* Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
*/
GstBuffer
*
gst_app_sink_pull_preroll
(
GstAppSink
*
appsink
)
{
GstBuffer
*
buf
=
NULL
;
//printf("pull_preroll\n");
g_return_val_if_fail
(
appsink
!=
NULL
,
NULL
);
g_return_val_if_fail
(
GST_IS_APP_SINK
(
appsink
),
NULL
);
g_mutex_lock
(
appsink
->
mutex
);
while
(
TRUE
)
{
GST_DEBUG_OBJECT
(
appsink
,
"trying to grab a buffer"
);
if
(
!
appsink
->
started
)
goto
not_started
;
if
(
appsink
->
preroll
!=
NULL
)
break
;
if
(
appsink
->
is_eos
)
goto
eos
;
/* nothing to return, wait */
GST_DEBUG_OBJECT
(
appsink
,
"waiting for the preroll buffer"
);
g_cond_wait
(
appsink
->
cond
,
appsink
->
mutex
);
}
buf
=
gst_buffer_ref
(
appsink
->
preroll
);
GST_DEBUG_OBJECT
(
appsink
,
"we have the preroll buffer %p"
,
buf
);
g_mutex_unlock
(
appsink
->
mutex
);
return
buf
;
/* special conditions */
eos
:
{
GST_DEBUG_OBJECT
(
appsink
,
"we are EOS, return NULL"
);
g_mutex_unlock
(
appsink
->
mutex
);
return
NULL
;
}
not_started
:
{
GST_DEBUG_OBJECT
(
appsink
,
"we are stopped, return NULL"
);
g_mutex_unlock
(
appsink
->
mutex
);
return
NULL
;
}
}
/**
* gst_app_sink_pull_buffer:
* @appsink: a #GstAppSink
*
* This function blocks until a buffer or EOS becomes available or the appsink
* element is set to the READY/NULL state.
*
* This function will only return buffers when the appsink is in the PLAYING
* state. All rendered buffers will be put in a queue so that the application
* can pull buffers at its own rate. Note that when the application does not
* pull buffers fast enough, the queued buffers could consume a lot of memory,
* especially when dealing with raw video frames.
*
* If an EOS event was received before any buffers, this function returns
* %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
*
* Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
*/
GstBuffer
*
gst_app_sink_pull_buffer
(
GstAppSink
*
appsink
)
{
GstBuffer
*
buf
=
NULL
;
//printf("pull_buffer\n");
g_return_val_if_fail
(
appsink
!=
NULL
,
NULL
);
g_return_val_if_fail
(
GST_IS_APP_SINK
(
appsink
),
NULL
);
g_mutex_lock
(
appsink
->
mutex
);
while
(
TRUE
)
{
GST_DEBUG_OBJECT
(
appsink
,
"trying to grab a buffer"
);
if
(
!
appsink
->
started
)
goto
not_started
;
if
(
!
g_queue_is_empty
(
appsink
->
queue
))
break
;
if
(
appsink
->
is_eos
)
goto
eos
;
/* nothing to return, wait */
GST_DEBUG_OBJECT
(
appsink
,
"waiting for a buffer"
);
g_cond_wait
(
appsink
->
cond
,
appsink
->
mutex
);
}
buf
=
(
GstBuffer
*
)
g_queue_pop_head
(
appsink
->
queue
);
GST_DEBUG_OBJECT
(
appsink
,
"we have a buffer %p"
,
buf
);
g_mutex_unlock
(
appsink
->
mutex
);
return
buf
;
/* special conditions */
eos
:
{
GST_DEBUG_OBJECT
(
appsink
,
"we are EOS, return NULL"
);
g_mutex_unlock
(
appsink
->
mutex
);
return
NULL
;
}
not_started
:
{
GST_DEBUG_OBJECT
(
appsink
,
"we are stopped, return NULL"
);
g_mutex_unlock
(
appsink
->
mutex
);
return
NULL
;
}
}
/**
* gst_app_sink_peek_buffer:
* @appsink: a #GstAppSink
*
* This function returns a buffer if there is one queued but does not block.
*
* This function will only return buffers when the appsink is in the PLAYING
* state. All rendered buffers will be put in a queue so that the application
* can pull buffers at its own rate. Note that when the application does not
* pull buffers fast enough, the queued buffers could consume a lot of memory,
* especially when dealing with raw video frames.
*
* If an EOS event was received before any buffers, this function returns
* %NULL. Use gst_app_sink_is_eos () to check for the EOS condition.
*
* Returns: a #GstBuffer or NULL when the appsink is stopped or EOS.
*/
GstBuffer
*
gst_app_sink_peek_buffer
(
GstAppSink
*
appsink
)
{
GstBuffer
*
buf
=
NULL
;
//printf("pull_buffer\n");
g_return_val_if_fail
(
appsink
!=
NULL
,
NULL
);
g_return_val_if_fail
(
GST_IS_APP_SINK
(
appsink
),
NULL
);
g_mutex_lock
(
appsink
->
mutex
);
GST_DEBUG_OBJECT
(
appsink
,
"trying to grab a buffer"
);
if
(
!
appsink
->
started
)
goto
not_started
;
if
(
g_queue_is_empty
(
appsink
->
queue
))
return
NULL
;
if
(
appsink
->
is_eos
)
goto
eos
;
/* nothing to return, wait */
buf
=
(
GstBuffer
*
)
g_queue_pop_head
(
appsink
->
queue
);
GST_DEBUG_OBJECT
(
appsink
,
"we have a buffer %p"
,
buf
);
g_mutex_unlock
(
appsink
->
mutex
);
return
buf
;
/* special conditions */
eos
:
{
GST_DEBUG_OBJECT
(
appsink
,
"we are EOS, return NULL"
);
g_mutex_unlock
(
appsink
->
mutex
);
return
NULL
;
}
not_started
:
{
GST_DEBUG_OBJECT
(
appsink
,
"we are stopped, return NULL"
);
g_mutex_unlock
(
appsink
->
mutex
);
return
NULL
;
}
}
guint
gst_app_sink_get_queue_length
(
GstAppSink
*
appsink
)
{
return
g_queue_get_length
(
appsink
->
queue
);
}
#endif
modules/highgui/src/gstappsink.h
deleted
100644 → 0
View file @
e7e72d24
/* GStreamer
* Copyright (C) 2007 David Schleef <ds@schleef.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _GST_APP_SINK_H_
#define _GST_APP_SINK_H_
#include <gst/gst.h>
#include <gst/base/gstbasesink.h>
G_BEGIN_DECLS
#define GST_TYPE_APP_SINK \
(gst_app_sink_get_type())
#define GST_APP_SINK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_APP_SINK,GstAppSink))
#define GST_APP_SINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_APP_SINK,GstAppSinkClass))
#define GST_IS_APP_SINK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_APP_SINK))
#define GST_IS_APP_SINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_APP_SINK))
typedef
struct
_GstAppSink
GstAppSink
;
typedef
struct
_GstAppSinkClass
GstAppSinkClass
;
struct
_GstAppSink
{
GstBaseSink
basesink
;
/*< private >*/
GstCaps
*
caps
;
GCond
*
cond
;
GMutex
*
mutex
;
GQueue
*
queue
;
GstBuffer
*
preroll
;
gboolean
started
;
gboolean
is_eos
;
};
struct
_GstAppSinkClass
{
GstBaseSinkClass
basesink_class
;
/* signals */
gboolean
(
*
eos
)
(
GstAppSink
*
sink
);
gboolean
(
*
new_preroll
)
(
GstAppSink
*
sink
);
gboolean
(
*
new_buffer
)
(
GstAppSink
*
sink
);
/* actions */
GstBuffer
*
(
*
pull_preroll
)
(
GstAppSink
*
sink
);
GstBuffer
*
(
*
pull_buffer
)
(
GstAppSink
*
sink
);
};
GType
gst_app_sink_get_type
(
void
);
GST_DEBUG_CATEGORY_EXTERN
(
app_sink_debug
);
void
gst_app_sink_set_caps
(
GstAppSink
*
appsink
,
const
GstCaps
*
caps
);
GstCaps
*
gst_app_sink_get_caps
(
GstAppSink
*
appsink
);
gboolean
gst_app_sink_is_eos
(
GstAppSink
*
appsink
);
GstBuffer
*
gst_app_sink_pull_preroll
(
GstAppSink
*
appsink
);
GstBuffer
*
gst_app_sink_pull_buffer
(
GstAppSink
*
appsink
);
GstBuffer
*
gst_app_sink_peek_buffer
(
GstAppSink
*
appsink
);
guint
gst_app_sink_get_queue_length
(
GstAppSink
*
appsink
);
G_END_DECLS
#endif
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment