gnomemm r1446 - in gstreamermm/trunk: . examples/media_player_gtkmm examples/ogg_player examples/ogg_player_gtkmm



Author: jaalburqu
Date: Tue Apr  8 05:57:17 2008
New Revision: 1446
URL: http://svn.gnome.org/viewvc/gnomemm?rev=1446&view=rev

Log:
2008-04-08  Josà Alburquerque  <jaalburqu svn gnome org>

	* examples/media_player_gtkmm/PlayerWindow.cc:
	* examples/media_player_gtkmm/PlayerWindow.h:
	* examples/media_player_gtkmm/main.cc: Modified media player example
	to use its own video sink with the playbin pipeline; Modified widget
	packing so that videoArea takes most space and rest less; Added code
	to react to initial data (buffer) received in the video sink pad to
	deal with size of videoArea.

Modified:
   gstreamermm/trunk/ChangeLog
   gstreamermm/trunk/examples/media_player_gtkmm/PlayerWindow.cc
   gstreamermm/trunk/examples/media_player_gtkmm/PlayerWindow.h
   gstreamermm/trunk/examples/media_player_gtkmm/main.cc
   gstreamermm/trunk/examples/ogg_player/   (props changed)
   gstreamermm/trunk/examples/ogg_player_gtkmm/   (props changed)

Modified: gstreamermm/trunk/examples/media_player_gtkmm/PlayerWindow.cc
==============================================================================
--- gstreamermm/trunk/examples/media_player_gtkmm/PlayerWindow.cc	(original)
+++ gstreamermm/trunk/examples/media_player_gtkmm/PlayerWindow.cc	Tue Apr  8 05:57:17 2008
@@ -23,7 +23,9 @@
 #include <gtkmm/filechooserdialog.h>
 #include <gdk/gdkx.h>
 #include <gstreamermm/bus.h>
+#include <gstreamermm/caps.h>
 #include <gstreamermm/clock.h>
+#include <gstreamermm/buffer.h>
 #include <gstreamermm/event.h>
 #include <gstreamermm/message.h>
 #include <gstreamermm/query.h>
@@ -34,8 +36,8 @@
 #include <iomanip>
 #include "PlayerWindow.h"
 
-PlayerWindow::PlayerWindow(Glib::RefPtr<Gst::Element> playbin,
-                                Glib::RefPtr<Gst::Pipeline> mainPipeline) :
+PlayerWindow::PlayerWindow(const Glib::RefPtr<Gst::Pipeline>& playbin,
+        const Glib::RefPtr<Gst::Element>& videoSink) :
 vBox(false, 5),
 progressLabel("000:00:00.000000000 / 000:00:00.000000000"),
 playButton(Gtk::Stock::MEDIA_PLAY),
@@ -48,10 +50,10 @@
     set_title("gstreamermm Media Player Example");
 
     add(vBox);
-    vBox.pack_start(videoArea);
-    vBox.pack_start(progressLabel);
-    vBox.pack_start(progressScale);
-    vBox.pack_start(buttonBox);
+    vBox.pack_start(videoArea, Gtk::PACK_EXPAND_WIDGET);
+    vBox.pack_start(progressLabel, Gtk::PACK_SHRINK);
+    vBox.pack_start(progressScale, Gtk::PACK_SHRINK);
+    vBox.pack_start(buttonBox, Gtk::PACK_SHRINK);
 
     progressLabel.set_alignment(Gtk::ALIGN_CENTER);
 
@@ -81,7 +83,7 @@
                                           &PlayerWindow::on_open));
 
     // get the bus from the pipeline
-    Glib::RefPtr<Gst::Bus> bus = mainPipeline->get_bus();
+    Glib::RefPtr<Gst::Bus> bus = playbin->get_bus();
 
     // Add a sync handler to receive synchronous messages from pipeline's
     // bus (this is done so that videoArea can be set up for drawing at an
@@ -101,7 +103,7 @@
     forwardButton.set_sensitive(false);
 
     this->playbin = playbin;
