UAV-Pilot-SDL
view release on metacpan or search on metacpan
lib/UAV/Pilot/SDL/Video.pm view on Meta::CPAN
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
package UAV::Pilot::SDL::Video;
use v5.14;
use Moose;
use namespace::autoclean;
use SDL;
use SDLx::Text;
use SDL::Event;
use SDL::Events;
use SDL::Video qw{ :surface :video };
use SDL::Overlay;
use Time::HiRes ();
use UAV::Pilot::SDL::VideoOverlay;
require DynaLoader;
our @ISA = qw(DynaLoader);
bootstrap UAV::Pilot::SDL::Video;
with 'UAV::Pilot::Logger';
use constant {
SDL_WIDTH => 640,
SDL_HEIGHT => 360,
SDL_OVERLAY_FLAG => SDL_YV12_OVERLAY,
#SDL_OVERLAY_FLAG => SDL_IYUV_OVERLAY,
#SDL_OVERLAY_FLAG => SDL_YUY2_OVERLAY,
#SDL_OVERLAY_FLAG => SDL_UYVY_OVERLAY,
#SDL_OVERLAY_FLAG => SDL_YVYU_OVERLAY,
#SDL_OVERLAY_FLAG => SDL_YVYU_OVERLAY,
BG_COLOR => [ 0, 255, 0 ],
};
with 'UAV::Pilot::Video::RawHandler';
has '_last_vid_frame' => (
is => 'rw',
isa => 'Maybe[UAV::Pilot::Video::H264Decoder]',
);
has 'frames_processed' => (
traits => ['Number'],
is => 'ro',
isa => 'Int',
default => 0,
handles => {
'_add_frames_processed' => 'add',
},
);
has '_bg_rect' => (
is => 'ro',
isa => 'SDL::Rect',
writer => '_set_bg_rect',
);
has '_bg_color' => (
is => 'rw',
);
has 'video_overlays' => (
is => 'ro',
isa => 'ArrayRef[UAV::Pilot::SDL::VideoOverlay]',
default => sub {[]},
traits => [ 'Array' ],
handles => {
_add_video_overlay => 'push',
},
);
with 'UAV::Pilot::SDL::WindowEventHandler';
sub BUILDARGS
{
my ($class, $args) = @_;
$$args{width} = $class->SDL_WIDTH;
$$args{height} = $class->SDL_HEIGHT;
return $args;
}
sub add_to_window
{
my ($self, $window, $location) = @_;
$location //= $window->TOP;
$window->add_child_with_yuv_overlay( $self,
$self->SDL_OVERLAY_FLAG, $location );
my @bg_color_parts = @{ $self->BG_COLOR };
my $sdl = $window->sdl;
my $bg_color = SDL::Video::map_RGB( $sdl->format, @bg_color_parts );
$self->_bg_color( $bg_color );
return 1;
}
sub update_window_rect
{
# Do nothing, since YUV overlay updates the area for us
return 1;
}
sub process_raw_frame
{
my ($self, $width, $height, $decoder) = @_;
if( ($width != $self->width) || ($height != $self->height) ) {
# TODO Ignore until we have a way of informing
# UAV::Pilot::SDL::Window of the change
#$self->_set_width_height( $width, $height );
}
$self->_last_vid_frame( $decoder );
$self->_add_frames_processed( 1 );
return 1;
}
sub draw
{
my ($self, $window) = @_;
my $last_vid_frame = $self->_last_vid_frame;
return 1 unless defined $last_vid_frame;
my $bg_rect = $window->yuv_overlay_rect;
my $sdl_overlay = $window->yuv_overlay;
SDL::Video::fill_rect(
$window->sdl,
$bg_rect,
$self->_bg_color,
);
$self->_draw_last_video_frame(
$sdl_overlay,
$bg_rect,
$last_vid_frame->get_last_frame_c_obj,
);
my @overlays = @{ $self->video_overlays };
if( @overlays ) {
foreach my $overlay (@overlays) {
$overlay->process_video_overlay( $window );
}
SDL::Video::update_rects( $window->sdl, $bg_rect );
}
$self->_logger->info( 'VIDEO_FRAME_TIMER,DISPLAY,'
. $self->frames_processed
. ',' . join( ',', Time::HiRes::gettimeofday ) );
return 1;
}
sub register_video_overlay
{
my ($self, $overlay, $window) = @_;
$overlay->init_video_overlay( $self, $window );
$self->_add_video_overlay( $overlay );
return 1;
}
sub _set_width_height
{
my ($self, $width, $height) = @_;
# TODO inform UAV::Pilot::SDL::Window of size change
my $sdl = $self->sdl_app;
$sdl->resize( $width, $height );
my $bg_rect = SDL::Rect->new( 0, 0, $width, $height );
my $sdl_overlay = SDL::Overlay->new( $width, $height, $self->SDL_OVERLAY_FLAG, $sdl );
$self->_set_bg_rect( $bg_rect );
$self->_set_sdl_overlay( $sdl_overlay );
$self->_set_width( $width );
$self->_set_height( $height );
return 1;
}
no Moose;
__PACKAGE__->meta->make_immutable;
1;
__END__
=head1 NAME
UAV::Pilot::SDL::Video
=head1 SYNOPSIS
my $cv = AnyEvent->condvar;
my $events = UAV::Pilot::Events->new({
condvar => $cv,
});
my $window = UAV::Pilot::SDL::Window->new;
my $display = UAV::Pilot::SDL::Video->new({
window => $window,
});
my $video = UAV::Pilot::Video::H264Decoder->new({
display => $display,
});
$events->register( $display );
=head1 DESCRIPTION
Process raw video frames and displays them to an SDL surface. This does the roles
C<UAV::Pilot::Video::RawHandler> and C<UAV::Pilot::EventHandler>.
=head1 METHODS
=head1 register_video_overlay
register_video_overlay( $overlay )
Adds an object that does the C<UAV::Pilot::SDL::VideoOverlay> role. This allows an
object to draw things on top of the video, like telemetry information.
Not to be confused with C<SDL::Overlay>.
=cut
( run in 1.296 second using v1.01-cache-2.11-cpan-98e64b0badf )