Steve_BZ has asked for the wisdom of the Perl Monks concerning the following question:
Hi Guys,
Update: I should have added that the code runs nicely on Windows and Linux. The problems on Windows aren't quite the same. 1 & 3 don't occur and 2 does not have the correct camera URI for Windows.
Following the continuing saga of Wx::MediaCtrl on Linux (Kubuntu 10.4). The following is a piece of code which demonstrates the following issues (among others):
I suspect the underlying GStreamerMediaBackend.cpp, so I'm about to try to do a native (C++) build of the C++ samples and try to debug it. However in the meantime any encouraging noises or support would be welcome.
Code follows.
Regards
Steve.
#!/usr/bin/perl -w -- use Wx 0.15 qw[:allclasses]; use strict; package MyFrame; use Wx qw[:everything]; use base qw(Wx::Frame); use strict; sub new { my( $self, $parent, $id, $title, $pos, $size, $style, $name ) = @_ +; $style = wxDEFAULT_FRAME_STYLE unless defined $style; $self = $self->SUPER::new( undef, wxID_ANY, "Draw/Video Controls", + wxDefaultPosition, wxDefaultSize, $style, "" ); $self->SetTitle("Draw/Video Controls"); # # Wx::Timer # $self->{TIMER} = Wx::Timer->new( $self, 1 ); $self->{TIMER}->Start( 200 ); Wx::Event::EVT_TIMER( $self, 1, \&on_timer ); # Events # Wx::Event::EVT_SCROLL_THUMBTRACK( $self, \&on_slider ); # Define parents of split $self->{Ctl_Post_Exam_Videos_Sizer_2} = Wx::BoxSizer->new(wxVERTIC +AL); # Top-level left-hand sizer (contains media) # # Video panel. # # wxMEDIABACKEND_DIRECTSHOW Use ActiveMovie/DirectShow. Requires w +xUSE_DIRECTSHOW to be enabled, requires linkage with the static libra +ry strmiids.lib, and is available on Windows Only. # wxMEDIABACKEND_QUICKTIME Use QuickTime. Windows and Mac Only. NO +TE: On Mac Systems lower than OSX 10.2 this defaults to emulating win +dow positioning and suffers from several bugs, including not working +correctly embedded in a wxNotebook. # wxMEDIABACKEND_MCI Use Media Command Interface. Windows Only +. # wxMEDIABACKEND_GSTREAMER Use GStreamer. Unix Only. # wxMEDIABACKEND_WMP10 Windows Media Player 9 or 10 # wxMEDIABACKEND_REALPLAYER Realplayer # Blank Allow to choose own player $self->{Ctl_Videos_Media}= Wx::MediaCtrl->new( $self, wxID_ANY, '' +, wxDefaultPosition, wxDefaultSize,0, ); $self->{Ctl_Videos_Media}->Show( 1 ); $self->{Ctl_Videos_Media}->ShowPlayerControls(wxMEDIACTRLPLAYERCON +TROLS_NONE); # or wxMEDIACTRLPLAYERCONTROLS_NONE # wxMEDIACTRLPLAYERCONTROLS_STEP # wxMEDIACTRLPLAYERCONTROLS_VOLUME # wxMEDIACTRLPLAYERCONTROLS_DEFAULT $self->{Ctl_Post_Exam_Videos_Sizer_2}->Add( $self->{Ctl_Videos_Med +ia}, 1, wxEXPAND|wxALL, 5 ); # # Draw Slider and end labels # $self->{Ctl_Media_Slider_Szr} = Wx::BoxSizer->new(wxHORIZONTAL); + # second-level left-hand sizer (contains slider) my $loc_post_exam_videos_panel=$self; $self->{Ctl_Media_Slider_Start_Lbl} = Wx::StaticText-> new($loc_po +st_exam_videos_panel, wxID_ANY, "0", wxDefaultPosition, wxDefaultSize +, ); $self->{Ctl_Media_Slider_Szr}->Add($self->{Ctl_Media_Slider_Start_ +Lbl}, 0, 0, 0); $self->{Ctl_Media_Slider_Sld} = Wx::Slider-> new($loc_post_exam_vi +deos_panel, wxID_ANY, 0, 0, 10, wxDefaultPosition, wxDefaultSize, wxS +L_HORIZONTAL); # |wxSL_AUTOTICKS|wxSL_LABELS $self->{Ctl_Media_Slider_Sld}->SetMinSize(Wx::Size->new(300, -1)); $self->{Ctl_Media_Slider_Sld}->SetToolTipString(("Drag slider to r +e-position video.")); $self->{Ctl_Media_Slider_Szr}->Add($self->{Ctl_Media_Slider_Sld}, +0, 0, 0); $self->{Ctl_Media_Slider_End_Lbl} = Wx::StaticText-> new($loc_post +_exam_videos_panel, wxID_ANY, "100", wxDefaultPosition, wxDefaultSize +, ); $self->{Ctl_Media_Slider_Szr}->Add($self->{Ctl_Media_Slider_End_Lb +l}, 0, 0, 0); # # Draw buttons # $self->{Ctl_Media_Button_Szr} = Wx::BoxSizer->new(wxHORIZONTAL); + # third-level left-hand sizer (contains buttons) $self->{Ctl_Media_Rewind_Btn} = Wx::Button-> new($loc_post_exam_vi +deos_panel, wxID_ANY, "<<", wxDefaultPosition, [40,-1] ); $self->{Ctl_Media_Rewind_Btn}->SetSize($self->{Ctl_Media_Rewind_Bt +n}->GetBestSize()); $self->{Ctl_Media_Button_Szr}->Add($self->{Ctl_Media_Rewind_Btn}, +0, 0, 2); $self->{Ctl_Media_Rewind_Btn}->Enable(1); $self->{Ctl_Media_Rewind_Btn}->SetToolTipString(("Rewinds 30 secon +ds.")); Wx::Event::EVT_BUTTON( $self, $self->{Ctl_Media_Rewind_Btn}, \&on_ +media_rw ); $self->{Ctl_Media_Play_Btn} = Wx::Button-> new($loc_post_exam_vide +os_panel, wxID_ANY, ">", wxDefaultPosition, [40,-1] ); $self->{Ctl_Media_Play_Btn}->SetSize($self->{Ctl_Media_Play_Btn}-> +GetBestSize()); $self->{Ctl_Media_Play_Btn}->Enable(1); $self->{Ctl_Media_Play_Btn}->SetToolTipString(("Play/resume media +clip.")); Wx::Event::EVT_BUTTON( $self, $self->{Ctl_Media_Play_Btn}, \&on_me +dia_play ); $self->{Ctl_Media_Button_Szr}->Add($self->{Ctl_Media_Play_Btn}, 0, + 0, 2); $self->{Ctl_Media_Pause_Btn} = Wx::Button-> new($loc_post_exam_vid +eos_panel, wxID_ANY, "||", wxDefaultPosition, [40,-1] ); $self->{Ctl_Media_Pause_Btn}->SetSize($self->{Ctl_Media_Pause_Btn} +->GetBestSize()); $self->{Ctl_Media_Button_Szr}->Add($self->{Ctl_Media_Pause_Btn}, 0 +, 0, 2); $self->{Ctl_Media_Pause_Btn}->Enable(1); $self->{Ctl_Media_Pause_Btn}->SetToolTipString(("Pause media clip. +")); Wx::Event::EVT_BUTTON( $self, $self->{Ctl_Media_Pause_Btn}, \&on_m +edia_pause ); $self->{Ctl_Media_Record_Btn} = Wx::Button-> new($loc_post_exam_vi +deos_panel, wxID_ANY, "Record", wxDefaultPosition, [40,-1] ); $self->{Ctl_Media_Record_Btn}->SetSize($self->{Ctl_Media_Record_Bt +n}->GetBestSize()); $self->{Ctl_Media_Button_Szr}->Add($self->{Ctl_Media_Record_Btn}, +0, 0, 2); $self->{Ctl_Media_Record_Btn}->Show(0); # Set to 1 +or zero depending on whether you are debugging or not. $self->{Ctl_Media_Record_Btn}->Enable(1); $self->{Ctl_Media_Record_Btn}->SetToolTipString(("Press red button + to start record of media clip. Press black button to complete.")); $self->{Ctl_Media_Ffwd_Btn} = Wx::Button-> new($loc_post_exam_vide +os_panel, wxID_ANY, ">>", wxDefaultPosition, [40,-1] ); $self->{Ctl_Media_Ffwd_Btn}->SetSize($self->{Ctl_Media_Ffwd_Btn}-> +GetBestSize()); $self->{Ctl_Media_Ffwd_Btn}->Enable(1); $self->{Ctl_Media_Ffwd_Btn}->SetToolTipString(("Forwards 30 second +s.")); $self->{Ctl_Media_Button_Szr}->Add($self->{Ctl_Media_Ffwd_Btn}, 0, + 0, 2); Wx::Event::EVT_BUTTON( $self, $self->{Ctl_Media_Ffwd_Btn}, \&on_me +dia_ff ); $self->{Ctl_Media_Open_Btn} = Wx::Button-> new($loc_post_exam_vide +os_panel, wxID_ANY, "Open", wxDefaultPosition, wxDefaultSize ); $self->{Ctl_Media_Open_Btn}->Show(1); # Set to 1 or + zero depending on whether you are debugging or not. $self->{Ctl_Media_Open_Btn}->SetToolTipString(("Press to open prev +ious clip. Clip is saved in media folder.")); $self->{Ctl_Media_Open_Btn}->SetSize($self->{Ctl_Media_Open_Btn}-> +GetBestSize()); $self->{Ctl_Media_Button_Szr}->Add($self->{Ctl_Media_Open_Btn}, 0, + 0, 2); Wx::Event::EVT_BUTTON( $self, $self->{Ctl_Media_Open_Btn}, \&on_me +dia_load ); $self->{Ctl_Media_OpenURI_Btn} = Wx::Button-> new($loc_post_exam_v +ideos_panel, wxID_ANY, "Camera"); $self->{Ctl_Media_OpenURI_Btn}->Show(1); # Set to 1 + or zero depending on whether you are debugging or not. $self->{Ctl_Media_OpenURI_Btn}->SetToolTipString(("Press to open p +revious clip. Clip is saved in media folder.")); $self->{Ctl_Media_OpenURI_Btn}->SetSize($self->{Ctl_Media_OpenURI_ +Btn}->GetBestSize()); $self->{Ctl_Media_Button_Szr}->Add($self->{Ctl_Media_OpenURI_Btn}, + 0, 0, 2); Wx::Event::EVT_BUTTON( $self, $self->{Ctl_Media_OpenURI_Btn}, \&on +_media_loadURI ); $self->{Ctl_Post_Exam_Videos_Sizer_2}->Add($self->{Ctl_Media_Slide +r_Szr}, 0, wxALL|wxEXPAND, 5); $self->{Ctl_Post_Exam_Videos_Sizer_2}->Add($self->{Ctl_Media_Butto +n_Szr}, 0, wxALL|wxEXPAND, 5); $self->{Ctl_Videos_Log}= Wx::LogWindow->new( $self, 'Log', 1,1 ); $self->SetSizer($self->{Ctl_Post_Exam_Videos_Sizer_2}); $self->Layout(); Wx::Event::EVT_MEDIA_LOADED( $self, $self->{Ctl_Videos_Media}, \&o +n_media_loaded ); return $self; } sub on_media_loaded { my( $self, $event ) = @_; $self->{Ctl_Videos_Media}->Play; on_media_play(@_); } sub on_media_ff { # # subroutine to update slider control # my( $i_frame, $event ) = @_; my $loc_bcur = Wx::BusyCursor->new; # C +reate hourglass within current scope. Hourglass is deleted on exit. my $loc_new_value = $i_frame->{Ctl_Videos_Media}->Tell()+30000; $i_frame->{Ctl_Media_Slider_Sld}->SetValue($loc_new_value/1000); + # Set slider Move forwards 30 seconds. $i_frame->{Ctl_Videos_Media}->Seek($loc_new_value, wxFromStart); my $time_in_secs = Wx::Slider::GetValue($i_frame->{Ctl_Media_Slide +r_Sld}); my $length_in_secs=($i_frame->{Ctl_Videos_Media}->Length())/1000; + # Only works after a 'play' command. my $ss = $length_in_secs % 60; if (length($ss) == 1) {$ss = "0" . $ss} # z +erp pad seconds my $loc_length_hhhss = int($length_in_secs / 60) . ":" . $ss ; $ss = $time_in_secs % 60; if (length($ss) == 1) {$ss = "0" . $ss} # z +erp pad seconds my $loc_time_hhhss = int($time_in_secs / 60) . ":" . $ss ; $i_frame->{Ctl_Media_Slider_End_Lbl}->SetLabel(" ".$loc_time_hhhss +."/".$loc_length_hhhss); # Set max video length in mm:ss. } sub on_media_rw { # # subroutine to update slider control # my( $i_frame, $event ) = @_; my $loc_bcur = Wx::BusyCursor->new; # C +reate hourglass within current scope. Hourglass is deleted on exit. my $loc_new_value = $i_frame->{Ctl_Videos_Media}->Tell()-30000; if (defined $i_frame->{mediafile_clip_start}){ if ($i_frame->{mediafile_clip_start} ne ''){ if($loc_new_value < ($i_frame->{mediafile_clip_start}) * 1 +000){ # Rewind can't precede record start during clip record. $loc_new_value =$i_frame->{mediafile_clip_start} * 100 +0; } } } if ($loc_new_value<0) {$loc_new_value=0} # If n +egative, set to beginning of video $i_frame->{Ctl_Media_Slider_Sld}->SetValue($loc_new_value/1000); + # Set slider to move backwards 30 seconds. $i_frame->{Ctl_Videos_Media}->Seek($loc_new_value, wxFromStart); + # Set media to move backwards 30 seconds. my $time_in_secs = Wx::Slider::GetValue($i_frame->{Ctl_Media_Slide +r_Sld}); my $length_in_secs=($i_frame->{Ctl_Videos_Media}->Length())/1000; + # Only works after a 'play' command. my $ss = $length_in_secs % 60; if (length($ss) == 1) {$ss = "0" . $ss} # z +erp pad seconds my $loc_length_hhhss = int($length_in_secs / 60) . ":" . $ss ; $ss = $time_in_secs % 60; if (length($ss) == 1) {$ss = "0" . $ss} # z +erp pad seconds my $loc_time_hhhss = int($time_in_secs / 60) . ":" . $ss ; $i_frame->{Ctl_Media_Slider_End_Lbl}->SetLabel(" ".$loc_time_hhhss +."/".$loc_length_hhhss); # Set max video length in mm:ss. } sub on_slider { # # subroutine to update slider control # my( $i_frame, $event ) = @_; my $time_in_secs = Wx::Slider::GetValue($i_frame->{Ctl_Media_Slide +r_Sld}); if (defined $i_frame->{mediafile_clip_start}){ if ($i_frame->{mediafile_clip_start} ne ''){ if($time_in_secs < $i_frame->{mediafile_clip_start}){ + # Slider can't precede record start during clip record. $time_in_secs =$i_frame->{mediafile_clip_start}; } } } $i_frame->{Ctl_Videos_Media}->Seek($time_in_secs*1000, wxFromStart +); # Set video to slider position in msecs. my $length_in_secs=($i_frame->{Ctl_Videos_Media}->Length())/1000; + # Only works after a 'play' command. my $ss = $length_in_secs % 60; if (length($ss) == 1) {$ss = "0" . $ss} # z +ero pad seconds my $loc_length_hhhss = int($length_in_secs / 60) . ":" . $ss ; $ss = $time_in_secs % 60; if (length($ss) == 1) {$ss = "0" . $ss} # z +ero pad seconds my $loc_time_hhhss = int($time_in_secs / 60) . ":" . $ss ; $i_frame->{Ctl_Media_Slider_End_Lbl}->SetLabel(" ".$loc_time_hhhss +."/".$loc_length_hhhss); # Set max video length in mm:ss. } sub on_media_play { my( $i_frame, $event ) = @_; $i_frame->{Ctl_Videos_Media}->Play; my $length_in_secs=($i_frame->{Ctl_Videos_Media}->Length())/1000; + # Only works after a 'play' command. $i_frame->{mediafile_length}= $length_in_secs ; + # Store length of video in '$i_frame' in secs $length_in_secs = int($length_in_secs); # R +ound length to display correctly $i_frame->{Ctl_Media_Slider_Sld}->SetRange(0,$length_in_secs); + # Set max video length in secs. my $ss = $length_in_secs % 60; if (length($ss) == 1) {$ss = "0" . $ss} # z +erp pad seconds my $hhss = int($length_in_secs / 60) . ":" . $ss ; $i_frame->{Ctl_Media_Slider_End_Lbl}->SetLabel("0/".$hhss); + # Set max video length in mm:ss. if (not defined $i_frame->{mediafile_clip_start}){ $i_frame->{mediafile_clip_start}=""; # Set +clip start. } if (not defined $i_frame->{mediafile_clip_end}){ $i_frame->{mediafile_clip_end}=""; # Se +t clip end. } $i_frame->{Ctl_Media_Button_Szr}->Layout(); } sub on_media_load { # # Load file button selected # my( $i_frame, $event ) = @_; #my $file = '/usr/bin/gst-launch-0.10 v4l2src ! tee name=videoout +! queue ! videorate ! video/x-raw-yuv,fps=15 ! queue ! theoraenc qual +ity=60 ! queue ! muxout. oggmux name=muxout ! filesink location=lulz. +ogg videoout. ! queue ! ffmpegcolorspace ! ximagesink'; my $file = Wx::FileSelector('Choose a media file'); + # Select video file if( length( $file ) ) { my $false = $i_frame->{Ctl_Videos_Media}->LoadFile ($file); + # Load video file print $false,"\n"; #print $i_frame->{Ctl_Videos_Media}->LoadURI ('file:///dev/vid +eo0'); # Load video file $i_frame->{mediafile}= $file; # Store l +ocation of video file in '$i_frame } $i_frame->{mediafile_clip_start}=""; # Set +clip start. $i_frame->{mediafile_clip_end}=""; # Set cl +ip end. } sub on_media_loadURI { # # Load file button selected # my( $i_frame, $event ) = @_; my $file = 'file:///dev/video0'; # Select v +ideo source my $false = $i_frame->{Ctl_Videos_Media}->LoadURI ($file); +# Load video source print $false,"\n"; $i_frame->{mediafile}= $file; # Store locat +ion of video source in '$i_frame $i_frame->{mediafile_clip_start}=""; # Set +clip start. $i_frame->{mediafile_clip_end}=""; # Set cl +ip end. } sub on_media_pause { my( $i_frame, $event ) = @_; my $time_in_msecs; my $time_in_secs; $i_frame->{Ctl_Videos_Media}->Pause(); $time_in_msecs=$i_frame->{Ctl_Videos_Media}->Tell(); $time_in_secs=$time_in_msecs/1000; $i_frame->{Ctl_Media_Button_Szr}->Layout(); } sub on_media_stop { my( $i_frame, $event ) = @_; $i_frame->{Ctl_Videos_Media}->Stop; } sub on_timer { # # subroutine to perform periodic processing # my( $i_frame, $event ) = @_; my $time_in_msecs; my $time_in_secs; if (defined $i_frame->{Ctl_Media_Snap_Time} ){ # and $gl_media_con +trol_available == 1){ if ($i_frame->{Ctl_Media_Snap_Time} ne ""){ $time_in_msecs=$i_frame->{Ctl_Videos_Media}->Play(); + # Restarts playback. $i_frame->{Ctl_Media_Snap_Time}=""; # Clear +s snap time of photo } } ######## update slider control position ############################## +################### $time_in_msecs=$i_frame->{Ctl_Videos_Media}->Tell(); + # Obtains the current position in time within the movie in millisec +onds. $time_in_secs=$time_in_msecs/1000; #print $time_in_secs; $i_frame->{Ctl_Media_Slider_Sld}->SetValue($time_in_secs); + # Set slider to video position in secs. my $length_in_secs=($i_frame->{Ctl_Videos_Media}->Length())/1000; + # Only works after a 'play' command. my $ss = $length_in_secs % 60; if (length($ss) == 1) {$ss = "0" . $ss} # zero- +pad seconds my $loc_length_hhhss = int($length_in_secs / 60) . ":" . $ss ; $ss = $time_in_secs % 60; if (length($ss) == 1) {$ss = "0" . $ss} # zerp +pad seconds my $loc_time_hhhss = int($time_in_secs / 60) . ":" . $ss ; $i_frame->{Ctl_Media_Slider_End_Lbl}->SetLabel(" ".$loc_time_hhhss +."/".$loc_length_hhhss); # Set max video length in mm:ss. } package main; unless(caller){ local *Wx::App::OnInit = sub{1}; my $app = Wx::App->new(); Wx::InitAllImageHandlers(); my $frame_1 = MyFrame->new(); $app->SetTopWindow($frame_1); $frame_1->Show(1); $app->MainLoop(); }
|
|---|