-    this->mainPipeline = mainPipeline;
+    this->videoSink = videoSink;
 
     show_all_children();
     pauseButton.hide();
@@ -127,14 +129,14 @@
 
     if (xoverlay)
     {
-        gulong xWindowId = GDK_WINDOW_XID(Glib::unwrap(videoArea.get_window()));
+        gulong xWindowId = GDK_WINDOW_XID(videoArea.get_window()->gobj());
         xoverlay->set_xwindow_id(xWindowId);
     }
 
     return Gst::BUS_DROP;
 }
 
-// This function is used to receive asynchronous messages from mainPipeline's bus
+// This function is used to receive asynchronous messages from playbin's bus
 bool PlayerWindow::on_bus_message(const Glib::RefPtr<Gst::Bus>& /* bus_not_used */,
 					const Glib::RefPtr<Gst::Message>& message)
 {
@@ -201,6 +203,30 @@
     return true;
 }
 
+bool PlayerWindow::on_video_pad_got_buffer(const Glib::RefPtr<Gst::Pad>& pad,
+        const Glib::RefPtr<Gst::MiniObject>& data)
+{
+    Glib::RefPtr<Gst::Buffer> buffer = Glib::RefPtr<Gst::Buffer>::cast_dynamic(data);
+
+    if (buffer) {
+        Glib::Value<int> widthValue;
+        Glib::Value<int> heightValue;
+
+        Glib::RefPtr<Gst::Caps> caps = buffer->get_caps();
+        caps->get_structure(0)->get_field("width", widthValue);
+        caps->get_structure(0)->get_field("height", heightValue);
+
+        videoArea.set_size_request(widthValue.get(), heightValue.get());
+        resize(1, 1);       // Resize to minimum when first playing by making size
+        check_resize();     // smallest then resizing according to video new size
+    }
+
+    pad->remove_buffer_probe(pad_probe_id);
+    pad_probe_id = 0; // Clear probe id to indicate that it has been removed
+
+    return true; // Keep buffer in pipeline (do not throw away)
+}
+
 void PlayerWindow::on_play(void)
 {
     progressScale.set_sensitive(true);
@@ -220,7 +246,7 @@
                              &PlayerWindow::update_stream_progress), 200);
 
     // set Gstmm pipeline to play mode
-	mainPipeline->set_state(Gst::STATE_PLAYING);
+	playbin->set_state(Gst::STATE_PLAYING);
 }
  
 void PlayerWindow::on_pause(void)
@@ -235,7 +261,7 @@
     progressConnection.disconnect();
     
     // set Gstmm pipeline to pause mode
-	mainPipeline->set_state(Gst::STATE_PAUSED);
+	playbin->set_state(Gst::STATE_PAUSED);
 }
  
 void PlayerWindow::on_stop(void)
@@ -255,16 +281,27 @@
     progressConnection.disconnect();
 
     // set Gstmm pipeline to inactive mode
-	mainPipeline->set_state(Gst::STATE_NULL);
+	playbin->set_state(Gst::STATE_NULL);
+
+    // reset display
     display_label_progress(0, duration);
     progressScale.set_value(0);
