#!/usr/bin/perl use strict; use warnings; use utf8; use Glib qw(TRUE FALSE); use GStreamer -init; # eingabe datei my $file='test.avi'; # ausgabe datei my $ofile='test.jpg'; # position im video my $pos=3_000_000_000; # ns # höhe /breite my $scale_w=720; my $scale_h=510; my @scales; push(@scales,"width=$scale_w") if($scale_w); push(@scales,"height=$scale_h") if($scale_h); #pipeline erzeugen my $pipeline = GStreamer::parse_launch(sprintf( 'filesrc location=%s ! avidemux name=data_demux '. 'data_demux.audio_00 ! queue ! fakesink '. 'data_demux.video_00 ! decodebin name=video_decode ! ffmpegcolorspace '. '! videoscale ! video/x-raw-yuv,%s ! jpegenc ! fakesink name=video_sink signal-handoffs=TRUE ', $file,join(',',@scales))); # der pipeline einen Namen geben $pipeline->set_name('my_pipeline'); # Puffer für die Ausgabe my $buffer=undef; # Listener für Frame einrichten my $video_sink=$pipeline->get_by_name('video_sink'); $video_sink->signal_connect(handoff => sub{ return TRUE if($buffer); my $query=GStreamer::Query::Position->new('time'); $video_sink->query($query); my (undef, $pos_now)=$query->position; return TRUE if($pos_now<$pos); $buffer=$_[1]; return TRUE; }); # video abspielen $pipeline->set_state("playing"); my $seek=1; my $bus=$pipeline->get_bus(); while (1) { # alle nahrichten vom bus holen my $message = $bus -> poll("any", 0); # Schleife beenden wenn wir ein Bild haben last if($buffer); # wenn keine Nachrichten warten unless (defined $message) { select(undef,undef,undef,0.25); next; } # beenden wenn das Video am Ende ist, # oder ein Fehler auftrat last if ( $message->type & "eos" || $message->type & "error" || $message->type & "warning" ); # wenn sich det Zusand eines pileelemts geändert hat if($message->type & "state-changed") { # Name des Elementes ermitteln my $name=$message->src()->get_name() || 'UNDEF'; #print "$name => ".$message->new_state()."\n"; # es wurde noch nicht zu der stelle gespringen, # der Name stimmt und die pipeline ist "playing" if($seek && $name eq 'my_pipeline' && $message->new_state() eq 'playing') { # zur gewünschten Stelle springen $pipeline->seek(1,'time','flush','set',$pos,'none',0) || last; $seek--; } } } # pipeline stoppen $pipeline->set_state("null"); # wenn ein bild da ist if($buffer) { # bild in Datei schreiben. open(my $fh, '>', $ofile) or die("Error open $ofile! ($!)"); binmode($fh); print $fh $buffer->data(); close($fh); }