<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<div class="moz-text-flowed" style="font-family: -moz-fixed;
font-size: 13px;" lang="x-western">Hi Guys,
<br>
<br>
I've been hacking the source code for wxMediaCtrl to get it
working for a video capture card while displaying and saving the
output. It worked fine for v4l2src, but it doesn't work at all
the for decklinksrc.
<br>
<br>
The basic pipeline works with gst-launch, but the cpp version does
not work. This is the pipeline:
<br>
<br>
gst-launch -v decklinksrc connection = 3 mode=18 ! videoscale !
ffmpegcolorspace ! videobalance brightness=.3 contrast=.8 ! gamma
gamma=.5 ! tee name=videoTee videoTee. ! queue name=monitorQueue !
xvimagesink sync=false force-aspect-ratio=true videoTee. ! queue
name=fileQueue ! videorate ! video/x-raw-yuv,framerate=15/1 !
theoraenc quality=63 keyframe-force=1 ! oggmux ! filesink
location=video.ogg
<br>
<br>
I hope it matches the code!!!
<br>
<br>
Where have I slipped up? Your thoughts would be very much
appreciated.
<br>
<br>
The code follows, sorry about it's length <span
class="moz-smiley-s2" title=":("></span>
<br>
<br>
Regards
<br>
<br>
Steve
<br>
<br>
//-----------------------------------------------------------------------------
<br>
// wxGStreamerMediaBackend::DeviceCapture
<br>
//
<br>
// Used to Capture and store input from a local device (eg
/dev/video0) in a specified file.
<br>
//-----------------------------------------------------------------------------
<br>
bool wxGStreamerMediaBackend::DeviceCapture(wxControl* ctrl,
wxWindow* parent,
<br>
wxWindowID id,
<br>
const wxPoint& pos,
<br>
const wxSize& size,
<br>
long style,
<br>
const wxValidator&
validator,
<br>
const wxString& name)
<br>
{
<br>
printf ("mediactrl->DeviceCapture option
'wxID_HIGHEST'.\n");
<br>
<br>
// wxMutexLocker lock(m_asynclock); // lock state events and
async callbacks
<br>
<br>
//
<br>
//init gstreamer
<br>
//
<br>
<br>
//Convert arguments to unicode if enabled
<br>
#if wxUSE_UNICODE
<br>
int i;
<br>
char **argvGST = new char*[wxTheApp->argc + 1];
<br>
for ( i = 0; i < wxTheApp->argc; i++ )
<br>
{
<br>
argvGST[i] =
wxStrdupA(wxConvUTF8.cWX2MB(wxTheApp->argv[i]));
<br>
}
<br>
<br>
argvGST[wxTheApp->argc] = NULL;
<br>
<br>
int argcGST = wxTheApp->argc;
<br>
#else
<br>
#define argcGST wxTheApp->argc
<br>
#define argvGST wxTheApp->argv
<br>
#endif
<br>
<br>
//Really init gstreamer
<br>
gboolean bInited;
<br>
GError* error = NULL;
<br>
#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10
<br>
bInited = gst_init_check(&argcGST, &argvGST,
&error);
<br>
#else
<br>
bInited = gst_init_check(&argcGST, &argvGST);
<br>
#endif
<br>
<br>
// Cleanup arguments for unicode case
<br>
#if wxUSE_UNICODE
<br>
for ( i = 0; i < argcGST; i++ )
<br>
{
<br>
free(argvGST[i]);
<br>
}
<br>
<br>
delete [] argvGST;
<br>
#endif
<br>
<br>
if(!bInited) //gst_init_check fail?
<br>
{
<br>
if(error)
<br>
{
<br>
wxLogSysError(wxT("Could not initialize GStreamer\n")
<br>
wxT("Error Message:%s"),
<br>
(const wxChar*)
wxConvUTF8.cMB2WX(error->message)
<br>
);
<br>
g_error_free(error);
<br>
}
<br>
else
<br>
wxLogSysError(wxT("Could not initialize GStreamer"));
<br>
<br>
return false;
<br>
}
<br>
<br>
//
<br>
// wxControl creation
<br>
//
<br>
m_ctrl = wxStaticCast(ctrl, wxMediaCtrl);
<br>
<br>
#ifdef __WXGTK__
<br>
// We handle our own GTK expose events
<br>
m_ctrl->m_noExpose = true;
<br>
#endif
<br>
<br>
if( !m_ctrl->wxControl::Create(parent, id, pos, size,
<br>
style, // TODO: remove borders???
<br>
validator, name) )
<br>
{
<br>
wxFAIL_MSG(wxT("Could not create wxControl!!!"));
<br>
return false;
<br>
}
<br>
<br>
#ifdef __WXGTK__
<br>
// Turn off double-buffering so that
<br>
// so it doesn't draw over the video and cause sporadic
<br>
// disappearances of the video
<br>
gtk_widget_set_double_buffered(m_ctrl->m_wxwindow, FALSE);
<br>
#endif
<br>
<br>
// don't erase the background of our control window
<br>
// so that resizing is a bit smoother
<br>
m_ctrl->SetBackgroundStyle(wxBG_STYLE_CUSTOM);
<br>
// Ready video.
<br>
<br>
printf ("Create Pipeline method starts.\n");
<br>
<br>
//m_playbin-----------------------------------------------------------
<br>
// decklinksrc connection = 18 mode=3 !
<br>
// videoscale ! ffmpegcolorspace ! videobalance brightness=.3
contrast=.8 ! gamma gamma=.5 ! tee name=videoTee
<br>
// videoTee ! monitorQueue ! xvimagesink sync=false
force-aspect-ratio=true
<br>
// videoTee ! fileQueue ! videorate !
video/x-raw-yuv,framerate=15/1 ! theoraenc quality=63
keyframe-force=1 !
<br>
// oggmux ! filesink location=video.ogg
<br>
<br>
//
<br>
// Create DeviceCapture object
<br>
//
<br>
//GstElement *m_playbin;
<br>
GstElement *videoSrc, *videoScale, *colorSpace, *videoBalance,
*videoGamma, *videoTee;
<br>
GstElement *monitorQueue, *videoSink;
<br>
GstElement *fileQueue, *videoRate, *encoder, *muxer,
*fileSink;
<br>
//
<br>
// Create elements
<br>
//
<br>
m_playbin = gst_pipeline_new ("DeviceCapture m_playbin
subsitute");
<br>
if (!m_playbin) {
<br>
wxLogSysError(wxT("wxGStreamerMediaBackend::DeviceCapture
- ")
<br>
wxT("'m_playbin' could not be created."));
<br>
//g_printerr ("'m_playbin' could not be created.\n");
<br>
return NULL;
<br>
}
<br>
videoSrc = gst_element_factory_make ("decklinksrc",
"videoSrc");
<br>
if (!videoSrc) {
<br>
wxLogSysError(wxT("wxGStreamerMediaBackend::DeviceCapture
- ")
<br>
wxT ("'videoSrc' could not be created.\n"));
<br>
return NULL;
<br>
}
<br>
videoScale = gst_element_factory_make ("videoscale",
"videoScale");
<br>
if (!videoScale) {
<br>
wxLogSysError(wxT("wxGStreamerMediaBackend::DeviceCapture
- ")
<br>
wxT ("'videoScale' could not be created.\n"));
<br>
return NULL;
<br>
}
<br>
colorSpace = gst_element_factory_make ("ffmpegcolorspace",
"colorSpace");
<br>
if (!colorSpace) {
<br>
g_printerr ("'colorSpace' could not be created.\n");
<br>
return NULL;
<br>
}
<br>
videoBalance = gst_element_factory_make ("videobalance",
"videoBalance");
<br>
if (!videoBalance) {
<br>
wxLogSysError(wxT("wxGStreamerMediaBackend::DeviceCapture
- ")
<br>
wxT ("'videoBalance' could not be
created.\n"));
<br>
return NULL;
<br>
}
<br>
videoGamma = gst_element_factory_make ("gamma", "videoGamma");
<br>
if (!videoGamma) {
<br>
wxLogSysError(wxT("wxGStreamerMediaBackend::DeviceCapture
- ")
<br>
wxT ("'videoGamma' could not be created.\n"));
<br>
return NULL;
<br>
}
<br>
<br>
videoTee = gst_element_factory_make ("tee", "videoTee");
<br>
if (!videoTee) {
<br>
wxLogSysError(wxT("wxGStreamerMediaBackend::DeviceCapture
- ")
<br>
wxT ("'videoTee' could not be created.\n"));
<br>
return NULL;
<br>
}
<br>
monitorQueue = gst_element_factory_make ("queue",
"monitorQueue");
<br>
if (!monitorQueue) {
<br>
wxLogSysError(wxT("wxGStreamerMediaBackend::DeviceCapture
- ")
<br>
wxT ("'monitorQueue' could not be
created.\n"));
<br>
return NULL;
<br>
}
<br>
fileQueue = gst_element_factory_make ("queue", "fileQueue");
<br>
if (!fileQueue) {
<br>
wxLogSysError(wxT("wxGStreamerMediaBackend::DeviceCapture
- ")
<br>
wxT ("'fileQueue' could not be created.\n"));
<br>
return NULL;
<br>
}
<br>
videoRate = gst_element_factory_make ("videorate",
"videorate");
<br>
if (!videoRate) {
<br>
wxLogSysError(wxT("wxGStreamerMediaBackend::DeviceCapture
- ")
<br>
wxT ("'videoRate' could not be created.\n"));
<br>
return NULL;
<br>
}
<br>
encoder = gst_element_factory_make ("theoraenc",
"videoenc");
<br>
if (!encoder) {
<br>
wxLogSysError(wxT("wxGStreamerMediaBackend::DeviceCapture
- ")
<br>
wxT ("'encoder' could not be created.\n"));
<br>
return NULL;
<br>
}
<br>
muxer = gst_element_factory_make ("oggmux", "muxer");
<br>
if (!muxer) {
<br>
wxLogSysError(wxT("wxGStreamerMediaBackend::DeviceCapture
- ")
<br>
wxT ("'muxer' could not be created.\n"));
<br>
return NULL;
<br>
}
<br>
fileSink = gst_element_factory_make ("filesink", "fileSink");
<br>
if (!fileSink) {
<br>
wxLogSysError(wxT("wxGStreamerMediaBackend::DeviceCapture
- ")
<br>
wxT ("'fileSink' could not be created.\n"));
<br>
return NULL;
<br>
}
<br>
// Setup video sink - first try gconf, then auto, then xvimage
and
<br>
// then finally plain ximage
<br>
videoSink = gst_gconf_get_default_video_sink();
<br>
if( !TryVideoSink(videoSink) )
<br>
{
<br>
videoSink = gst_element_factory_make ("autovideosink",
"video-sink");
<br>
if( !TryVideoSink(videoSink) )
<br>
{
<br>
videoSink = gst_element_factory_make ("xvimagesink",
"video-sink");
<br>
if( !TryVideoSink(videoSink) )
<br>
{
<br>
// finally, do a final fallback to ximagesink
<br>
videoSink =
<br>
gst_element_factory_make ("ximagesink",
"video-sink");
<br>
if( !TryVideoSink(videoSink) )
<br>
{
<br>
g_object_unref(videoSink);
<br>
wxLogSysError(wxT("Could not find a suitable
video sink"));
<br>
return false;
<br>
}
<br>
}
<br>
}
<br>
}
<br>
// Error reporting
<br>
if (!m_playbin || !videoSrc || !videoScale || !colorSpace ||
!videoBalance || !videoGamma || !videoTee || !monitorQueue ||
!videoSink || !monitorQueue
<br>
|| !fileQueue || !videoRate || !encoder || !muxer||
!fileSink) {
<br>
wxLogSysError(wxT("wxGStreamerMediaBackend::DeviceCapture
- ")
<br>
wxT ("One element could not be created.\n"));
<br>
return NULL;
<br>
}
<br>
// Set paramaters for the GstElements
<br>
// Video source
<br>
g_object_set (G_OBJECT (videoSrc), "connection", 3, NULL);
<br>
// Queue-size default is 2, set to 1 to reduce latency;
<br>
g_object_set (G_OBJECT (videoSrc), "mode", 18, NULL);
<br>
// Colour settings for camera
<br>
g_object_set (G_OBJECT (videoBalance), "brightness", .3,
NULL);
<br>
g_object_set (G_OBJECT (videoBalance), "contrast", .8, NULL);
<br>
g_object_set (G_OBJECT (videoGamma), "gamma", .5, NULL);
<br>
// File location
<br>
g_object_set (G_OBJECT (fileSink), "location",
"/home/image/tmp_vid.ogg", NULL); // was .avi
<br>
// Encoder quality
<br>
g_object_set (G_OBJECT (encoder), "quality", 63, NULL);
<br>
// Encoder keyframe rate
<br>
g_object_set (G_OBJECT (encoder), "keyframe-force", 1, NULL);
<br>
// videoSink sync=false force-aspect-ratio=true
<br>
g_object_set (G_OBJECT (videoSink), "sync", false,
"force-aspect-ratio", true, NULL);
<br>
// g_object_set (G_OBJECT (videoSink), "sync", false, NULL);
<br>
// add elements to pipeline
<br>
gst_bin_add_many (GST_BIN (m_playbin),
<br>
videoSrc, videoScale, colorSpace, videoTee,
<br>
monitorQueue, videoSink,
<br>
fileQueue, videoRate, videoBalance, videoGamma, encoder,
muxer, fileSink, NULL);
<br>
// link elements.
<br>
if (!gst_element_link_many( videoSrc, videoScale, colorSpace,
videoBalance, videoGamma, videoTee, NULL )) {
<br>
g_warning ("Failed to link videoScale, colorSpace,
videoBalance, videoGamma and videoTee.");
<br>
}
<br>
if (!gst_element_link_many( videoTee, monitorQueue, videoSink,
NULL )) {
<br>
g_warning ("Failed to link videoTee, monitorQueue and
videoSink.");
<br>
}
<br>
if (!gst_element_link_many( videoTee, fileQueue, videoRate,
NULL )) {
<br>
g_warning ("Failed to link videoTee, fileQueue and
videoRate.");
<br>
}
<br>
// Create caps stuff
<br>
GstCaps *caps;
<br>
m_videoFps = 15;
<br>
caps = gst_caps_new_simple ("video/x-raw-yuv",
<br>
"framerate", GST_TYPE_FRACTION, 15, 1,
<br>
NULL);
<br>
if (!gst_element_link_filtered (videoRate, encoder, caps)) {
<br>
g_warning ("Failed to link videoRate and encoder.");
<br>
}
<br>
gst_caps_unref (caps);
<br>
if (!gst_element_link_many( encoder, muxer, fileSink, NULL
)) {
<br>
g_warning ("Failed to link encoder, muxer and fileSink.");
<br>
}
<br>
if (!GST_IS_ELEMENT(m_playbin))
<br>
{
<br>
if(G_IS_OBJECT(m_playbin))
<br>
g_object_unref(m_playbin);
<br>
wxLogSysError(wxT("Got an invalid bin"));
<br>
return false;
<br>
}
<br>
<br>
// Set playbin to ready
<br>
if( gst_element_set_state (m_playbin, GST_STATE_READY) ==
<br>
GST_STATE_FAILURE || !SyncStateChange(m_playbin,
GST_STATE_READY))
<br>
{
<br>
wxLogSysError(wxT("wxGStreamerMediaBackend::DeviceCapture
- ")
<br>
wxT("Could not set initial state to paused"));
<br>
return false;
<br>
}
<br>
<br>
printf ("Playbin set.\n");
<br>
<br>
#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR < 10
<br>
// Connect the glib events/callbacks we want to our playbin
<br>
g_signal_connect(m_playbin, "eos",
<br>
G_CALLBACK(gst_finish_callback), this);
<br>
g_signal_connect(m_playbin, "error",
<br>
G_CALLBACK(gst_error_callback), this);
<br>
g_signal_connect(m_playbin, "state-change",
<br>
G_CALLBACK(gst_state_change_callback), this);
<br>
#else
<br>
<br>
// GStreamer 0.10+ uses GstBus for this now, connect to the
sync
<br>
// handler as well so we can set the X window id of our
xoverlay
<br>
gst_bus_add_watch (gst_element_get_bus(m_playbin),
<br>
(GstBusFunc) gst_bus_async_callback, this);
<br>
gst_bus_set_sync_handler(gst_element_get_bus(m_playbin),
<br>
(GstBusSyncHandler)
gst_bus_sync_callback, this);
<br>
g_signal_connect(m_playbin, "notify::stream-info",
<br>
G_CALLBACK(gst_notify_stream_info_callback),
this);
<br>
#endif
<br>
<br>
#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR < 10
<br>
// Not on 0.10... called when video size changes
<br>
g_signal_connect(m_xoverlay, "desired-size-changed",
<br>
G_CALLBACK(gst_desired_size_changed_callback), this);
<br>
#endif
<br>
// Tell GStreamer which window to draw to in 0.8 - 0.10
<br>
// sometimes needs this too...
<br>
SetupXOverlay();
<br>
printf ("Control created.\n");
<br>
<br>
m_eventHandler = new wxGStreamerMediaEventHandler(this);
<br>
return true;
<br>
}
<br>
<br>
<br>
</div>
</body>
</html>