<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>