+
+    // Remove video sink pad buffer probe if after playing, probe id is
+    // not zero (means probe was not removed because media had no video and
+    // video_pad_got_buffer method never got a chance to remove probe)
+    if (pad_probe_id != 0)
+    {
+        videoSink->get_pad("sink")->remove_buffer_probe(pad_probe_id);
+        pad_probe_id  = 0;
+    }
 }
 
 bool PlayerWindow::on_scale_value_changed(Gtk::ScrollType /* type_not_used */, double value)
 {
     gint64 newPos = gint64(value * duration);
 
-    if (mainPipeline->seek(Gst::FORMAT_TIME, Gst::SEEK_FLAG_FLUSH, newPos))
+    if (playbin->seek(Gst::FORMAT_TIME, Gst::SEEK_FLAG_FLUSH, newPos))
     {
         display_label_progress(newPos, duration);
         return true;
@@ -283,13 +320,13 @@
     gint64 pos;
     Gst::Format fmt = Gst::FORMAT_TIME;
 
-    if (mainPipeline->query_position(fmt, pos))
+    if (playbin->query_position(fmt, pos))
     {
         gint64 newPos = (pos > skipAmount) ? (pos - skipAmount) : 0;
 
-        if (mainPipeline->seek(Gst::FORMAT_TIME, Gst::SEEK_FLAG_FLUSH, newPos)) {
-            display_label_progress(newPos, duration);
+        if (playbin->seek(Gst::FORMAT_TIME, Gst::SEEK_FLAG_FLUSH, newPos)) {
             progressScale.set_value(double(newPos) / duration);
+            display_label_progress(newPos, duration);
         }
         else
             std::cerr << "Could not seek!" << std::endl;
@@ -305,7 +342,7 @@
 
     Glib::RefPtr<Gst::Query> query = Gst::QueryPosition::create(fmt);
 
-    if (mainPipeline->query(query))
+    if (playbin->query(query))
     {
         Glib::RefPtr<Gst::QueryPosition> posQuery =
             Glib::RefPtr<Gst::QueryPosition>::cast_dynamic(query);
@@ -322,7 +359,7 @@
         Glib::RefPtr<Gst::EventSeek> seekEvent =
             Glib::RefPtr<Gst::EventSeek>::cast_dynamic(event);
 
-        if (mainPipeline->send_event(seekEvent))
+        if (playbin->send_event(seekEvent))
         {
             progressScale.set_value(double(newPos) / duration);
             display_label_progress(newPos, duration);
@@ -349,8 +386,22 @@
     if (response == Gtk::RESPONSE_OK) {
         workingDir = chooser.get_current_folder();
 
-        // Set filename property on the file source. Also add a message handler:
-        playbin->set_property("uri", chooser.get_uri());
+        // Set uri property on the playbin.
+        Glib::RefPtr<Gst::Element>::cast_dynamic(playbin)->
+                set_property("uri", chooser.get_uri());
+
+        // Resize videoArea and window to minimum when opening a file
+        videoArea.set_size_request(0, 0);
+        resize(1, 1);
+
+        // Add buffer probe to video sink pad when file is opened which will
+        // be removed after first buffer is received in on_video_pad_got_buffer
+        // method (if there's video).  When first buffer arrives, video
+        // size can be extracted.  If there's no video, probe will be
+        // removed when media stops in on_stop method
+        pad_probe_id = videoSink->get_pad("sink")->add_buffer_probe(
+            sigc::mem_fun(*this, &PlayerWindow::on_video_pad_got_buffer));
+
         set_title(Glib::filename_display_basename(chooser.get_filename()));
 
         playButton.set_sensitive(true);
@@ -363,8 +414,8 @@
     Gst::Format fmt = Gst::FORMAT_TIME;
     gint64 pos = 0;
 
-    if (mainPipeline->query_position(fmt, pos)
-    && mainPipeline->query_duration(fmt, duration)) {
+    if (playbin->query_position(fmt, pos)
+    && playbin->query_duration(fmt, duration)) {
         progressScale.set_value(double(pos) / duration);
         display_label_progress(pos, duration);
     }
@@ -394,5 +445,5 @@
 
 PlayerWindow::~PlayerWindow()
 {
-  mainPipeline->get_bus()->remove_watch(watch_id);
+  playbin->get_bus()->remove_watch(watch_id);
 }

Modified: gstreamermm/trunk/examples/media_player_gtkmm/PlayerWindow.h
==============================================================================
--- gstreamermm/trunk/examples/media_player_gtkmm/PlayerWindow.h	(original)
+++ gstreamermm/trunk/examples/media_player_gtkmm/PlayerWindow.h	Tue Apr  8 05:57:17 2008
@@ -35,8 +35,9 @@
 class PlayerWindow : public Gtk::Window
 {
 public:
-    PlayerWindow(Glib::RefPtr<Gst::Element> playbin,
-                 Glib::RefPtr<Gst::Pipeline> mainPipeline);
+    PlayerWindow(const Glib::RefPtr<Gst::Pipeline>& playbin,
+            const Glib::RefPtr<Gst::Element>& videoSink);
+
     ~PlayerWindow();
 protected:
     Gtk::VBox vBox;
@@ -58,6 +59,9 @@
     virtual bool on_bus_message(const Glib::RefPtr<Gst::Bus>& bus,
                             const Glib::RefPtr<Gst::Message>& message);
 
+    virtual bool on_video_pad_got_buffer(const Glib::RefPtr<Gst::Pad>& pad,
+                            const Glib::RefPtr<Gst::MiniObject>& buffer);
+
     virtual void on_play(void);
     virtual void on_pause(void);
     virtual void on_stop(void);
@@ -69,11 +73,12 @@
     bool update_stream_progress(void);
     void display_label_progress(gint64 pos, gint64 len);
 private:
-    Glib::RefPtr<Gst::Element> playbin;
-    Glib::RefPtr<Gst::Pipeline> mainPipeline;
+    Glib::RefPtr<Gst::Pipeline> playbin;
+    Glib::RefPtr<Gst::Element> videoSink;
     sigc::connection progressConnection;
-    unsigned int watch_id;
+    guint watch_id;
     gint64 duration;
+    gulong pad_probe_id;
 };
 
 #endif /* _PLAYERWINDOW_H */

Modified: gstreamermm/trunk/examples/media_player_gtkmm/main.cc
==============================================================================
--- gstreamermm/trunk/examples/media_player_gtkmm/main.cc	(original)
+++ gstreamermm/trunk/examples/media_player_gtkmm/main.cc	Tue Apr  8 05:57:17 2008
@@ -34,38 +34,31 @@
     Gtk::Main kit(argc, argv);
     Gst::init(argc, argv);
 
-    // Create the pipeline
-    Glib::RefPtr<Gst::Pipeline> pipeline = Gst::Pipeline::create("media-player");
-
     // Create the elements
 
     // Autoplays any media type.  Implements GstBase::XOverlay so accepts
     // a window id in which to draw video
-    Glib::RefPtr<Gst::Element> playbin = Gst::ElementFactory::create("playbin", "media-playbin");
+    Glib::RefPtr<Gst::Element> playbin = Gst::ElementFactory::create("playbin", "media-player");
+    Glib::RefPtr<Gst::Pipeline> playbinPipeline = Glib::RefPtr<Gst::Pipeline>::cast_dynamic(playbin);
 
-    if (!pipeline || !playbin)
-    {
-        std::cerr << "One element could not be created" << std::endl;
-        return -1;
-    }
+    // Video sink where video (if any) will be drawn
+    Glib::RefPtr<Gst::Element> videoSink = Gst::ElementFactory::create("ximagesink", "video-sink");
 
-    // Put elements in a pipeline:
-    try
+    if (!playbinPipeline || !videoSink)
     {
-        pipeline->add(playbin);
-    }
-    catch(const Glib::Error& ex)
-    {
-        std::cerr << "Error while adding elements to the pipeline: " << ex.what() << std::endl;
+        std::cerr << "One of the elements for media player could not be created." << std::endl;
         return -1;
     }
 
-    PlayerWindow mainWindow(playbin, pipeline);
+    // set the playbin's video-sink property so that videoSink is used for video display
+    playbinPipeline->set_property("video-sink", videoSink);
+
+    PlayerWindow mainWindow(playbinPipeline, videoSink);
 
     kit.run(mainWindow);
 
     // Clean up nicely:
-    pipeline->set_state(Gst::STATE_NULL);
+    playbinPipeline->set_state(Gst::STATE_NULL);
 
     return 0;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]