Permalink
Browse files

1

  • Loading branch information...
0 parents commit ef4792211e1fd05f23668ca28cf94648407824a8 @zpmorgan committed Jan 15, 2012
Showing with 252 additions and 0 deletions.
  1. +2 −0 .gitignore
  2. +16 −0 dist.ini
  3. +103 −0 examine_av.pl
  4. +110 −0 lib/PDL/GStreamer.pm
  5. +21 −0 screenshot_imag2d.pl
@@ -0,0 +1,2 @@
+*.swp
+
@@ -0,0 +1,16 @@
+name = PDL-GStreamer
+author = Zach Morgan <zpmorgan@gmail.com>
+license = Perl_5
+copyright_holder = Zach Morgan
+copyright_year = 2012
+
+version = 0.001
+
+[Prereqs]
+MooseX::Types::Path::Class = 0
+PDL = 0
+Glib = 0
+GStreamer = 0
+
+
+[@Basic]
@@ -0,0 +1,103 @@
+#!/usr/bin/perl
+use Modern::Perl;
+use Glib qw/TRUE FALSE /;
+use GStreamer qw/-init GST_TIME_FORMAT GST_SECOND/;
+
+my $filename = shift @ARGV;
+die 'nofile' unless $filename;
+
+use Cwd 'abs_path';
+$filename = abs_path $filename;
+die 'notfound' unless -e $filename;
+
+# frame positioning?
+#
+my $GST_SEEK_FLAG_ACCURATE = 1<<1;
+my $player;
+my $audio_sink;
+my $video_sink;
+
+
+
+# (from totem thumbnailer) /* our desired output format (RGB24) */
+ #/* Note: we don't ask for a specific width/height here, so that
+ #* videoscale can adjust dimensions from a non-1/1 pixel aspect
+ #* ratio to a 1/1 pixel-aspect-ratio. We also don't ask for a
+ #* specific framerate, because the input framerate won't
+ #* necessarily match the output framerate if there's a deinterlacer
+ #* in the pipeline. */
+my $img_caps = GStreamer::Caps::Simple->new ("video/x-raw-rgb",
+ "bpp", "Glib::Int", 24,
+ "depth", 'Glib::Int', 24,
+ "pixel-aspect-ratio", 'GStreamer::Fraction', [1, 1],
+ #"endianness", 'Glib::Int', 'G_BIG_ENDIAN',
+ "red_mask", 'Glib::Int', 0xff0000,
+ "green_mask", 'Glib::Int', 0x00ff00,
+ "blue_mask", 'Glib::Int', 0x0000ff,
+);
+
+
+# http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/chapter-elements.html
+
+sub setup_player{
+ $player = GStreamer::ElementFactory -> make(playbin2 => "player");
+ # http://git.gnome.org/browse/totem/tree/src/totem-video-thumbnailer.c
+ # http://git.gnome.org/browse/totem/tree/src/gst/totem-gst-helpers.c
+ $audio_sink = GStreamer::ElementFactory->make ("fakesink", "audio-fake-sink");
+ $video_sink = GStreamer::ElementFactory->make ("fakesink", "video-fake-sink");
+ #g_object_set (video_sink, "sync", TRUE, NULL);
+ $video_sink->set("sync", TRUE);
+
+ $player->set(
+ "audio-sink" => $audio_sink,
+ # "video-sink" => $video_sink,
+ #"flags" => [qw/ GST_PLAY_FLAG_VIDEO GST_PLAY_FLAG_AUDIO /],
+ );
+}
+
+sub seek_to_random_frame{
+ # actually seek to 500 seconds.
+ my $foo = $player->seek (
+ 1, #rate
+ "GST_FORMAT_TIME", #3, #format. GST_FORMAT_TIME(), #format
+ "GST_SEEK_FLAG_ACCURATE", #flags
+ "GST_SEEK_TYPE_SET" , #GST_SEEK_TYPE_SET -- absolute position is requested
+ 500*GST_SECOND, #cur
+ "GST_SEEK_TYPE_NONE", #stop_type. GST_SEEK_TYPE_NONE.
+ #510*GST_SECOND, #stop. 0 i guess?
+ -1,
+ );
+
+ # /* And wait for this seek to complete */
+ $player->get_state(-1);#, NULL, NULL, GST_CLOCK_TIME_NONE);
+ #gboolean gst_element_seek (GstElement *element, gdouble rate, GstFormat format, GstSeekFlags flags, GstSeekType cur_type, gint64 cur, GstSeekType stop_type, gint64 stop);
+ ;
+}
+
+sub dump_screenshot{
+# my $buf = GSignal->emit_by_name($player, 'convert-frame', $img_caps);
+ my $buf = $player->signal_emit ('convert-frame', $img_caps);
+ sleep(1);
+ die $buf;
+}
+
+my $loop = Glib::MainLoop -> new(undef, FALSE);
+setup_player();
+
+$player -> set(uri => Glib::filename_to_uri $filename, "localhost");
+#$player -> get_bus() -> add_watch(\&my_bus_callback, $loop);
+
+print "Playing: $filename\n";
+
+$player -> set_state("playing") or die "Could not start playing";
+ sleep(1);
+seek_to_random_frame();
+
+dump_screenshot();
+
+if (1){
+ sleep(1);
+ $loop -> run();
+ $player -> set_state("null");
+}
+
@@ -0,0 +1,110 @@
+package PDL::GStreamer;
+use Moose 'has';
+use MooseX::Types::Path::Class;
+use PDL;
+use GStreamer qw/ -init GST_SECOND /;
+use Glib qw/TRUE FALSE/;
+
+#my $appsinkplugin = GStreamer::Plugin::load_by_name('app');
+#die unless $appsinkplugin->get_description;
+
+# http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/section-data-spoof.html
+
+has filename => (
+ is => 'ro',
+ isa => 'Path::Class::File',
+ coerce => 1,
+ required => 1,
+);
+
+has player => (
+ builder => '_mk_player',
+ lazy => 1,
+ is => 'ro',
+ isa => 'GStreamer::Pipeline',
+);
+
+has _audiosink => (
+ is => 'rw',
+ #seems like this 'isa' could break.
+ #isa => 'Glib::Object::_Unregistered::GstFakeSink',
+ required => 0,
+);
+has _videosink => (
+ is => 'rw',
+ #seems like this 'isa' could break.
+ #isa => 'Glib::Object::_Unregistered::GstFakeSink',
+ required => 0,
+);
+
+sub _mk_player{
+ my $self = shift;
+ my $player = GStreamer::ElementFactory -> make(playbin2 => "player");
+ # http://git.gnome.org/browse/totem/tree/src/totem-video-thumbnailer.c
+ # http://git.gnome.org/browse/totem/tree/src/gst/totem-gst-helpers.c
+ my $audio_sink = GStreamer::ElementFactory->make ("fakesink", "audio-fake-sink");
+ #my $video_sink = GStreamer::ElementFactory->make ("fakesink", "video-fake-sink");
+ my $video_sink = GStreamer::ElementFactory->make ("fakesink", "video-app-sink");
+ $video_sink->set("sync", TRUE);
+ $self->_audiosink($audio_sink);
+ $self->_videosink($video_sink);
+
+ $player->set(
+ "audio-sink" => $audio_sink,
+ "video-sink" => $video_sink,
+ "flags" => [qw/ video audio /],# GST_PLAY_FLAG_VIDEO GST_PLAY_FLAG_AUDIO /],
+ );
+ $player -> set(uri => Glib::filename_to_uri $self->filename, "localhost");
+ return $player;
+}
+
+sub image_caps{
+ my $self = shift;
+ # (from totem thumbnailer) /* our desired output format (RGB24) */
+ #/* Note: we don't ask for a specific width/height here, so that
+ #* videoscale can adjust dimensions from a non-1/1 pixel aspect
+ #* ratio to a 1/1 pixel-aspect-ratio. We also don't ask for a
+ #* specific framerate, because the input framerate won't
+ #* necessarily match the output framerate if there's a deinterlacer
+ #* in the pipeline. */
+ my $img_caps = GStreamer::Caps::Simple->new ("video/x-raw-rgb",
+ "bpp", "Glib::Int", 24,
+ "depth", 'Glib::Int', 24,
+ "pixel-aspect-ratio", 'GStreamer::Fraction', [1, 1],
+ #"endianness", 'Glib::Int', 'G_BIG_ENDIAN',
+ "red_mask", 'Glib::Int', 0xff0000,
+ "green_mask", 'Glib::Int', 0x00ff00,
+ "blue_mask", 'Glib::Int', 0x0000ff,
+ );
+ return $img_caps;
+}
+
+
+sub seek{
+ my ($self,$time) = @_;
+ my $ok = $self->player->seek(
+ 1, #rate
+ "time", #3, #format. GST_FORMAT_TIME(), #format
+ [qw/accurate/],#"GST_SEEK_FLAG_ACCURATE", #flags
+ "set" , #GST_SEEK_TYPE_SET -- absolute position is requested
+ $time * GST_SECOND, #cur
+ "none", #stop_type. GST_SEEK_TYPE_NONE.
+ -1, # stop.
+ );
+ $self->player->get_state(-1);
+ die 'seek not handled correctly?' unless $ok;
+}
+
+sub capture_image{
+ my $self = shift;
+# my $buf = $self->_videosink->pull_preroll();
+ #$self->player->set_state('playing');
+ my @foo = $self->player->get_state(-1);
+ #die @foo;
+ my $buf = $self->player->signal_emit ('convert-frame', $self->image_caps);
+ die $buf;
+}
+
+
+
+'excelloriffying';
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+use Modern::Perl;
+use lib 'lib';
+use PDL::GStreamer;
+use PDL;
+use PDL::Graphics2D 'imag2d';
+
+#to run: ./screenshot_imag2d.pl blah.avi
+
+my $filename = shift @ARGV;
+
+my $noir = PDL::GStreamer->new(
+ filename => $filename,
+ #time => 500,
+);
+
+$noir->seek(500); #seconds
+my $screenshot = $noir->capture_image;
+imag2d($screenshot);
+
+

0 comments on commit ef47922

Please sign in to comment.